diff options
Diffstat (limited to 'firmware/target/arm/sandisk/sansa-e200/ata-e200.c')
-rw-r--r-- | firmware/target/arm/sandisk/sansa-e200/ata-e200.c | 562 |
1 files changed, 361 insertions, 201 deletions
diff --git a/firmware/target/arm/sandisk/sansa-e200/ata-e200.c b/firmware/target/arm/sandisk/sansa-e200/ata-e200.c index ca8cc1b3d9..1b67454445 100644 --- a/firmware/target/arm/sandisk/sansa-e200/ata-e200.c +++ b/firmware/target/arm/sandisk/sansa-e200/ata-e200.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "disk.h" | 27 | #include "disk.h" |
28 | #include "pp5024.h" | 28 | #include "pp5024.h" |
29 | #include "panic.h" | 29 | #include "panic.h" |
30 | #include "usb.h" | ||
30 | 31 | ||
31 | #define BLOCK_SIZE (512) | 32 | #define BLOCK_SIZE (512) |
32 | #define SECTOR_SIZE (512) | 33 | #define SECTOR_SIZE (512) |
@@ -69,7 +70,7 @@ | |||
69 | #define PRG 7 | 70 | #define PRG 7 |
70 | #define DIS 8 | 71 | #define DIS 8 |
71 | 72 | ||
72 | #define FIFO_SIZE 16 /* FIFO is 16 words deep */ | 73 | #define FIFO_LEN 16 /* FIFO is 16 words deep */ |
73 | 74 | ||
74 | /* SD Commands */ | 75 | /* SD Commands */ |
75 | #define GO_IDLE_STATE 0 | 76 | #define GO_IDLE_STATE 0 |
@@ -95,38 +96,59 @@ | |||
95 | #define ERASE 38 | 96 | #define ERASE 38 |
96 | #define APP_CMD 55 | 97 | #define APP_CMD 55 |
97 | 98 | ||
98 | #define EC_POWER_UP 1 /* error code */ | 99 | #define EC_OK 0 |
99 | #define EC_READ_TIMEOUT 2 /* error code */ | 100 | #define EC_FAILED 1 |
100 | #define EC_WRITE_TIMEOUT 3 /* error code */ | 101 | #define EC_NOCARD 2 |
101 | #define EC_TRAN_SEL_BANK 4 /* error code */ | 102 | #define EC_WAIT_STATE_FAILED 3 |
102 | #define EC_TRAN_READ_ENTRY 5 /* error code */ | 103 | #define EC_CHECK_TIMEOUT_FAILED 4 |
103 | #define EC_TRAN_READ_EXIT 6 /* error code */ | 104 | #define EC_POWER_UP 5 |
104 | #define EC_TRAN_WRITE_ENTRY 7 /* error code */ | 105 | #define EC_READ_TIMEOUT 6 |
105 | #define EC_TRAN_WRITE_EXIT 8 /* error code */ | 106 | #define EC_WRITE_TIMEOUT 7 |
106 | #define DO_PANIC 32 /* marker */ | 107 | #define EC_TRAN_SEL_BANK 8 |
107 | #define NO_PANIC 0 /* marker */ | 108 | #define EC_TRAN_READ_ENTRY 9 |
108 | #define EC_COMMAND 10 /* error code */ | 109 | #define EC_TRAN_READ_EXIT 10 |
109 | #define EC_FIFO_SEL_BANK_EMPTY 11 /* error code */ | 110 | #define EC_TRAN_WRITE_ENTRY 11 |
110 | #define EC_FIFO_SEL_BANK_DONE 12 /* error code */ | 111 | #define EC_TRAN_WRITE_EXIT 12 |
111 | #define EC_FIFO_ENA_BANK_EMPTY 13 /* error code */ | 112 | #define EC_FIFO_SEL_BANK_EMPTY 13 |
112 | #define EC_FIFO_READ_FULL 14 /* error code */ | 113 | #define EC_FIFO_SEL_BANK_DONE 14 |
113 | #define EC_FIFO_WR_EMPTY 15 /* error code */ | 114 | #define EC_FIFO_ENA_BANK_EMPTY 15 |
114 | #define EC_FIFO_WR_DONE 16 /* error code */ | 115 | #define EC_FIFO_READ_FULL 16 |
116 | #define EC_FIFO_WR_EMPTY 17 | ||
117 | #define EC_FIFO_WR_DONE 18 | ||
118 | #define EC_COMMAND 19 | ||
119 | #define NUM_EC 20 | ||
115 | 120 | ||
116 | /* Application Specific commands */ | 121 | /* Application Specific commands */ |
117 | #define SET_BUS_WIDTH 6 | 122 | #define SET_BUS_WIDTH 6 |
118 | #define SD_APP_OP_COND 41 | 123 | #define SD_APP_OP_COND 41 |
119 | 124 | ||
125 | /** global, exported variables **/ | ||
126 | |||
120 | /* for compatibility */ | 127 | /* for compatibility */ |
121 | int ata_spinup_time = 0; | 128 | int ata_spinup_time = 0; |
122 | 129 | ||
123 | long last_disk_activity = -1; | 130 | long last_disk_activity = -1; |
124 | 131 | ||
132 | /** static, private data **/ | ||
125 | static bool initialized = false; | 133 | static bool initialized = false; |
126 | static int sd1_status = 0x00; /* 0x00:inserted, 0x80:not inserted */ | 134 | |
135 | static long next_yield = 0; | ||
136 | #define MIN_YIELD_PERIOD 2000 | ||
127 | 137 | ||
128 | static tSDCardInfo card_info[2]; | 138 | static tSDCardInfo card_info[2]; |
129 | static tSDCardInfo *currcard; /* current active card */ | 139 | static tSDCardInfo *currcard = NULL; /* current active card */ |
140 | |||
141 | struct sd_card_status | ||
142 | { | ||
143 | int retry; | ||
144 | int retry_max; | ||
145 | }; | ||
146 | |||
147 | static struct sd_card_status sd_status[2] = | ||
148 | { | ||
149 | { 0, 1 }, | ||
150 | { 0, 10 } | ||
151 | }; | ||
130 | 152 | ||
131 | /* Shoot for around 75% usage */ | 153 | /* Shoot for around 75% usage */ |
132 | static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x1c0)/sizeof(long)]; | 154 | static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x1c0)/sizeof(long)]; |
@@ -136,38 +158,48 @@ static struct event_queue sd_queue; | |||
136 | 158 | ||
137 | /* Posted when card plugged status has changed */ | 159 | /* Posted when card plugged status has changed */ |
138 | #define SD_HOTSWAP 1 | 160 | #define SD_HOTSWAP 1 |
161 | /* Actions taken by sd_thread when card status has changed */ | ||
162 | enum sd_thread_actions | ||
163 | { | ||
164 | SDA_NONE = 0x0, | ||
165 | SDA_UNMOUNTED = 0x1, | ||
166 | SDA_MOUNTED = 0x2 | ||
167 | }; | ||
139 | 168 | ||
140 | /* Private Functions */ | 169 | /* Private Functions */ |
141 | 170 | ||
142 | static unsigned int check_time[10]; | 171 | static unsigned int check_time[NUM_EC]; |
143 | 172 | ||
144 | static inline void sd_check_timeout(unsigned int timeout, int id) | 173 | static inline bool sd_check_timeout(long timeout, int id) |
145 | { | 174 | { |
146 | if (USEC_TIMER > check_time[id] + timeout) | 175 | return !TIME_AFTER(USEC_TIMER, check_time[id] + timeout); |
147 | panicf("Error SDCard: %d", id); | ||
148 | } | 176 | } |
149 | 177 | ||
150 | static inline bool sd_poll_status(unsigned int trigger, unsigned int timeout, | 178 | static bool sd_poll_status(unsigned int trigger, long timeout) |
151 | int id) | ||
152 | { | 179 | { |
153 | unsigned int t = USEC_TIMER; | 180 | long t = USEC_TIMER; |
154 | 181 | ||
155 | while ((STATUS_REG & trigger) == 0) | 182 | while ((STATUS_REG & trigger) == 0) |
156 | { | 183 | { |
157 | if (USEC_TIMER > t + timeout) | 184 | long time = USEC_TIMER; |
185 | |||
186 | if (TIME_AFTER(time, next_yield)) | ||
158 | { | 187 | { |
159 | if(id & DO_PANIC) | 188 | long ty = USEC_TIMER; |
160 | panicf("Error SDCard: %d", id & 31); | 189 | priority_yield(); |
190 | timeout += USEC_TIMER - ty; | ||
191 | next_yield = ty + MIN_YIELD_PERIOD; | ||
192 | } | ||
161 | 193 | ||
194 | if (TIME_AFTER(time, t + timeout)) | ||
162 | return false; | 195 | return false; |
163 | } | ||
164 | } | 196 | } |
165 | 197 | ||
166 | return true; | 198 | return true; |
167 | } | 199 | } |
168 | 200 | ||
169 | static bool sd_command(unsigned int cmd, unsigned long arg1, | 201 | static int sd_command(unsigned int cmd, unsigned long arg1, |
170 | unsigned int *response, unsigned int type) | 202 | unsigned int *response, unsigned int type) |
171 | { | 203 | { |
172 | int i, words; /* Number of 16 bit words to read from RESPONSE_REG */ | 204 | int i, words; /* Number of 16 bit words to read from RESPONSE_REG */ |
173 | unsigned int data[9]; | 205 | unsigned int data[9]; |
@@ -177,22 +209,26 @@ static bool sd_command(unsigned int cmd, unsigned long arg1, | |||
177 | CMD_REG2 = (unsigned int)((arg1 & 0xffff)); | 209 | CMD_REG2 = (unsigned int)((arg1 & 0xffff)); |
178 | UNKNOWN = type; | 210 | UNKNOWN = type; |
179 | 211 | ||
180 | sd_poll_status(CMD_DONE, 100000, EC_COMMAND | DO_PANIC); | 212 | if (!sd_poll_status(CMD_DONE, 100000)) |
213 | return -EC_COMMAND; | ||
181 | 214 | ||
182 | if ((STATUS_REG & ERROR_BITS) != CMD_OK) | 215 | if ((STATUS_REG & ERROR_BITS) != CMD_OK) |
183 | return false; /* Error sending command */ | 216 | /* Error sending command */ |
217 | return -EC_COMMAND - (STATUS_REG & ERROR_BITS)*100; | ||
184 | 218 | ||
185 | if (cmd == GO_IDLE_STATE) | 219 | if (cmd == GO_IDLE_STATE) |
186 | return true; /* no response here */ | 220 | return 0; /* no response here */ |
187 | 221 | ||
188 | words = (type == 2) ? 9 : 3; | 222 | words = (type == 2) ? 9 : 3; |
189 | 223 | ||
190 | for (i = 0; i < words; i++) /* RESPONSE_REG is read MSB first */ | 224 | for (i = 0; i < words; i++) /* RESPONSE_REG is read MSB first */ |
191 | { | ||
192 | data[i] = RESPONSE_REG; /* Read most significant 16-bit word */ | 225 | data[i] = RESPONSE_REG; /* Read most significant 16-bit word */ |
193 | } | ||
194 | 226 | ||
195 | if (type == 2) | 227 | if (response == NULL) |
228 | { | ||
229 | /* response discarded */ | ||
230 | } | ||
231 | else if (type == 2) | ||
196 | { | 232 | { |
197 | /* Response type 2 has the following structure: | 233 | /* Response type 2 has the following structure: |
198 | * [135:135] Start Bit - '0' | 234 | * [135:135] Start Bit - '0' |
@@ -201,10 +237,10 @@ static bool sd_command(unsigned int cmd, unsigned long arg1, | |||
201 | * [127:001] CID or CSD register including internal CRC7 | 237 | * [127:001] CID or CSD register including internal CRC7 |
202 | * [000:000] End Bit - '1' | 238 | * [000:000] End Bit - '1' |
203 | */ | 239 | */ |
204 | response[3] = (data[0]<<24) + (data[1]<<8) + ((data[2]&0xff00)>>8); | 240 | response[3] = (data[0]<<24) + (data[1]<<8) + (data[2]>>8); |
205 | response[2] = (data[2]<<24) + (data[3]<<8) + ((data[4]&0xff00)>>8); | 241 | response[2] = (data[2]<<24) + (data[3]<<8) + (data[4]>>8); |
206 | response[1] = (data[4]<<24) + (data[5]<<8) + ((data[6]&0xff00)>>8); | 242 | response[1] = (data[4]<<24) + (data[5]<<8) + (data[6]>>8); |
207 | response[0] = (data[6]<<24) + (data[7]<<8) + ((data[8]&0xff00)>>8); | 243 | response[0] = (data[6]<<24) + (data[7]<<8) + (data[8]>>8); |
208 | } | 244 | } |
209 | else | 245 | else |
210 | { | 246 | { |
@@ -234,30 +270,44 @@ static bool sd_command(unsigned int cmd, unsigned long arg1, | |||
234 | * R3: Reserved - '1111111' | 270 | * R3: Reserved - '1111111' |
235 | * [0] End Bit - '1' | 271 | * [0] End Bit - '1' |
236 | */ | 272 | */ |
237 | response[0] = (data[0]<<24) + (data[1]<<8) + ((data[2]&0xff00)>>8); | 273 | response[0] = (data[0]<<24) + (data[1]<<8) + (data[2]>>8); |
238 | } | 274 | } |
239 | 275 | ||
240 | return true; | 276 | return 0; |
241 | } | 277 | } |
242 | 278 | ||
243 | static void sd_wait_for_state(unsigned int state, unsigned int id) | 279 | static int sd_wait_for_state(unsigned int state, int id) |
244 | { | 280 | { |
245 | unsigned int response = 0; | 281 | unsigned int response = 0; |
282 | unsigned int timeout = 0x80000; | ||
246 | 283 | ||
247 | check_time[id] = USEC_TIMER; | 284 | check_time[id] = USEC_TIMER; |
248 | 285 | ||
249 | while (1) | 286 | while (1) |
250 | { | 287 | { |
251 | sd_command(SEND_STATUS, currcard->rca, &response, 1); | 288 | int ret = sd_command(SEND_STATUS, currcard->rca, &response, 1); |
252 | sd_check_timeout(0x80000, id); | 289 | long us; |
290 | |||
291 | if (ret < 0) | ||
292 | return ret*100 - id; | ||
253 | 293 | ||
254 | if (((response >> 9) & 0xf) == state) | 294 | if (((response >> 9) & 0xf) == state) |
255 | break; | 295 | { |
296 | SD_STATE_REG = state; | ||
297 | return 0; | ||
298 | } | ||
256 | 299 | ||
257 | priority_yield(); | 300 | if (!sd_check_timeout(timeout, id)) |
258 | } | 301 | return -EC_WAIT_STATE_FAILED*100 - id; |
259 | 302 | ||
260 | SD_STATE_REG = state; | 303 | us = USEC_TIMER; |
304 | if (TIME_AFTER(us, next_yield)) | ||
305 | { | ||
306 | priority_yield(); | ||
307 | timeout += USEC_TIMER - us; | ||
308 | next_yield = us + MIN_YIELD_PERIOD; | ||
309 | } | ||
310 | } | ||
261 | } | 311 | } |
262 | 312 | ||
263 | static inline void copy_read_sectors_fast(unsigned char **buf) | 313 | static inline void copy_read_sectors_fast(unsigned char **buf) |
@@ -385,7 +435,7 @@ static inline void copy_read_sectors_fast(unsigned char **buf) | |||
385 | 435 | ||
386 | static inline void copy_read_sectors_slow(unsigned char** buf) | 436 | static inline void copy_read_sectors_slow(unsigned char** buf) |
387 | { | 437 | { |
388 | int cnt = FIFO_SIZE; | 438 | int cnt = FIFO_LEN; |
389 | int t; | 439 | int t; |
390 | 440 | ||
391 | /* Copy one chunk of 16 words */ | 441 | /* Copy one chunk of 16 words */ |
@@ -404,33 +454,37 @@ static inline void copy_read_sectors_slow(unsigned char** buf) | |||
404 | } | 454 | } |
405 | 455 | ||
406 | /* Writes have to be kept slow for now */ | 456 | /* Writes have to be kept slow for now */ |
407 | static inline void copy_write_sectors(const unsigned char* buf) | 457 | static inline void copy_write_sectors(const unsigned char** buf) |
408 | { | 458 | { |
409 | unsigned short tmp = 0; | 459 | int cnt = FIFO_LEN; |
410 | const unsigned char* bufend = buf + FIFO_SIZE*2; | 460 | unsigned t; |
411 | 461 | ||
412 | do | 462 | do |
413 | { | 463 | { |
414 | tmp = (unsigned short) *buf++; | 464 | t = *(*buf)++; |
415 | tmp |= (unsigned short) *buf++ << 8; | 465 | t |= *(*buf)++ << 8; |
416 | DATA_REG = tmp; | 466 | DATA_REG = t; |
417 | } while (buf < bufend); /* tail loop is faster */ | 467 | } while (--cnt > 0); /* tail loop is faster */ |
418 | } | 468 | } |
419 | 469 | ||
420 | static bool sd_select_bank(unsigned char bank) | 470 | static int sd_select_bank(unsigned char bank) |
421 | { | 471 | { |
422 | unsigned int response; | ||
423 | unsigned char card_data[512]; | 472 | unsigned char card_data[512]; |
424 | unsigned char* write_buf; | 473 | const unsigned char* write_buf; |
425 | int i; | 474 | int i, ret; |
426 | 475 | ||
427 | memset(card_data, 0, 512); | 476 | memset(card_data, 0, 512); |
428 | sd_wait_for_state(TRAN, EC_TRAN_SEL_BANK); | 477 | |
478 | ret = sd_wait_for_state(TRAN, EC_TRAN_SEL_BANK); | ||
479 | if (ret < 0) | ||
480 | return ret; | ||
481 | |||
429 | BLOCK_SIZE_REG = 512; | 482 | BLOCK_SIZE_REG = 512; |
430 | BLOCK_COUNT_REG = 1; | 483 | BLOCK_COUNT_REG = 1; |
431 | 484 | ||
432 | if (!sd_command(35, 0, &response, 0x1c0d)) /* CMD35 is vendor specific */ | 485 | ret = sd_command(35, 0, NULL, 0x1c0d); /* CMD35 is vendor specific */ |
433 | return false; | 486 | if (ret < 0) |
487 | return ret; | ||
434 | 488 | ||
435 | SD_STATE_REG = PRG; | 489 | SD_STATE_REG = PRG; |
436 | 490 | ||
@@ -438,41 +492,29 @@ static bool sd_select_bank(unsigned char bank) | |||
438 | 492 | ||
439 | /* Write the card data */ | 493 | /* Write the card data */ |
440 | write_buf = card_data; | 494 | write_buf = card_data; |
441 | for (i = 0; i < BLOCK_SIZE / 2; i += FIFO_SIZE) | 495 | for (i = 0; i < BLOCK_SIZE/2; i += FIFO_LEN) |
442 | { | 496 | { |
443 | /* Wait for the FIFO to empty */ | 497 | /* Wait for the FIFO to empty */ |
444 | sd_poll_status(FIFO_EMPTY, 10000, EC_FIFO_SEL_BANK_EMPTY | DO_PANIC); | 498 | if (sd_poll_status(FIFO_EMPTY, 10000)) |
445 | 499 | { | |
446 | copy_write_sectors(write_buf); /* Copy one chunk of 16 words */ | 500 | copy_write_sectors(&write_buf); /* Copy one chunk of 16 words */ |
501 | continue; | ||
502 | } | ||
447 | 503 | ||
448 | write_buf += FIFO_SIZE*2; /* Advance one chunk of 16 words */ | 504 | return -EC_FIFO_SEL_BANK_EMPTY; |
449 | } | 505 | } |
450 | 506 | ||
451 | sd_poll_status(DATA_DONE, 10000, EC_FIFO_SEL_BANK_DONE | DO_PANIC); | 507 | if (!sd_poll_status(DATA_DONE, 10000)) |
508 | return -EC_FIFO_SEL_BANK_DONE; | ||
452 | 509 | ||
453 | currcard->current_bank = bank; | 510 | currcard->current_bank = bank; |
454 | 511 | ||
455 | return true; | 512 | return 0; |
456 | } | 513 | } |
457 | 514 | ||
458 | /* lock must already be aquired */ | 515 | static void sd_card_mux(int card_no) |
459 | static void sd_init_device(int card_no) | ||
460 | { | 516 | { |
461 | /* SD Protocol registers */ | 517 | /* Set the current card mux */ |
462 | unsigned int i, dummy; | ||
463 | unsigned int c_size = 0; | ||
464 | unsigned long c_mult = 0; | ||
465 | unsigned char carddata[512]; | ||
466 | unsigned char *dataptr; | ||
467 | |||
468 | /* Enable and initialise controller */ | ||
469 | REG_1 = 6; | ||
470 | |||
471 | currcard = &card_info[card_no]; | ||
472 | |||
473 | /* Initialise card data as blank */ | ||
474 | memset(currcard, 0, sizeof(*currcard)); | ||
475 | |||
476 | if (card_no == 0) | 518 | if (card_no == 0) |
477 | { | 519 | { |
478 | outl(inl(0x70000080) | 0x4, 0x70000080); | 520 | outl(inl(0x70000080) | 0x4, 0x70000080); |
@@ -497,8 +539,28 @@ static void sd_init_device(int card_no) | |||
497 | 539 | ||
498 | outl(inl(0x70000014) & ~(0x3ffff), 0x70000014); | 540 | outl(inl(0x70000014) & ~(0x3ffff), 0x70000014); |
499 | } | 541 | } |
542 | } | ||
543 | |||
544 | static void sd_init_device(int card_no) | ||
545 | { | ||
546 | /* SD Protocol registers */ | ||
547 | unsigned int i; | ||
548 | unsigned int c_size; | ||
549 | unsigned long c_mult; | ||
550 | unsigned char carddata[512]; | ||
551 | unsigned char *dataptr; | ||
552 | int ret; | ||
553 | |||
554 | /* Enable and initialise controller */ | ||
555 | REG_1 = 6; | ||
556 | |||
557 | /* Initialise card data as blank */ | ||
558 | memset(currcard, 0, sizeof(*currcard)); | ||
559 | |||
560 | /* Switch card mux to card to initialize */ | ||
561 | sd_card_mux(card_no); | ||
500 | 562 | ||
501 | /* Init NAND */ | 563 | /* Init NAND */ |
502 | REG_11 |= (1 << 15); | 564 | REG_11 |= (1 << 15); |
503 | REG_12 |= (1 << 15); | 565 | REG_12 |= (1 << 15); |
504 | REG_12 &= ~(3 << 12); | 566 | REG_12 &= ~(3 << 12); |
@@ -514,28 +576,38 @@ static void sd_init_device(int card_no) | |||
514 | 576 | ||
515 | REG_5 = 0xf; | 577 | REG_5 = 0xf; |
516 | 578 | ||
517 | if (!sd_command(GO_IDLE_STATE, 0, &dummy, 256)) | 579 | ret = sd_command(GO_IDLE_STATE, 0, NULL, 256); |
580 | if (ret < 0) | ||
518 | goto card_init_error; | 581 | goto card_init_error; |
519 | 582 | ||
520 | check_time[EC_POWER_UP] = USEC_TIMER; | 583 | check_time[EC_POWER_UP] = USEC_TIMER; |
521 | while ((currcard->ocr & (1 << 31)) == 0) /* until card is powered up */ | 584 | while ((currcard->ocr & (1 << 31)) == 0) /* until card is powered up */ |
522 | { | 585 | { |
523 | if (!sd_command(APP_CMD, currcard->rca, &dummy, 1)) | 586 | ret = sd_command(APP_CMD, currcard->rca, NULL, 1); |
587 | if (ret < 0) | ||
524 | goto card_init_error; | 588 | goto card_init_error; |
525 | 589 | ||
526 | if (!sd_command(SD_APP_OP_COND, 0x100000, &currcard->ocr, 3)) | 590 | ret = sd_command(SD_APP_OP_COND, 0x100000, &currcard->ocr, 3); |
591 | if (ret < 0) | ||
527 | goto card_init_error; | 592 | goto card_init_error; |
528 | 593 | ||
529 | sd_check_timeout(5000000, EC_POWER_UP); | 594 | if (!sd_check_timeout(5000000, EC_POWER_UP)) |
595 | { | ||
596 | ret = -EC_POWER_UP; | ||
597 | goto card_init_error; | ||
598 | } | ||
530 | } | 599 | } |
531 | 600 | ||
532 | if (!sd_command(ALL_SEND_CID, 0, currcard->cid, 2)) | 601 | ret = sd_command(ALL_SEND_CID, 0, currcard->cid, 2); |
602 | if (ret < 0) | ||
533 | goto card_init_error; | 603 | goto card_init_error; |
534 | 604 | ||
535 | if (!sd_command(SEND_RELATIVE_ADDR, 0, &currcard->rca, 1)) | 605 | ret = sd_command(SEND_RELATIVE_ADDR, 0, &currcard->rca, 1); |
606 | if (ret < 0) | ||
536 | goto card_init_error; | 607 | goto card_init_error; |
537 | 608 | ||
538 | if (!sd_command(SEND_CSD, currcard->rca, currcard->csd, 2)) | 609 | ret = sd_command(SEND_CSD, currcard->rca, currcard->csd, 2); |
610 | if (ret < 0) | ||
539 | goto card_init_error; | 611 | goto card_init_error; |
540 | 612 | ||
541 | /* These calculations come from the Sandisk SD card product manual */ | 613 | /* These calculations come from the Sandisk SD card product manual */ |
@@ -548,39 +620,49 @@ static void sd_init_device(int card_no) | |||
548 | 620 | ||
549 | REG_1 = 0; | 621 | REG_1 = 0; |
550 | 622 | ||
551 | if (!sd_command(SELECT_CARD, currcard->rca, &dummy, 129)) | 623 | ret = sd_command(SELECT_CARD, currcard->rca, NULL, 129); |
624 | if (ret < 0) | ||
552 | goto card_init_error; | 625 | goto card_init_error; |
553 | 626 | ||
554 | if (!sd_command(APP_CMD, currcard->rca, &dummy, 1)) | 627 | ret = sd_command(APP_CMD, currcard->rca, NULL, 1); |
628 | if (ret < 0) | ||
555 | goto card_init_error; | 629 | goto card_init_error; |
556 | 630 | ||
557 | if (!sd_command(SET_BUS_WIDTH, currcard->rca | 2, &dummy, 1)) /* 4 bit */ | 631 | ret = sd_command(SET_BUS_WIDTH, currcard->rca | 2, NULL, 1); /* 4 bit */ |
632 | if (ret < 0) | ||
558 | goto card_init_error; | 633 | goto card_init_error; |
559 | 634 | ||
560 | if (!sd_command(SET_BLOCKLEN, currcard->block_size, &dummy, 1)) | 635 | ret = sd_command(SET_BLOCKLEN, currcard->block_size, NULL, 1); |
636 | if (ret < 0) | ||
561 | goto card_init_error; | 637 | goto card_init_error; |
562 | 638 | ||
563 | BLOCK_SIZE_REG = currcard->block_size; | 639 | BLOCK_SIZE_REG = currcard->block_size; |
564 | 640 | ||
565 | /* If this card is > 4Gb, then we need to enable bank switching */ | 641 | /* If this card is > 4Gb, then we need to enable bank switching */ |
566 | if(currcard->numblocks >= BLOCKS_PER_BANK) | 642 | if (currcard->numblocks >= BLOCKS_PER_BANK) |
567 | { | 643 | { |
568 | SD_STATE_REG = TRAN; | 644 | SD_STATE_REG = TRAN; |
569 | BLOCK_COUNT_REG = 1; | 645 | BLOCK_COUNT_REG = 1; |
570 | 646 | ||
571 | if (!sd_command(SWITCH_FUNC, 0x80ffffef, &dummy, 0x1c05)) | 647 | ret = sd_command(SWITCH_FUNC, 0x80ffffef, NULL, 0x1c05); |
648 | if (ret < 0) | ||
572 | goto card_init_error; | 649 | goto card_init_error; |
573 | 650 | ||
574 | /* Read 512 bytes from the card. | 651 | /* Read 512 bytes from the card. |
575 | The first 512 bits contain the status information | 652 | The first 512 bits contain the status information |
576 | TODO: Do something useful with this! */ | 653 | TODO: Do something useful with this! */ |
577 | dataptr = carddata; | 654 | dataptr = carddata; |
578 | for (i = 0; i < BLOCK_SIZE / 2; i += FIFO_SIZE) | 655 | for (i = 0; i < BLOCK_SIZE/2; i += FIFO_LEN) |
579 | { | 656 | { |
580 | /* Wait for the FIFO to be full */ | 657 | /* Wait for the FIFO to be full */ |
581 | sd_poll_status(FIFO_FULL, 100000, | 658 | if (sd_poll_status(FIFO_FULL, 100000)) |
582 | EC_FIFO_ENA_BANK_EMPTY | DO_PANIC); | 659 | { |
583 | copy_read_sectors_slow(&dataptr); | 660 | copy_read_sectors_slow(&dataptr); |
661 | continue; | ||
662 | } | ||
663 | |||
664 | ret = -EC_FIFO_ENA_BANK_EMPTY; | ||
665 | goto card_init_error; | ||
584 | } | 666 | } |
585 | } | 667 | } |
586 | 668 | ||
@@ -589,7 +671,32 @@ static void sd_init_device(int card_no) | |||
589 | 671 | ||
590 | /* Card failed to initialize so disable it */ | 672 | /* Card failed to initialize so disable it */ |
591 | card_init_error: | 673 | card_init_error: |
592 | currcard->initialized = -1; | 674 | currcard->initialized = ret; |
675 | } | ||
676 | |||
677 | /* lock must already be aquired */ | ||
678 | static void sd_select_device(int card_no) | ||
679 | { | ||
680 | currcard = &card_info[card_no]; | ||
681 | |||
682 | if (card_no == 0) | ||
683 | { | ||
684 | /* Main card always gets a chance */ | ||
685 | sd_status[0].retry = 0; | ||
686 | } | ||
687 | |||
688 | if (currcard->initialized > 0) | ||
689 | { | ||
690 | /* This card is already initialized - switch to it */ | ||
691 | sd_card_mux(card_no); | ||
692 | return; | ||
693 | } | ||
694 | |||
695 | if (currcard->initialized == 0) | ||
696 | { | ||
697 | /* Card needs (re)init */ | ||
698 | sd_init_device(card_no); | ||
699 | } | ||
593 | } | 700 | } |
594 | 701 | ||
595 | /* API Functions */ | 702 | /* API Functions */ |
@@ -599,12 +706,11 @@ void ata_led(bool onoff) | |||
599 | led(onoff); | 706 | led(onoff); |
600 | } | 707 | } |
601 | 708 | ||
602 | int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int incount, | 709 | int ata_read_sectors(int drive, unsigned long start, int incount, |
603 | void* inbuf) | 710 | void* inbuf) |
604 | { | 711 | { |
605 | int ret = -9; | 712 | int ret; |
606 | unsigned char *buf, *buf_end; | 713 | unsigned char *buf, *buf_end; |
607 | unsigned int dummy; | ||
608 | int bank; | 714 | int bank; |
609 | 715 | ||
610 | /* TODO: Add DMA support. */ | 716 | /* TODO: Add DMA support. */ |
@@ -613,31 +719,43 @@ int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int incount, | |||
613 | 719 | ||
614 | ata_led(true); | 720 | ata_led(true); |
615 | 721 | ||
722 | ata_read_retry: | ||
616 | if (drive != 0 && (GPIOA_INPUT_VAL & 0x80) != 0) | 723 | if (drive != 0 && (GPIOA_INPUT_VAL & 0x80) != 0) |
724 | { | ||
617 | /* no external sd-card inserted */ | 725 | /* no external sd-card inserted */ |
726 | ret = -EC_NOCARD; | ||
618 | goto ata_read_error; | 727 | goto ata_read_error; |
728 | } | ||
619 | 729 | ||
620 | if (&card_info[drive] != currcard || card_info[drive].initialized == 0) | 730 | sd_select_device(drive); |
621 | { | ||
622 | sd_init_device(drive); | ||
623 | 731 | ||
624 | if (card_info[drive].initialized < 0) | 732 | if (currcard->initialized < 0) |
625 | goto ata_read_error; | 733 | { |
734 | ret = currcard->initialized; | ||
735 | goto ata_read_error; | ||
626 | } | 736 | } |
627 | 737 | ||
628 | last_disk_activity = current_tick; | 738 | last_disk_activity = current_tick; |
629 | 739 | ||
630 | bank = start / BLOCKS_PER_BANK; | 740 | bank = start / BLOCKS_PER_BANK; |
631 | 741 | ||
632 | if (currcard->current_bank != bank && !sd_select_bank(bank)) | 742 | if (currcard->current_bank != bank) |
633 | goto ata_read_error; | 743 | { |
744 | ret = sd_select_bank(bank); | ||
745 | if (ret < 0) | ||
746 | goto ata_read_error; | ||
747 | } | ||
634 | 748 | ||
635 | start -= bank * BLOCKS_PER_BANK; | 749 | start -= bank * BLOCKS_PER_BANK; |
636 | 750 | ||
637 | sd_wait_for_state(TRAN, EC_TRAN_READ_ENTRY); | 751 | ret = sd_wait_for_state(TRAN, EC_TRAN_READ_ENTRY); |
752 | if (ret < 0) | ||
753 | goto ata_read_error; | ||
754 | |||
638 | BLOCK_COUNT_REG = incount; | 755 | BLOCK_COUNT_REG = incount; |
639 | 756 | ||
640 | if (!sd_command(READ_MULTIPLE_BLOCK, start * BLOCK_SIZE, &dummy, 0x1c25)) | 757 | ret = sd_command(READ_MULTIPLE_BLOCK, start * BLOCK_SIZE, NULL, 0x1c25); |
758 | if (ret < 0) | ||
641 | goto ata_read_error; | 759 | goto ata_read_error; |
642 | 760 | ||
643 | /* TODO: Don't assume BLOCK_SIZE == SECTOR_SIZE */ | 761 | /* TODO: Don't assume BLOCK_SIZE == SECTOR_SIZE */ |
@@ -646,79 +764,104 @@ int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int incount, | |||
646 | for (buf = inbuf; buf < buf_end;) | 764 | for (buf = inbuf; buf < buf_end;) |
647 | { | 765 | { |
648 | /* Wait for the FIFO to be full */ | 766 | /* Wait for the FIFO to be full */ |
649 | sd_poll_status(FIFO_FULL, 0x80000, EC_FIFO_READ_FULL | DO_PANIC); | 767 | if (sd_poll_status(FIFO_FULL, 0x80000)) |
650 | copy_read_sectors_fast(&buf); /* Copy one chunk of 16 words */ | 768 | { |
769 | copy_read_sectors_fast(&buf); /* Copy one chunk of 16 words */ | ||
770 | /* TODO: Switch bank if necessary */ | ||
771 | continue; | ||
772 | } | ||
651 | 773 | ||
652 | /* TODO: Switch bank if necessary */ | 774 | ret = -EC_FIFO_READ_FULL; |
775 | goto ata_read_error; | ||
653 | } | 776 | } |
654 | 777 | ||
655 | last_disk_activity = current_tick; | 778 | last_disk_activity = current_tick; |
656 | #if 0 | ||
657 | udelay(75); | ||
658 | #endif | ||
659 | if (!sd_command(STOP_TRANSMISSION, 0, &dummy, 1)) | ||
660 | goto ata_read_error; | ||
661 | 779 | ||
662 | sd_wait_for_state(TRAN, EC_TRAN_READ_EXIT); | 780 | ret = sd_command(STOP_TRANSMISSION, 0, NULL, 1); |
781 | if (ret < 0) | ||
782 | goto ata_read_error; | ||
663 | 783 | ||
664 | ret = 0; | 784 | ret = sd_wait_for_state(TRAN, EC_TRAN_READ_EXIT); |
785 | if (ret < 0) | ||
786 | goto ata_read_error; | ||
665 | 787 | ||
666 | ata_read_error: | 788 | while (1) |
667 | ata_led(false); | 789 | { |
790 | ata_led(false); | ||
791 | spinlock_unlock(&sd_mtx); | ||
668 | 792 | ||
669 | spinlock_unlock(&sd_mtx); | 793 | return ret; |
670 | 794 | ||
671 | return ret; | 795 | ata_read_error: |
796 | if (sd_status[drive].retry < sd_status[drive].retry_max | ||
797 | && ret != -EC_NOCARD) | ||
798 | { | ||
799 | sd_status[drive].retry++; | ||
800 | currcard->initialized = 0; | ||
801 | goto ata_read_retry; | ||
802 | } | ||
803 | } | ||
672 | } | 804 | } |
673 | 805 | ||
674 | int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count, | 806 | int ata_write_sectors(int drive, unsigned long start, int count, |
675 | const void* outbuf) | 807 | const void* outbuf) |
676 | { | 808 | { |
677 | /* Write support is not finished yet */ | 809 | /* Write support is not finished yet */ |
678 | /* TODO: The standard suggests using ACMD23 prior to writing multiple blocks | 810 | /* TODO: The standard suggests using ACMD23 prior to writing multiple blocks |
679 | to improve performance */ | 811 | to improve performance */ |
680 | unsigned int response; | 812 | int ret; |
681 | void const* buf, *buf_end; | 813 | const unsigned char *buf, *buf_end; |
682 | int ret = -9; | ||
683 | int bank; | 814 | int bank; |
684 | 815 | ||
685 | spinlock_lock(&sd_mtx); | 816 | spinlock_lock(&sd_mtx); |
686 | 817 | ||
687 | ata_led(true); | 818 | ata_led(true); |
688 | 819 | ||
820 | ata_write_retry: | ||
689 | if (drive != 0 && (GPIOA_INPUT_VAL & 0x80) != 0) | 821 | if (drive != 0 && (GPIOA_INPUT_VAL & 0x80) != 0) |
822 | { | ||
690 | /* no external sd-card inserted */ | 823 | /* no external sd-card inserted */ |
824 | ret = -EC_NOCARD; | ||
691 | goto ata_write_error; | 825 | goto ata_write_error; |
826 | } | ||
692 | 827 | ||
693 | if (&card_info[drive] != currcard || card_info[drive].initialized == 0) | 828 | sd_select_device(drive); |
694 | { | ||
695 | sd_init_device(drive); | ||
696 | 829 | ||
697 | if (card_info[drive].initialized < 0) | 830 | if (currcard->initialized < 0) |
698 | goto ata_write_error; | 831 | { |
832 | ret = currcard->initialized; | ||
833 | goto ata_write_error; | ||
699 | } | 834 | } |
700 | 835 | ||
701 | bank = start / BLOCKS_PER_BANK; | 836 | bank = start / BLOCKS_PER_BANK; |
702 | 837 | ||
703 | if (currcard->current_bank != bank && !sd_select_bank(bank)) | 838 | if (currcard->current_bank != bank) |
704 | goto ata_write_error; | 839 | { |
840 | ret = sd_select_bank(bank); | ||
841 | if (ret < 0) | ||
842 | goto ata_write_error; | ||
843 | } | ||
705 | 844 | ||
706 | start -= bank * BLOCKS_PER_BANK; | 845 | start -= bank * BLOCKS_PER_BANK; |
707 | 846 | ||
708 | check_time[EC_WRITE_TIMEOUT] = USEC_TIMER; | 847 | check_time[EC_WRITE_TIMEOUT] = USEC_TIMER; |
709 | sd_wait_for_state(TRAN, EC_TRAN_WRITE_ENTRY); | 848 | |
849 | ret = sd_wait_for_state(TRAN, EC_TRAN_WRITE_ENTRY); | ||
850 | if (ret < 0) | ||
851 | goto ata_write_error; | ||
852 | |||
710 | BLOCK_COUNT_REG = count; | 853 | BLOCK_COUNT_REG = count; |
711 | 854 | ||
712 | if (!sd_command(WRITE_MULTIPLE_BLOCK, start * SECTOR_SIZE, | 855 | ret = sd_command(WRITE_MULTIPLE_BLOCK, start * SECTOR_SIZE, |
713 | &response, 0x1c2d)) | 856 | NULL, 0x1c2d); |
714 | { | 857 | if (ret < 0) |
715 | goto ata_write_error; | 858 | goto ata_write_error; |
716 | } | ||
717 | 859 | ||
718 | buf_end = outbuf + count * currcard->block_size; | 860 | buf_end = outbuf + count * currcard->block_size - 2*FIFO_LEN; |
719 | for (buf = outbuf; buf < buf_end; buf += 2 * FIFO_SIZE) | 861 | |
862 | for (buf = outbuf; buf <= buf_end;) | ||
720 | { | 863 | { |
721 | if (buf >= buf_end - 2 * FIFO_SIZE) | 864 | if (buf == buf_end) |
722 | { | 865 | { |
723 | /* Set SD_STATE_REG to PRG for the last buffer fill */ | 866 | /* Set SD_STATE_REG to PRG for the last buffer fill */ |
724 | SD_STATE_REG = PRG; | 867 | SD_STATE_REG = PRG; |
@@ -727,30 +870,49 @@ int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count, | |||
727 | udelay(2); /* needed here (loop is too fast :-) */ | 870 | udelay(2); /* needed here (loop is too fast :-) */ |
728 | 871 | ||
729 | /* Wait for the FIFO to empty */ | 872 | /* Wait for the FIFO to empty */ |
730 | sd_poll_status(FIFO_EMPTY, 0x80000, EC_FIFO_WR_EMPTY | DO_PANIC); | 873 | if (sd_poll_status(FIFO_EMPTY, 0x80000)) |
731 | 874 | { | |
732 | copy_write_sectors(buf); /* Copy one chunk of 16 words */ | 875 | copy_write_sectors(&buf); /* Copy one chunk of 16 words */ |
876 | /* TODO: Switch bank if necessary */ | ||
877 | continue; | ||
878 | } | ||
733 | 879 | ||
734 | /* TODO: Switch bank if necessary */ | 880 | ret = -EC_FIFO_WR_EMPTY; |
881 | goto ata_write_error; | ||
735 | } | 882 | } |
736 | 883 | ||
737 | last_disk_activity = current_tick; | 884 | last_disk_activity = current_tick; |
738 | 885 | ||
739 | sd_poll_status(DATA_DONE, 0x80000, EC_FIFO_WR_DONE | DO_PANIC); | 886 | if (!sd_poll_status(DATA_DONE, 0x80000)) |
740 | sd_check_timeout(0x80000, EC_WRITE_TIMEOUT); | 887 | { |
888 | ret = -EC_FIFO_WR_DONE; | ||
889 | goto ata_write_error; | ||
890 | } | ||
741 | 891 | ||
742 | if (!sd_command(STOP_TRANSMISSION, 0, &response, 1)) | 892 | ret = sd_command(STOP_TRANSMISSION, 0, NULL, 1); |
893 | if (ret < 0) | ||
743 | goto ata_write_error; | 894 | goto ata_write_error; |
744 | 895 | ||
745 | sd_wait_for_state(TRAN, EC_TRAN_WRITE_EXIT); | 896 | ret = sd_wait_for_state(TRAN, EC_TRAN_WRITE_EXIT); |
897 | if (ret < 0) | ||
898 | goto ata_write_error; | ||
746 | 899 | ||
747 | ret = 0; | 900 | while (1) |
901 | { | ||
902 | ata_led(false); | ||
903 | spinlock_unlock(&sd_mtx); | ||
748 | 904 | ||
749 | ata_write_error: | 905 | return ret; |
750 | ata_led(false); | ||
751 | spinlock_unlock(&sd_mtx); | ||
752 | 906 | ||
753 | return ret; | 907 | ata_write_error: |
908 | if (sd_status[drive].retry < sd_status[drive].retry_max | ||
909 | && ret != -EC_NOCARD) | ||
910 | { | ||
911 | sd_status[drive].retry++; | ||
912 | currcard->initialized = 0; | ||
913 | goto ata_write_retry; | ||
914 | } | ||
915 | } | ||
754 | } | 916 | } |
755 | 917 | ||
756 | static void sd_thread(void) __attribute__((noreturn)); | 918 | static void sd_thread(void) __attribute__((noreturn)); |
@@ -767,19 +929,13 @@ static void sd_thread(void) | |||
767 | { | 929 | { |
768 | case SD_HOTSWAP: | 930 | case SD_HOTSWAP: |
769 | { | 931 | { |
770 | int status = 0; | 932 | int action = SDA_NONE; |
771 | enum { SD_UNMOUNTED = 0x1, SD_MOUNTED = 0x2 }; | ||
772 | |||
773 | /* Delay on insert and remove to prevent reading state if it is | ||
774 | just bouncing back and forth while card is sliding - delay on | ||
775 | insert is also required for the card to stabilize and accept | ||
776 | commands */ | ||
777 | sleep(HZ/10); | ||
778 | 933 | ||
779 | /* Lock to keep us from messing with this variable while an init | 934 | /* Lock to keep us from messing with this variable while an init |
780 | may be in progress */ | 935 | may be in progress */ |
781 | spinlock_lock(&sd_mtx); | 936 | spinlock_lock(&sd_mtx); |
782 | card_info[1].initialized = false; | 937 | card_info[1].initialized = 0; |
938 | sd_status[1].retry = 0; | ||
783 | spinlock_unlock(&sd_mtx); | 939 | spinlock_unlock(&sd_mtx); |
784 | 940 | ||
785 | /* Either unmount because the card was pulled or unmount and | 941 | /* Either unmount because the card was pulled or unmount and |
@@ -787,18 +943,18 @@ static void sd_thread(void) | |||
787 | generated for the same event - like someone inserting a new | 943 | generated for the same event - like someone inserting a new |
788 | card before anything detects the old one pulled :) */ | 944 | card before anything detects the old one pulled :) */ |
789 | if (disk_unmount(1) != 0) /* release "by force" */ | 945 | if (disk_unmount(1) != 0) /* release "by force" */ |
790 | status |= SD_UNMOUNTED; | 946 | action |= SDA_UNMOUNTED; |
791 | 947 | ||
792 | if (card_detect_target() && disk_mount(1) != 0) /* mount SD-CARD */ | 948 | if (ev.data != 0 && disk_mount(1) != 0) /* mount SD-CARD */ |
793 | status |= SD_MOUNTED; | 949 | action |= SDA_MOUNTED; |
794 | 950 | ||
795 | if (status & SD_UNMOUNTED) | 951 | if (action & SDA_UNMOUNTED) |
796 | queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0); | 952 | queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0); |
797 | 953 | ||
798 | if (status & SD_MOUNTED) | 954 | if (action & SDA_MOUNTED) |
799 | queue_broadcast(SYS_HOTSWAP_INSERTED, 0); | 955 | queue_broadcast(SYS_HOTSWAP_INSERTED, 0); |
800 | 956 | ||
801 | if (status) | 957 | if (action != SDA_NONE) |
802 | queue_broadcast(SYS_FS_CHANGED, 0); | 958 | queue_broadcast(SYS_FS_CHANGED, 0); |
803 | break; | 959 | break; |
804 | } /* SD_HOTSWAP */ | 960 | } /* SD_HOTSWAP */ |
@@ -807,12 +963,23 @@ static void sd_thread(void) | |||
807 | { | 963 | { |
808 | idle_notified = false; | 964 | idle_notified = false; |
809 | } | 965 | } |
810 | else if (!idle_notified) | 966 | else |
811 | { | 967 | { |
812 | call_ata_idle_notifys(false); | 968 | /* never let a timer wrap confuse us */ |
813 | idle_notified = true; | 969 | next_yield = USEC_TIMER; |
970 | |||
971 | if (!idle_notified) | ||
972 | { | ||
973 | call_ata_idle_notifys(false); | ||
974 | idle_notified = true; | ||
975 | } | ||
814 | } | 976 | } |
815 | break; | 977 | break; |
978 | case SYS_USB_CONNECTED: | ||
979 | usb_acknowledge(SYS_USB_CONNECTED_ACK); | ||
980 | /* Wait until the USB cable is extracted again */ | ||
981 | usb_wait_for_disconnect(&sd_queue); | ||
982 | break; | ||
816 | } | 983 | } |
817 | } | 984 | } |
818 | } | 985 | } |
@@ -878,7 +1045,6 @@ int ata_init(void) | |||
878 | outl(inl(0x70000088) & ~(0x4), 0x70000088); | 1045 | outl(inl(0x70000088) & ~(0x4), 0x70000088); |
879 | outl(inl(0x7000008c) & ~(0x4), 0x7000008c); | 1046 | outl(inl(0x7000008c) & ~(0x4), 0x7000008c); |
880 | outl(inl(0x70000084) | 0x4, 0x70000084); | 1047 | outl(inl(0x70000084) | 0x4, 0x70000084); |
881 | outl(0x1010, 0x70000034); | ||
882 | 1048 | ||
883 | GPIOG_ENABLE |= (0x3 << 5); | 1049 | GPIOG_ENABLE |= (0x3 << 5); |
884 | GPIOG_OUTPUT_EN |= (0x3 << 5); | 1050 | GPIOG_OUTPUT_EN |= (0x3 << 5); |
@@ -890,10 +1056,10 @@ int ata_init(void) | |||
890 | GPIOA_OUTPUT_EN &= ~0x80; | 1056 | GPIOA_OUTPUT_EN &= ~0x80; |
891 | GPIOA_ENABLE |= 0x80; | 1057 | GPIOA_ENABLE |= 0x80; |
892 | 1058 | ||
893 | sd_init_device(0); | 1059 | sd_select_device(0); |
894 | 1060 | ||
895 | if (currcard->initialized <= 0) | 1061 | if (currcard->initialized < 0) |
896 | ret = -1; | 1062 | ret = currcard->initialized; |
897 | 1063 | ||
898 | queue_init(&sd_queue, true); | 1064 | queue_init(&sd_queue, true); |
899 | create_thread(sd_thread, sd_stack, sizeof(sd_stack), | 1065 | create_thread(sd_thread, sd_stack, sizeof(sd_stack), |
@@ -905,8 +1071,7 @@ int ata_init(void) | |||
905 | CPU_INT_EN = HI_MASK; | 1071 | CPU_INT_EN = HI_MASK; |
906 | CPU_HI_INT_EN = GPIO0_MASK; | 1072 | CPU_HI_INT_EN = GPIO0_MASK; |
907 | 1073 | ||
908 | sd1_status = GPIOA_INPUT_VAL & 0x80; | 1074 | GPIOA_INT_LEV = (GPIOA_INT_LEV & ~0x80) | (~GPIOA_INPUT_VAL & 0x80); |
909 | GPIOA_INT_LEV = (GPIOA_INT_LEV & ~0x80) | (sd1_status ^ 0x80); | ||
910 | 1075 | ||
911 | GPIOA_INT_CLR = 0x80; | 1076 | GPIOA_INT_CLR = 0x80; |
912 | GPIOA_INT_EN |= 0x80; | 1077 | GPIOA_INT_EN |= 0x80; |
@@ -960,17 +1125,12 @@ bool card_detect_target(void) | |||
960 | /* called on insertion/removal interrupt */ | 1125 | /* called on insertion/removal interrupt */ |
961 | void microsd_int(void) | 1126 | void microsd_int(void) |
962 | { | 1127 | { |
963 | int status = GPIOA_INPUT_VAL & 0x80; | 1128 | int detect = GPIOA_INPUT_VAL & 0x80; |
964 | |||
965 | GPIOA_INT_LEV = (GPIOA_INT_LEV & ~0x80) | (status ^ 0x80); | ||
966 | GPIOA_INT_CLR = 0x80; | ||
967 | |||
968 | if (status == sd1_status) | ||
969 | return; | ||
970 | 1129 | ||
971 | sd1_status = status; | 1130 | GPIOA_INT_LEV = (GPIOA_INT_LEV & ~0x80) | (detect ^ 0x80); |
1131 | GPIOA_INT_CLR = 0x80; | ||
972 | 1132 | ||
973 | /* Take final state only - insert/remove is bouncy */ | 1133 | /* Take final state only - insert/remove is bouncy */ |
974 | queue_remove_from_head(&sd_queue, SD_HOTSWAP); | 1134 | queue_remove_from_head(&sd_queue, SD_HOTSWAP); |
975 | queue_post(&sd_queue, SD_HOTSWAP, status); | 1135 | queue_post(&sd_queue, SD_HOTSWAP, detect == 0); |
976 | } | 1136 | } |