diff options
author | Solomon Peachy <pizza@shaftnet.org> | 2018-09-05 14:59:32 -0400 |
---|---|---|
committer | Solomon Peachy <pizza@shaftnet.org> | 2018-09-20 19:38:25 -0400 |
commit | 640ada038954a97ff73a863e84672c00fe358649 (patch) | |
tree | 95579d25852fa5b5df47a9ae770bc49ad0aca7a7 /firmware/target | |
parent | 8edf4052c78992a269e00d78a2cb82ed73f38358 (diff) | |
download | rockbox-640ada038954a97ff73a863e84672c00fe358649.tar.gz rockbox-640ada038954a97ff73a863e84672c00fe358649.zip |
jz4760: Enhancements and fixes to SD driver.
* Fully Interrupt-driven, with proper task yielding
* Much more robust error handling
* Eliminate duplicate code
* Pile of bugfixes
(Much of this adapted from Igor Poretsky's tree)
Change-Id: I46006412323cba2088b70094635d62a241be1d7e
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c | 518 |
1 files changed, 239 insertions, 279 deletions
diff --git a/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c b/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c index d01015fee6..680a2a6823 100644 --- a/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c +++ b/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c | |||
@@ -30,6 +30,13 @@ | |||
30 | #include "storage.h" | 30 | #include "storage.h" |
31 | #include "string.h" | 31 | #include "string.h" |
32 | 32 | ||
33 | #define SD_DMA_ENABLE 1 | ||
34 | #define SD_DMA_INTERRUPT 1 | ||
35 | |||
36 | #if NUM_DRIVES > 2 | ||
37 | #error "JZ4760 SD driver supports NUM_DRIVES <= 2 only" | ||
38 | #endif | ||
39 | |||
33 | static long last_disk_activity = -1; | 40 | static long last_disk_activity = -1; |
34 | static tCardInfo card[NUM_DRIVES]; | 41 | static tCardInfo card[NUM_DRIVES]; |
35 | 42 | ||
@@ -40,13 +47,14 @@ static int sd_drive_nr = 0; | |||
40 | #endif | 47 | #endif |
41 | 48 | ||
42 | static struct mutex sd_mtx; | 49 | static struct mutex sd_mtx; |
43 | //static struct semaphore sd_wakeup; | 50 | #if SD_DMA_INTERRUPT |
51 | static struct semaphore sd_wakeup; | ||
52 | #endif | ||
44 | 53 | ||
45 | static int use_4bit[NUM_DRIVES]; | 54 | static int use_4bit[NUM_DRIVES]; |
46 | static int num_6[NUM_DRIVES]; | 55 | static int num_6[NUM_DRIVES]; |
47 | static int sd2_0[NUM_DRIVES]; | 56 | static int sd2_0[NUM_DRIVES]; |
48 | 57 | ||
49 | #define SD_DMA_ENABLE 1 | ||
50 | 58 | ||
51 | //#define DEBUG(x...) logf(x) | 59 | //#define DEBUG(x...) logf(x) |
52 | #define DEBUG(x, ...) | 60 | #define DEBUG(x, ...) |
@@ -129,45 +137,6 @@ enum sd_rsp_t | |||
129 | RESPONSE_R7 = 9, | 137 | RESPONSE_R7 = 9, |
130 | }; | 138 | }; |
131 | 139 | ||
132 | /* | ||
133 | MMC status in R1 | ||
134 | Type | ||
135 | e : error bit | ||
136 | s : status bit | ||
137 | r : detected and set for the actual command response | ||
138 | x : detected and set during command execution. the host must poll | ||
139 | the card by sending status command in order to read these bits. | ||
140 | Clear condition | ||
141 | a : according to the card state | ||
142 | b : always related to the previous command. Reception of | ||
143 | a valid command will clear it (with a delay of one command) | ||
144 | c : clear by read | ||
145 | */ | ||
146 | |||
147 | #define R1_OUT_OF_RANGE (1 << 31) /* er, c */ | ||
148 | #define R1_ADDRESS_ERROR (1 << 30) /* erx, c */ | ||
149 | #define R1_BLOCK_LEN_ERROR (1 << 29) /* er, c */ | ||
150 | #define R1_ERASE_SEQ_ERROR (1 << 28) /* er, c */ | ||
151 | #define R1_ERASE_PARAM (1 << 27) /* ex, c */ | ||
152 | #define R1_WP_VIOLATION (1 << 26) /* erx, c */ | ||
153 | #define R1_CARD_IS_LOCKED (1 << 25) /* sx, a */ | ||
154 | #define R1_LOCK_UNLOCK_FAILED (1 << 24) /* erx, c */ | ||
155 | #define R1_COM_CRC_ERROR (1 << 23) /* er, b */ | ||
156 | #define R1_ILLEGAL_COMMAND (1 << 22) /* er, b */ | ||
157 | #define R1_CARD_ECC_FAILED (1 << 21) /* ex, c */ | ||
158 | #define R1_CC_ERROR (1 << 20) /* erx, c */ | ||
159 | #define R1_ERROR (1 << 19) /* erx, c */ | ||
160 | #define R1_UNDERRUN (1 << 18) /* ex, c */ | ||
161 | #define R1_OVERRUN (1 << 17) /* ex, c */ | ||
162 | #define R1_CID_CSD_OVERWRITE (1 << 16) /* erx, c, CID/CSD overwrite */ | ||
163 | #define R1_WP_ERASE_SKIP (1 << 15) /* sx, c */ | ||
164 | #define R1_CARD_ECC_DISABLED (1 << 14) /* sx, a */ | ||
165 | #define R1_ERASE_RESET (1 << 13) /* sr, c */ | ||
166 | #define R1_STATUS(x) (x & 0xFFFFE000) | ||
167 | #define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */ | ||
168 | #define R1_READY_FOR_DATA (1 << 8) /* sx, a */ | ||
169 | #define R1_APP_CMD (1 << 7) /* sr, c */ | ||
170 | |||
171 | /* These are unpacked versions of the actual responses */ | 140 | /* These are unpacked versions of the actual responses */ |
172 | struct sd_response_r1 | 141 | struct sd_response_r1 |
173 | { | 142 | { |
@@ -176,7 +145,7 @@ struct sd_response_r1 | |||
176 | }; | 145 | }; |
177 | 146 | ||
178 | struct sd_response_r3 | 147 | struct sd_response_r3 |
179 | { | 148 | { |
180 | unsigned int ocr; | 149 | unsigned int ocr; |
181 | }; | 150 | }; |
182 | 151 | ||
@@ -233,23 +202,23 @@ static int sd_unpack_r1(struct sd_request *request, struct sd_response_r1 *r1) | |||
233 | 202 | ||
234 | DEBUG("sd_unpack_r1: cmd=%d status=%08x", r1->cmd, r1->status); | 203 | DEBUG("sd_unpack_r1: cmd=%d status=%08x", r1->cmd, r1->status); |
235 | 204 | ||
236 | if (R1_STATUS(r1->status)) { | 205 | if (SD_R1_STATUS(r1->status)) { |
237 | if (r1->status & R1_OUT_OF_RANGE) return SD_ERROR_OUT_OF_RANGE; | 206 | if (r1->status & SD_R1_OUT_OF_RANGE) return SD_ERROR_OUT_OF_RANGE; |
238 | if (r1->status & R1_ADDRESS_ERROR) return SD_ERROR_ADDRESS; | 207 | if (r1->status & SD_R1_ADDRESS_ERROR) return SD_ERROR_ADDRESS; |
239 | if (r1->status & R1_BLOCK_LEN_ERROR) return SD_ERROR_BLOCK_LEN; | 208 | if (r1->status & SD_R1_BLOCK_LEN_ERROR) return SD_ERROR_BLOCK_LEN; |
240 | if (r1->status & R1_ERASE_SEQ_ERROR) return SD_ERROR_ERASE_SEQ; | 209 | if (r1->status & SD_R1_ERASE_SEQ_ERROR) return SD_ERROR_ERASE_SEQ; |
241 | if (r1->status & R1_ERASE_PARAM) return SD_ERROR_ERASE_PARAM; | 210 | if (r1->status & SD_R1_ERASE_PARAM) return SD_ERROR_ERASE_PARAM; |
242 | if (r1->status & R1_WP_VIOLATION) return SD_ERROR_WP_VIOLATION; | 211 | if (r1->status & SD_R1_WP_VIOLATION) return SD_ERROR_WP_VIOLATION; |
243 | //if (r1->status & R1_CARD_IS_LOCKED) return SD_ERROR_CARD_IS_LOCKED; | 212 | //if (r1->status & SD_R1_CARD_IS_LOCKED) return SD_ERROR_CARD_IS_LOCKED; |
244 | if (r1->status & R1_LOCK_UNLOCK_FAILED) return SD_ERROR_LOCK_UNLOCK_FAILED; | 213 | if (r1->status & SD_R1_LOCK_UNLOCK_FAILED) return SD_ERROR_LOCK_UNLOCK_FAILED; |
245 | if (r1->status & R1_COM_CRC_ERROR) return SD_ERROR_COM_CRC; | 214 | if (r1->status & SD_R1_COM_CRC_ERROR) return SD_ERROR_COM_CRC; |
246 | if (r1->status & R1_ILLEGAL_COMMAND) return SD_ERROR_ILLEGAL_COMMAND; | 215 | if (r1->status & SD_R1_ILLEGAL_COMMAND) return SD_ERROR_ILLEGAL_COMMAND; |
247 | if (r1->status & R1_CARD_ECC_FAILED) return SD_ERROR_CARD_ECC_FAILED; | 216 | if (r1->status & SD_R1_CARD_ECC_FAILED) return SD_ERROR_CARD_ECC_FAILED; |
248 | if (r1->status & R1_CC_ERROR) return SD_ERROR_CC; | 217 | if (r1->status & SD_R1_CC_ERROR) return SD_ERROR_CC; |
249 | if (r1->status & R1_ERROR) return SD_ERROR_GENERAL; | 218 | if (r1->status & SD_R1_ERROR) return SD_ERROR_GENERAL; |
250 | if (r1->status & R1_UNDERRUN) return SD_ERROR_UNDERRUN; | 219 | if (r1->status & SD_R1_UNDERRUN) return SD_ERROR_UNDERRUN; |
251 | if (r1->status & R1_OVERRUN) return SD_ERROR_OVERRUN; | 220 | if (r1->status & SD_R1_OVERRUN) return SD_ERROR_OVERRUN; |
252 | if (r1->status & R1_CID_CSD_OVERWRITE) return SD_ERROR_CID_CSD_OVERWRITE; | 221 | if (r1->status & SD_R1_CSD_OVERWRITE) return SD_ERROR_CID_CSD_OVERWRITE; |
253 | } | 222 | } |
254 | 223 | ||
255 | if (buf[0] != request->cmd) | 224 | if (buf[0] != request->cmd) |
@@ -257,7 +226,7 @@ static int sd_unpack_r1(struct sd_request *request, struct sd_response_r1 *r1) | |||
257 | 226 | ||
258 | /* This should be last - it's the least dangerous error */ | 227 | /* This should be last - it's the least dangerous error */ |
259 | 228 | ||
260 | return 0; | 229 | return SD_NO_ERROR; |
261 | } | 230 | } |
262 | 231 | ||
263 | static int sd_unpack_r6(struct sd_request *request, struct sd_response_r1 *r1, unsigned long *rca) | 232 | static int sd_unpack_r6(struct sd_request *request, struct sd_response_r1 *r1, unsigned long *rca) |
@@ -287,7 +256,7 @@ static int sd_unpack_r3(struct sd_request *request, struct sd_response_r3 *r3) | |||
287 | if (buf[0] != 0x3f) | 256 | if (buf[0] != 0x3f) |
288 | return SD_ERROR_HEADER_MISMATCH; | 257 | return SD_ERROR_HEADER_MISMATCH; |
289 | 258 | ||
290 | return 0; | 259 | return SD_NO_ERROR; |
291 | } | 260 | } |
292 | 261 | ||
293 | /* Stop the MMC clock and wait while it happens */ | 262 | /* Stop the MMC clock and wait while it happens */ |
@@ -339,10 +308,8 @@ static int jz_sd_check_status(const int drive, struct sd_request *request) | |||
339 | { | 308 | { |
340 | DEBUG("SD CRC error, MSC_STAT 0x%x", status); | 309 | DEBUG("SD CRC error, MSC_STAT 0x%x", status); |
341 | return SD_ERROR_CRC; | 310 | return SD_ERROR_CRC; |
342 | |||
343 | } | 311 | } |
344 | 312 | ||
345 | |||
346 | /* Checking for FIFO empty */ | 313 | /* Checking for FIFO empty */ |
347 | /*if(status & MSC_STAT_DATA_FIFO_EMPTY && request->rtype != RESPONSE_NONE) | 314 | /*if(status & MSC_STAT_DATA_FIFO_EMPTY && request->rtype != RESPONSE_NONE) |
348 | { | 315 | { |
@@ -358,7 +325,10 @@ static void jz_sd_get_response(const int drive, struct sd_request *request) | |||
358 | { | 325 | { |
359 | int i; | 326 | int i; |
360 | unsigned char *buf; | 327 | unsigned char *buf; |
361 | unsigned int data; | 328 | unsigned short data; |
329 | |||
330 | if (request->result != SD_NO_RESPONSE) | ||
331 | return; | ||
362 | 332 | ||
363 | DEBUG("fetch response for request %d, cmd %d", request->rtype, | 333 | DEBUG("fetch response for request %d, cmd %d", request->rtype, |
364 | request->cmd); | 334 | request->cmd); |
@@ -419,37 +389,39 @@ static int jz_sd_receive_data(const int drive, struct sd_request *req) | |||
419 | unsigned char *buf = req->buffer; | 389 | unsigned char *buf = req->buffer; |
420 | unsigned int *wbuf = (unsigned int *) buf; | 390 | unsigned int *wbuf = (unsigned int *) buf; |
421 | unsigned int waligned = (((unsigned int) buf & 0x3) == 0); /* word aligned ? */ | 391 | unsigned int waligned = (((unsigned int) buf & 0x3) == 0); /* word aligned ? */ |
422 | unsigned int stat, timeout, data, cnt; | 392 | unsigned int stat, data, cnt; |
423 | 393 | ||
424 | for (; nob >= 1; nob--) | 394 | for (; nob >= 1; nob--) |
425 | { | 395 | { |
426 | timeout = 0x3FFFFFF; | 396 | long deadline = current_tick + (HZ * 65); |
427 | 397 | ||
428 | while (timeout) | 398 | do { |
429 | { | ||
430 | timeout--; | ||
431 | stat = REG_MSC_STAT(MSC_CHN(drive)); | 399 | stat = REG_MSC_STAT(MSC_CHN(drive)); |
432 | 400 | ||
433 | if (stat & MSC_STAT_TIME_OUT_READ) | 401 | if (stat & MSC_STAT_TIME_OUT_READ) |
434 | return SD_ERROR_TIMEOUT; | 402 | return SD_ERROR_TIMEOUT; |
435 | else if (stat & MSC_STAT_CRC_READ_ERROR) | 403 | else if (stat & MSC_STAT_CRC_READ_ERROR) |
436 | return SD_ERROR_CRC; | 404 | return SD_ERROR_CRC; |
437 | else if (!(stat & MSC_STAT_DATA_FIFO_EMPTY) | 405 | else if ((stat & MSC_STAT_DATA_FIFO_AFULL) || |
438 | || (stat & MSC_STAT_DATA_FIFO_AFULL)) | 406 | !(stat & MSC_STAT_DATA_FIFO_EMPTY)) |
439 | /* Ready to read data */ | 407 | /* Ready to read data */ |
440 | break; | 408 | break; |
441 | 409 | ||
442 | udelay(1); | 410 | yield(); |
443 | } | 411 | } while (TIME_BEFORE(current_tick, deadline)); |
444 | |||
445 | if (!timeout) | ||
446 | return SD_ERROR_TIMEOUT; | ||
447 | 412 | ||
448 | /* Read data from RXFIFO. It could be FULL or PARTIAL FULL */ | 413 | /* Read data from RXFIFO. It could be FULL or PARTIAL FULL */ |
449 | DEBUG("Receive Data = %d", wblocklen); | 414 | DEBUG("Receive Data = %d", wblocklen); |
450 | cnt = wblocklen; | 415 | cnt = wblocklen; |
451 | while (cnt) | 416 | while (cnt) |
452 | { | 417 | { |
418 | if (REG_MSC_STAT(MSC_CHN(drive)) & MSC_STAT_DATA_FIFO_EMPTY) | ||
419 | { | ||
420 | if (TIME_AFTER(current_tick, deadline)) | ||
421 | return SD_ERROR_TIMEOUT; | ||
422 | continue; | ||
423 | } | ||
424 | |||
453 | data = REG_MSC_RXFIFO(MSC_CHN(drive)); | 425 | data = REG_MSC_RXFIFO(MSC_CHN(drive)); |
454 | if (waligned) | 426 | if (waligned) |
455 | *wbuf++ = data; | 427 | *wbuf++ = data; |
@@ -461,9 +433,6 @@ static int jz_sd_receive_data(const int drive, struct sd_request *req) | |||
461 | *buf++ = (unsigned char) (data >> 24); | 433 | *buf++ = (unsigned char) (data >> 24); |
462 | } | 434 | } |
463 | cnt--; | 435 | cnt--; |
464 | while (cnt | ||
465 | && (REG_MSC_STAT(MSC_CHN(drive)) & | ||
466 | MSC_STAT_DATA_FIFO_EMPTY)); | ||
467 | } | 436 | } |
468 | } | 437 | } |
469 | 438 | ||
@@ -477,15 +446,13 @@ static int jz_sd_transmit_data(const int drive, struct sd_request *req) | |||
477 | unsigned char *buf = req->buffer; | 446 | unsigned char *buf = req->buffer; |
478 | unsigned int *wbuf = (unsigned int *) buf; | 447 | unsigned int *wbuf = (unsigned int *) buf; |
479 | unsigned int waligned = (((unsigned int) buf & 0x3) == 0); /* word aligned ? */ | 448 | unsigned int waligned = (((unsigned int) buf & 0x3) == 0); /* word aligned ? */ |
480 | unsigned int stat, timeout, data, cnt; | 449 | unsigned int stat, data, cnt; |
481 | 450 | ||
482 | for (; nob >= 1; nob--) | 451 | for (; nob >= 1; nob--) |
483 | { | 452 | { |
484 | timeout = 0x3FFFFFF; | 453 | long deadline = current_tick + (HZ * 65); |
485 | 454 | ||
486 | while (timeout) | 455 | do { |
487 | { | ||
488 | timeout--; | ||
489 | stat = REG_MSC_STAT(MSC_CHN(drive)); | 456 | stat = REG_MSC_STAT(MSC_CHN(drive)); |
490 | 457 | ||
491 | if (stat & | 458 | if (stat & |
@@ -496,17 +463,19 @@ static int jz_sd_transmit_data(const int drive, struct sd_request *req) | |||
496 | /* Ready to write data */ | 463 | /* Ready to write data */ |
497 | break; | 464 | break; |
498 | 465 | ||
499 | udelay(1); | 466 | yield(); |
500 | } | 467 | } while (TIME_BEFORE(current_tick, deadline)); |
501 | |||
502 | if (!timeout) | ||
503 | return SD_ERROR_TIMEOUT; | ||
504 | 468 | ||
505 | /* Write data to TXFIFO */ | 469 | /* Write data to TXFIFO */ |
506 | cnt = wblocklen; | 470 | cnt = wblocklen; |
507 | while (cnt) | 471 | while (cnt) |
508 | { | 472 | { |
509 | while (REG_MSC_STAT(MSC_CHN(drive)) & MSC_STAT_DATA_FIFO_FULL); | 473 | if (REG_MSC_STAT(MSC_CHN(drive)) & MSC_STAT_DATA_FIFO_FULL) |
474 | { | ||
475 | if (TIME_AFTER(current_tick, deadline)) | ||
476 | return SD_ERROR_TIMEOUT; | ||
477 | continue; | ||
478 | } | ||
510 | 479 | ||
511 | if (waligned) | 480 | if (waligned) |
512 | REG_MSC_TXFIFO(MSC_CHN(drive)) = *wbuf++; | 481 | REG_MSC_TXFIFO(MSC_CHN(drive)) = *wbuf++; |
@@ -527,72 +496,81 @@ static int jz_sd_transmit_data(const int drive, struct sd_request *req) | |||
527 | } | 496 | } |
528 | 497 | ||
529 | #if SD_DMA_ENABLE | 498 | #if SD_DMA_ENABLE |
530 | static void jz_sd_receive_data_dma(const int drive, struct sd_request *req) | 499 | static int jz_sd_receive_data_dma(const int drive, struct sd_request *req) |
531 | { | 500 | { |
532 | unsigned int waligned = (((unsigned int)req->buffer & 0x3) == 0); /* word aligned ? */ | 501 | if ((unsigned int)req->buffer & 0x3) |
533 | unsigned int size = req->block_len * req->nob; | 502 | return jz_sd_receive_data(drive, req); |
534 | |||
535 | if (!waligned) | ||
536 | { | ||
537 | jz_sd_receive_data(drive, req); | ||
538 | return; | ||
539 | } | ||
540 | 503 | ||
541 | /* flush dcache */ | 504 | /* flush dcache */ |
542 | dma_cache_wback_inv((unsigned long) req->buffer, size); | 505 | dma_cache_wback_inv((unsigned long) req->buffer, req->cnt); |
543 | 506 | ||
544 | /* setup dma channel */ | 507 | /* setup dma channel */ |
545 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) = 0; | 508 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) = 0; |
546 | REG_DMAC_DSAR(DMA_SD_RX_CHANNEL) = PHYSADDR(MSC_RXFIFO(MSC_CHN(drive))); /* DMA source addr */ | 509 | REG_DMAC_DSAR(DMA_SD_RX_CHANNEL) = PHYSADDR(MSC_RXFIFO(MSC_CHN(drive))); /* DMA source addr */ |
547 | REG_DMAC_DTAR(DMA_SD_RX_CHANNEL) = PHYSADDR((unsigned long)req->buffer); /* DMA dest addr */ | 510 | REG_DMAC_DTAR(DMA_SD_RX_CHANNEL) = PHYSADDR((unsigned long)req->buffer); /* DMA dest addr */ |
548 | REG_DMAC_DTCR(DMA_SD_RX_CHANNEL) = (size + 3) >> 2; /* DMA transfer count */ | 511 | REG_DMAC_DTCR(DMA_SD_RX_CHANNEL) = (req->cnt + 3) >> 2; /* DMA transfer count */ |
549 | REG_DMAC_DRSR(DMA_SD_RX_CHANNEL) = (drive == SD_SLOT_1) ? DMAC_DRSR_RS_MSC2IN : DMAC_DRSR_RS_MSC1IN; /* DMA request type */ | 512 | REG_DMAC_DRSR(DMA_SD_RX_CHANNEL) = (drive == SD_SLOT_1) ? DMAC_DRSR_RS_MSC2IN : DMAC_DRSR_RS_MSC1IN; /* DMA request type */ |
550 | 513 | ||
551 | REG_DMAC_DCMD(DMA_SD_RX_CHANNEL) = | 514 | REG_DMAC_DCMD(DMA_SD_RX_CHANNEL) = |
515 | #if SD_DMA_INTERRUPT | ||
516 | DMAC_DCMD_TIE | /* Enable DMA interrupt */ | ||
517 | #endif | ||
552 | DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | | 518 | DMAC_DCMD_DAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | |
553 | DMAC_DCMD_DS_32BIT; | 519 | DMAC_DCMD_DS_32BIT; |
554 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) = DMAC_DCCSR_EN | DMAC_DCCSR_NDES; | 520 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) = DMAC_DCCSR_EN | DMAC_DCCSR_NDES; |
555 | 521 | ||
556 | /* wait for dma completion */ | 522 | /* wait for dma completion */ |
557 | while (REG_DMAC_DTCR(DMA_SD_RX_CHANNEL)); | 523 | #if SD_DMA_INTERRUPT |
524 | semaphore_wait(&sd_wakeup, TIMEOUT_BLOCK); | ||
525 | #else | ||
526 | while (REG_DMAC_DTCR(DMA_SD_RX_CHANNEL)) | ||
527 | yield(); | ||
528 | #endif | ||
558 | 529 | ||
559 | /* clear status and disable channel */ | 530 | /* clear status and disable channel */ |
560 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) = 0; | 531 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) = 0; |
532 | |||
533 | return SD_NO_ERROR; | ||
561 | } | 534 | } |
562 | 535 | ||
563 | static void jz_sd_transmit_data_dma(const int drive, struct sd_request *req) | 536 | static int jz_sd_transmit_data_dma(const int drive, struct sd_request *req) |
564 | { | 537 | { |
565 | unsigned int waligned = (((unsigned int)req->buffer & 0x3) == 0); /* word aligned ? */ | 538 | if ((unsigned int)req->buffer & 0x3) |
566 | unsigned int size = req->block_len * req->nob; | 539 | return jz_sd_transmit_data(drive, req); |
567 | |||
568 | if (!waligned) | ||
569 | { | ||
570 | jz_sd_transmit_data(drive, req); | ||
571 | return; | ||
572 | } | ||
573 | 540 | ||
574 | /* flush dcache */ | 541 | /* flush dcache */ |
575 | dma_cache_wback_inv((unsigned long) req->buffer, size); | 542 | dma_cache_wback_inv((unsigned long) req->buffer, req->cnt); |
576 | 543 | ||
577 | /* setup dma channel */ | 544 | /* setup dma channel */ |
578 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) = 0; | 545 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) = 0; |
579 | REG_DMAC_DSAR(DMA_SD_TX_CHANNEL) = PHYSADDR((unsigned long) req->buffer); /* DMA source addr */ | 546 | REG_DMAC_DSAR(DMA_SD_TX_CHANNEL) = PHYSADDR((unsigned long) req->buffer); /* DMA source addr */ |
580 | REG_DMAC_DTAR(DMA_SD_TX_CHANNEL) = PHYSADDR(MSC_TXFIFO(MSC_CHN(drive))); /* DMA dest addr */ | 547 | REG_DMAC_DTAR(DMA_SD_TX_CHANNEL) = PHYSADDR(MSC_TXFIFO(MSC_CHN(drive))); /* DMA dest addr */ |
581 | REG_DMAC_DTCR(DMA_SD_TX_CHANNEL) = (size + 3) >> 2; /* DMA transfer count */ | 548 | REG_DMAC_DTCR(DMA_SD_TX_CHANNEL) = (req->cnt + 3) >> 2; /* DMA transfer count */ |
582 | REG_DMAC_DRSR(DMA_SD_TX_CHANNEL) = (drive == SD_SLOT_1) ? DMAC_DRSR_RS_MSC2OUT : DMAC_DRSR_RS_MSC1OUT; /* DMA request type */ | 549 | REG_DMAC_DRSR(DMA_SD_TX_CHANNEL) = (drive == SD_SLOT_1) ? DMAC_DRSR_RS_MSC2OUT : DMAC_DRSR_RS_MSC1OUT; /* DMA request type */ |
583 | 550 | ||
584 | REG_DMAC_DCMD(DMA_SD_TX_CHANNEL) = | 551 | REG_DMAC_DCMD(DMA_SD_TX_CHANNEL) = |
552 | #if SD_DMA_INTERRUPT | ||
553 | DMAC_DCMD_TIE | /* Enable DMA interrupt */ | ||
554 | #endif | ||
585 | DMAC_DCMD_SAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | | 555 | DMAC_DCMD_SAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_32 | |
586 | DMAC_DCMD_DS_32BIT; | 556 | DMAC_DCMD_DS_32BIT; |
587 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL) = DMAC_DCCSR_EN | DMAC_DCCSR_NDES; | 557 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL) = DMAC_DCCSR_EN | DMAC_DCCSR_NDES; |
588 | 558 | ||
589 | /* wait for dma completion */ | 559 | /* wait for dma completion */ |
590 | while (REG_DMAC_DTCR(DMA_SD_TX_CHANNEL)); | 560 | #if SD_DMA_INTERRUPT |
561 | semaphore_wait(&sd_wakeup, TIMEOUT_BLOCK); | ||
562 | #else | ||
563 | while (REG_DMAC_DTCR(DMA_SD_TX_CHANNEL)) | ||
564 | yield(); | ||
565 | #endif | ||
591 | 566 | ||
592 | /* clear status and disable channel */ | 567 | /* clear status and disable channel */ |
593 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL) = 0; | 568 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL) = 0; |
569 | |||
570 | return SD_NO_ERROR; | ||
594 | } | 571 | } |
595 | 572 | ||
573 | #if SD_DMA_INTERRUPT | ||
596 | void DMA_CALLBACK(DMA_SD_RX_CHANNEL)(void) | 574 | void DMA_CALLBACK(DMA_SD_RX_CHANNEL)(void) |
597 | { | 575 | { |
598 | if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) & DMAC_DCCSR_AR) | 576 | if (REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) & DMAC_DCCSR_AR) |
@@ -612,6 +590,8 @@ void DMA_CALLBACK(DMA_SD_RX_CHANNEL)(void) | |||
612 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) &= ~DMAC_DCCSR_TT; | 590 | REG_DMAC_DCCSR(DMA_SD_RX_CHANNEL) &= ~DMAC_DCCSR_TT; |
613 | //sd_rx_dma_callback(); | 591 | //sd_rx_dma_callback(); |
614 | } | 592 | } |
593 | |||
594 | semaphore_release(&sd_wakeup); | ||
615 | } | 595 | } |
616 | 596 | ||
617 | void DMA_CALLBACK(DMA_SD_TX_CHANNEL)(void) | 597 | void DMA_CALLBACK(DMA_SD_TX_CHANNEL)(void) |
@@ -633,7 +613,10 @@ void DMA_CALLBACK(DMA_SD_TX_CHANNEL)(void) | |||
633 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL) &= ~DMAC_DCCSR_TT; | 613 | REG_DMAC_DCCSR(DMA_SD_TX_CHANNEL) &= ~DMAC_DCCSR_TT; |
634 | //sd_tx_dma_callback(); | 614 | //sd_tx_dma_callback(); |
635 | } | 615 | } |
616 | |||
617 | semaphore_release(&sd_wakeup); | ||
636 | } | 618 | } |
619 | #endif /* SD_DMA_INTERRUPT */ | ||
637 | #endif /* SD_DMA_ENABLE */ | 620 | #endif /* SD_DMA_ENABLE */ |
638 | 621 | ||
639 | static inline unsigned int jz_sd_calc_clkrt(const int drive, unsigned int rate) | 622 | static inline unsigned int jz_sd_calc_clkrt(const int drive, unsigned int rate) |
@@ -654,7 +637,7 @@ static inline void cpm_select_msc_clk(unsigned int rate) | |||
654 | { | 637 | { |
655 | unsigned int div = __cpm_get_pllout2() / rate; | 638 | unsigned int div = __cpm_get_pllout2() / rate; |
656 | if (div == 0) | 639 | if (div == 0) |
657 | div = 1; | 640 | div = 1; |
658 | 641 | ||
659 | REG_CPM_MSCCDR = MSCCDR_MCS | (div - 1); | 642 | REG_CPM_MSCCDR = MSCCDR_MCS | (div - 1); |
660 | DEBUG("MSCCLK == %x\n", REG_CPM_MSCCDR); | 643 | DEBUG("MSCCLK == %x\n", REG_CPM_MSCCDR); |
@@ -686,7 +669,8 @@ static void jz_sd_set_clock(const int drive, unsigned int rate) | |||
686 | static int jz_sd_exec_cmd(const int drive, struct sd_request *request) | 669 | static int jz_sd_exec_cmd(const int drive, struct sd_request *request) |
687 | { | 670 | { |
688 | unsigned int cmdat = 0, events = 0; | 671 | unsigned int cmdat = 0, events = 0; |
689 | int retval, timeout = 0x3fffff; | 672 | int retval; |
673 | long deadline = current_tick + (HZ * 5); | ||
690 | 674 | ||
691 | /* Indicate we have no result yet */ | 675 | /* Indicate we have no result yet */ |
692 | request->result = SD_NO_RESPONSE; | 676 | request->result = SD_NO_RESPONSE; |
@@ -704,32 +688,14 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) | |||
704 | /* On reset, stop SD clock */ | 688 | /* On reset, stop SD clock */ |
705 | jz_sd_stop_clock(drive); | 689 | jz_sd_stop_clock(drive); |
706 | } | 690 | } |
707 | if (request->cmd == SD_SET_BUS_WIDTH) | ||
708 | { | ||
709 | if (request->arg == 0x2) | ||
710 | { | ||
711 | DEBUG("Use 4-bit bus width"); | ||
712 | use_4bit[drive] = 1; | ||
713 | } | ||
714 | else | ||
715 | { | ||
716 | DEBUG("Use 1-bit bus width"); | ||
717 | use_4bit[drive] = 0; | ||
718 | } | ||
719 | } | ||
720 | 691 | ||
721 | /* stop clock */ | 692 | /* stop clock */ |
722 | jz_sd_stop_clock(drive); | 693 | jz_sd_stop_clock(drive); |
723 | 694 | ||
724 | /* mask all interrupts */ | 695 | /* mask all interrupts and clear status */ |
725 | //REG_MSC_IMASK(MSC_CHN(drive)) = 0xffff; | 696 | SD_IRQ_MASK(MSC_CHN(drive)); |
726 | /* clear status */ | ||
727 | REG_MSC_IREG(MSC_CHN(drive)) = 0xffff; | ||
728 | /*open interrupt */ | 697 | /*open interrupt */ |
729 | REG_MSC_IMASK(MSC_CHN(drive)) = (~7); | 698 | REG_MSC_IMASK(MSC_CHN(drive)) = ~(MSC_IMASK_END_CMD_RES | MSC_IMASK_DATA_TRAN_DONE | MSC_IMASK_PRG_DONE); |
730 | /* use 4-bit bus width when possible */ | ||
731 | if (use_4bit[drive]) | ||
732 | cmdat |= MSC_CMDAT_BUS_WIDTH_4BIT; | ||
733 | 699 | ||
734 | /* Set command type and events */ | 700 | /* Set command type and events */ |
735 | switch (request->cmd) | 701 | switch (request->cmd) |
@@ -750,10 +716,18 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) | |||
750 | break; | 716 | break; |
751 | 717 | ||
752 | /* adtc - addressed with data transfer */ | 718 | /* adtc - addressed with data transfer */ |
719 | case SD_SEND_SCR: | ||
720 | /* SD card returns SCR register as data. | ||
721 | SD core expect it in the response buffer, | ||
722 | after normal response. */ | ||
723 | request->buffer = | ||
724 | (unsigned char *) ((unsigned int) request->response + 5); | ||
725 | request->block_len = 8; | ||
726 | request->nob = 1; | ||
727 | |||
753 | case SD_READ_DAT_UNTIL_STOP: | 728 | case SD_READ_DAT_UNTIL_STOP: |
754 | case SD_READ_SINGLE_BLOCK: | 729 | case SD_READ_SINGLE_BLOCK: |
755 | case SD_READ_MULTIPLE_BLOCK: | 730 | case SD_READ_MULTIPLE_BLOCK: |
756 | case SD_SEND_SCR: | ||
757 | #if SD_DMA_ENABLE | 731 | #if SD_DMA_ENABLE |
758 | cmdat |= | 732 | cmdat |= |
759 | MSC_CMDAT_DATA_EN | MSC_CMDAT_READ | MSC_CMDAT_DMA_EN; | 733 | MSC_CMDAT_DATA_EN | MSC_CMDAT_READ | MSC_CMDAT_DMA_EN; |
@@ -763,7 +737,17 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) | |||
763 | events = SD_EVENT_RX_DATA_DONE; | 737 | events = SD_EVENT_RX_DATA_DONE; |
764 | break; | 738 | break; |
765 | 739 | ||
766 | case 6: | 740 | case SD_SWITCH_FUNC: |
741 | if (request->arg == 0x2) | ||
742 | { | ||
743 | DEBUG("Use 4-bit bus width"); | ||
744 | use_4bit[drive] = 1; | ||
745 | } | ||
746 | else | ||
747 | { | ||
748 | DEBUG("Use 1-bit bus width"); | ||
749 | use_4bit[drive] = 0; | ||
750 | } | ||
767 | if (num_6[drive] < 2) | 751 | if (num_6[drive] < 2) |
768 | { | 752 | { |
769 | #if SD_DMA_ENABLE | 753 | #if SD_DMA_ENABLE |
@@ -782,7 +766,7 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) | |||
782 | case SD_WRITE_MULTIPLE_BLOCK: | 766 | case SD_WRITE_MULTIPLE_BLOCK: |
783 | case SD_PROGRAM_CID: | 767 | case SD_PROGRAM_CID: |
784 | case SD_PROGRAM_CSD: | 768 | case SD_PROGRAM_CSD: |
785 | case SD_LOCK_UNLOCK: | 769 | // case SD_LOCK_UNLOCK: |
786 | #if SD_DMA_ENABLE | 770 | #if SD_DMA_ENABLE |
787 | cmdat |= | 771 | cmdat |= |
788 | MSC_CMDAT_DATA_EN | MSC_CMDAT_WRITE | MSC_CMDAT_DMA_EN; | 772 | MSC_CMDAT_DATA_EN | MSC_CMDAT_WRITE | MSC_CMDAT_DMA_EN; |
@@ -833,6 +817,10 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) | |||
833 | break; | 817 | break; |
834 | } | 818 | } |
835 | 819 | ||
820 | /* use 4-bit bus width when possible */ | ||
821 | if (use_4bit[drive]) | ||
822 | cmdat |= MSC_CMDAT_BUS_WIDTH_4BIT; | ||
823 | |||
836 | /* Set command index */ | 824 | /* Set command index */ |
837 | if (request->cmd == SD_CIM_RESET) | 825 | if (request->cmd == SD_CIM_RESET) |
838 | REG_MSC_CMD(MSC_CHN(drive)) = SD_GO_IDLE_STATE; | 826 | REG_MSC_CMD(MSC_CHN(drive)) = SD_GO_IDLE_STATE; |
@@ -843,16 +831,8 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) | |||
843 | REG_MSC_ARG(MSC_CHN(drive)) = request->arg; | 831 | REG_MSC_ARG(MSC_CHN(drive)) = request->arg; |
844 | 832 | ||
845 | /* Set block length and nob */ | 833 | /* Set block length and nob */ |
846 | if (request->cmd == SD_SEND_SCR) | 834 | REG_MSC_BLKLEN(MSC_CHN(drive)) = request->block_len; |
847 | { /* get SCR from DataFIFO */ | 835 | REG_MSC_NOB(MSC_CHN(drive)) = request->nob; |
848 | REG_MSC_BLKLEN(MSC_CHN(drive)) = 8; | ||
849 | REG_MSC_NOB(MSC_CHN(drive)) = 1; | ||
850 | } | ||
851 | else | ||
852 | { | ||
853 | REG_MSC_BLKLEN(MSC_CHN(drive)) = request->block_len; | ||
854 | REG_MSC_NOB(MSC_CHN(drive)) = request->nob; | ||
855 | } | ||
856 | 836 | ||
857 | /* Set command */ | 837 | /* Set command */ |
858 | REG_MSC_CMDAT(MSC_CHN(drive)) = cmdat; | 838 | REG_MSC_CMDAT(MSC_CHN(drive)) = cmdat; |
@@ -866,11 +846,12 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) | |||
866 | /* Wait for command completion */ | 846 | /* Wait for command completion */ |
867 | //__intc_unmask_irq(IRQ_MSC); | 847 | //__intc_unmask_irq(IRQ_MSC); |
868 | //semaphore_wait(&sd_wakeup, 100); | 848 | //semaphore_wait(&sd_wakeup, 100); |
869 | while (timeout-- && !(REG_MSC_STAT(MSC_CHN(drive)) & MSC_STAT_END_CMD_RES)); | 849 | while (!(REG_MSC_IREG(MSC_CHN(drive)) & MSC_IREG_END_CMD_RES)) |
870 | 850 | { | |
871 | 851 | if (TIME_AFTER(current_tick, deadline)) | |
872 | if (timeout == 0) | 852 | return SD_ERROR_TIMEOUT; |
873 | return SD_ERROR_TIMEOUT; | 853 | yield(); |
854 | } | ||
874 | 855 | ||
875 | REG_MSC_IREG(MSC_CHN(drive)) = MSC_IREG_END_CMD_RES; /* clear flag */ | 856 | REG_MSC_IREG(MSC_CHN(drive)) = MSC_IREG_END_CMD_RES; /* clear flag */ |
876 | 857 | ||
@@ -891,33 +872,31 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) | |||
891 | { | 872 | { |
892 | if (events & SD_EVENT_RX_DATA_DONE) | 873 | if (events & SD_EVENT_RX_DATA_DONE) |
893 | { | 874 | { |
894 | if (request->cmd == SD_SEND_SCR) | ||
895 | { | ||
896 | /* SD card returns SCR register as data. | ||
897 | SD core expect it in the response buffer, | ||
898 | after normal response. */ | ||
899 | request->buffer = | ||
900 | (unsigned char *) ((unsigned int) request->response + 5); | ||
901 | } | ||
902 | #if SD_DMA_ENABLE | 875 | #if SD_DMA_ENABLE |
903 | jz_sd_receive_data_dma(drive, request); | 876 | retval = jz_sd_receive_data_dma(drive, request); |
904 | #else | 877 | #else |
905 | jz_sd_receive_data(drive, request); | 878 | retval = jz_sd_receive_data(drive, request); |
906 | #endif | 879 | #endif |
907 | } | 880 | } |
881 | if (retval) | ||
882 | return retval; | ||
908 | 883 | ||
909 | if (events & SD_EVENT_TX_DATA_DONE) | 884 | if (events & SD_EVENT_TX_DATA_DONE) |
910 | { | 885 | { |
911 | #if SD_DMA_ENABLE | 886 | #if SD_DMA_ENABLE |
912 | jz_sd_transmit_data_dma(drive, request); | 887 | retval = jz_sd_transmit_data_dma(drive, request); |
913 | #else | 888 | #else |
914 | jz_sd_transmit_data(drive, request); | 889 | retval = jz_sd_transmit_data(drive, request); |
915 | #endif | 890 | #endif |
916 | } | 891 | } |
892 | if (retval) | ||
893 | return retval; | ||
894 | |||
917 | //__intc_unmask_irq(IRQ_MSC); | 895 | //__intc_unmask_irq(IRQ_MSC); |
918 | //semaphore_wait(&sd_wakeup, 100); | 896 | //semaphore_wait(&sd_wakeup, 100); |
919 | /* Wait for Data Done */ | 897 | /* Wait for Data Done */ |
920 | while (!(REG_MSC_IREG(MSC_CHN(drive)) & MSC_IREG_DATA_TRAN_DONE)); | 898 | while (!(REG_MSC_IREG(MSC_CHN(drive)) & MSC_IREG_DATA_TRAN_DONE)) |
899 | yield(); | ||
921 | REG_MSC_IREG(MSC_CHN(drive)) = MSC_IREG_DATA_TRAN_DONE; /* clear status */ | 900 | REG_MSC_IREG(MSC_CHN(drive)) = MSC_IREG_DATA_TRAN_DONE; /* clear status */ |
922 | } | 901 | } |
923 | 902 | ||
@@ -926,7 +905,8 @@ static int jz_sd_exec_cmd(const int drive, struct sd_request *request) | |||
926 | { | 905 | { |
927 | //__intc_unmask_irq(IRQ_MSC); | 906 | //__intc_unmask_irq(IRQ_MSC); |
928 | //semaphore_wait(&sd_wakeup, 100); | 907 | //semaphore_wait(&sd_wakeup, 100); |
929 | while (!(REG_MSC_IREG(MSC_CHN(drive)) & MSC_IREG_PRG_DONE)); | 908 | while (!(REG_MSC_IREG(MSC_CHN(drive)) & MSC_IREG_PRG_DONE)) |
909 | yield(); | ||
930 | REG_MSC_IREG(MSC_CHN(drive)) = MSC_IREG_PRG_DONE; /* clear status */ | 910 | REG_MSC_IREG(MSC_CHN(drive)) = MSC_IREG_PRG_DONE; /* clear status */ |
931 | } | 911 | } |
932 | 912 | ||
@@ -986,10 +966,12 @@ static void jz_sd_hardware_init(const int drive) | |||
986 | jz_sd_stop_clock(drive); /* stop SD clock */ | 966 | jz_sd_stop_clock(drive); /* stop SD clock */ |
987 | } | 967 | } |
988 | 968 | ||
989 | static int sd_send_cmd(const int drive, struct sd_request *request, int cmd, unsigned int arg, | 969 | static void sd_send_cmd(const int drive, struct sd_request *request, int cmd, unsigned int arg, |
990 | unsigned short nob, unsigned short block_len, | 970 | unsigned short nob, unsigned short block_len, |
991 | enum sd_rsp_t rtype, unsigned char* buffer) | 971 | enum sd_rsp_t rtype, unsigned char* buffer) |
992 | { | 972 | { |
973 | int retval; | ||
974 | |||
993 | request->cmd = cmd; | 975 | request->cmd = cmd; |
994 | request->arg = arg; | 976 | request->arg = arg; |
995 | request->rtype = rtype; | 977 | request->rtype = rtype; |
@@ -998,7 +980,9 @@ static int sd_send_cmd(const int drive, struct sd_request *request, int cmd, uns | |||
998 | request->buffer = buffer; | 980 | request->buffer = buffer; |
999 | request->cnt = nob * block_len; | 981 | request->cnt = nob * block_len; |
1000 | 982 | ||
1001 | return jz_sd_exec_cmd(drive, request); | 983 | retval = jz_sd_exec_cmd(drive, request); |
984 | if (retval) | ||
985 | request->result = retval; | ||
1002 | } | 986 | } |
1003 | 987 | ||
1004 | static void sd_simple_cmd(const int drive, struct sd_request *request, int cmd, unsigned int arg, | 988 | static void sd_simple_cmd(const int drive, struct sd_request *request, int cmd, unsigned int arg, |
@@ -1007,6 +991,23 @@ static void sd_simple_cmd(const int drive, struct sd_request *request, int cmd, | |||
1007 | sd_send_cmd(drive, request, cmd, arg, 0, 0, rtype, NULL); | 991 | sd_send_cmd(drive, request, cmd, arg, 0, 0, rtype, NULL); |
1008 | } | 992 | } |
1009 | 993 | ||
994 | static int sd_exec_acmd(const int drive, struct sd_request *request, int cmd, unsigned int arg) | ||
995 | { | ||
996 | struct sd_response_r1 r1; | ||
997 | int retval; | ||
998 | |||
999 | sd_simple_cmd(drive, request, SD_APP_CMD, card[drive].rca, RESPONSE_R1); | ||
1000 | retval = sd_unpack_r1(request, &r1); | ||
1001 | |||
1002 | if (!retval) | ||
1003 | { | ||
1004 | sd_simple_cmd(drive, request, cmd, arg, RESPONSE_R1); | ||
1005 | retval = sd_unpack_r1(request, &r1); | ||
1006 | } | ||
1007 | |||
1008 | return retval; | ||
1009 | } | ||
1010 | |||
1010 | #define SD_INIT_DOING 0 | 1011 | #define SD_INIT_DOING 0 |
1011 | #define SD_INIT_PASSED 1 | 1012 | #define SD_INIT_PASSED 1 |
1012 | #define SD_INIT_FAILED 2 | 1013 | #define SD_INIT_FAILED 2 |
@@ -1014,7 +1015,7 @@ static int sd_init_card_state(const int drive, struct sd_request *request) | |||
1014 | { | 1015 | { |
1015 | struct sd_response_r1 r1; | 1016 | struct sd_response_r1 r1; |
1016 | struct sd_response_r3 r3; | 1017 | struct sd_response_r3 r3; |
1017 | int retval, i, ocr = 0x40300000, limit_41 = 0; | 1018 | int retval, i, ocr = 0x40300000; |
1018 | 1019 | ||
1019 | switch (request->cmd) | 1020 | switch (request->cmd) |
1020 | { | 1021 | { |
@@ -1028,28 +1029,15 @@ static int sd_init_card_state(const int drive, struct sd_request *request) | |||
1028 | break; | 1029 | break; |
1029 | 1030 | ||
1030 | case SD_APP_CMD: | 1031 | case SD_APP_CMD: |
1031 | retval = sd_unpack_r1(request, &r1); | 1032 | if (sd_unpack_r1(request, &r1)) |
1032 | if (retval & (limit_41 < 100)) | 1033 | return SD_INIT_FAILED; |
1033 | { | 1034 | sd_simple_cmd(drive, request, SD_APP_OP_COND, ocr, RESPONSE_R3); |
1034 | DEBUG("sd_init_card_state: unable to SD_APP_CMD error=%d", | ||
1035 | retval); | ||
1036 | limit_41++; | ||
1037 | sd_simple_cmd(drive, request, SD_APP_OP_COND, ocr, RESPONSE_R3); | ||
1038 | } | ||
1039 | else if (limit_41 < 100) | ||
1040 | { | ||
1041 | limit_41++; | ||
1042 | sd_simple_cmd(drive, request, SD_APP_OP_COND, ocr, RESPONSE_R3); | ||
1043 | } | ||
1044 | else | ||
1045 | /* reset the card to idle*/ | ||
1046 | sd_simple_cmd(drive, request, SD_GO_IDLE_STATE, 0, RESPONSE_NONE); | ||
1047 | break; | 1035 | break; |
1048 | 1036 | ||
1049 | case SD_APP_OP_COND: | 1037 | case SD_APP_OP_COND: |
1050 | retval = sd_unpack_r3(request, &r3); | 1038 | retval = sd_unpack_r3(request, &r3); |
1051 | if (retval) | 1039 | if (retval) |
1052 | break; | 1040 | return SD_INIT_FAILED; |
1053 | 1041 | ||
1054 | DEBUG("sd_init_card_state: read ocr value = 0x%08x", r3.ocr); | 1042 | DEBUG("sd_init_card_state: read ocr value = 0x%08x", r3.ocr); |
1055 | card[drive].ocr = r3.ocr; | 1043 | card[drive].ocr = r3.ocr; |
@@ -1068,20 +1056,24 @@ static int sd_init_card_state(const int drive, struct sd_request *request) | |||
1068 | break; | 1056 | break; |
1069 | 1057 | ||
1070 | case SD_ALL_SEND_CID: | 1058 | case SD_ALL_SEND_CID: |
1059 | if (request->result) | ||
1060 | return SD_INIT_FAILED; | ||
1061 | |||
1071 | for(i=0; i<4; i++) | 1062 | for(i=0; i<4; i++) |
1072 | card[drive].cid[i] = ((request->response[1+i*4]<<24) | (request->response[2+i*4]<<16) | | 1063 | card[drive].cid[i] = ((request->response[1+i*4]<<24) | (request->response[2+i*4]<<16) | |
1073 | (request->response[3+i*4]<< 8) | request->response[4+i*4]); | 1064 | (request->response[3+i*4]<< 8) | request->response[4+i*4]); |
1074 | 1065 | ||
1075 | logf("CID: %08lx%08lx%08lx%08lx", card[drive].cid[0], card[drive].cid[1], card[drive].cid[2], card[drive].cid[3]); | 1066 | logf("CID: %08lx%08lx%08lx%08lx", card[drive].cid[0], card[drive].cid[1], card[drive].cid[2], card[drive].cid[3]); |
1076 | sd_simple_cmd(drive, request, SD_SEND_RELATIVE_ADDR, 0, RESPONSE_R6); | 1067 | sd_simple_cmd(drive, request, SD_SEND_RELATIVE_ADDR, 0, RESPONSE_R6); |
1077 | break; | 1068 | break; |
1069 | |||
1078 | case SD_SEND_RELATIVE_ADDR: | 1070 | case SD_SEND_RELATIVE_ADDR: |
1079 | retval = sd_unpack_r6(request, &r1, &card[drive].rca); | 1071 | retval = sd_unpack_r6(request, &r1, &card[drive].rca); |
1080 | card[drive].rca = card[drive].rca << 16; | 1072 | card[drive].rca = card[drive].rca << 16; |
1081 | DEBUG("sd_init_card_state: Get RCA from SD: 0x%04lx Status: %x", card[drive].rca, r1.status); | 1073 | DEBUG("sd_init_card_state: Get RCA from SD: 0x%04lx Status: %x", card[drive].rca, r1.status); |
1082 | if (retval) | 1074 | if (retval) |
1083 | { | 1075 | { |
1084 | DEBUG("sd_init_card_state: unable to SET_RELATIVE_ADDR error=%d", | 1076 | DEBUG("sd_init_card_state: unable to SET_RELATIVE_ADDR error=%d", |
1085 | retval); | 1077 | retval); |
1086 | return SD_INIT_FAILED; | 1078 | return SD_INIT_FAILED; |
1087 | } | 1079 | } |
@@ -1090,8 +1082,10 @@ static int sd_init_card_state(const int drive, struct sd_request *request) | |||
1090 | break; | 1082 | break; |
1091 | 1083 | ||
1092 | case SD_SEND_CSD: | 1084 | case SD_SEND_CSD: |
1085 | if (request->result) | ||
1086 | return SD_INIT_FAILED; | ||
1093 | for(i=0; i<4; i++) | 1087 | for(i=0; i<4; i++) |
1094 | card[drive].csd[i] = ((request->response[1+i*4]<<24) | (request->response[2+i*4]<<16) | | 1088 | card[drive].csd[i] = ((request->response[1+i*4]<<24) | (request->response[2+i*4]<<16) | |
1095 | (request->response[3+i*4]<< 8) | request->response[4+i*4]); | 1089 | (request->response[3+i*4]<< 8) | request->response[4+i*4]); |
1096 | 1090 | ||
1097 | sd_parse_csd(&card[drive]); | 1091 | sd_parse_csd(&card[drive]); |
@@ -1120,7 +1114,7 @@ static int sd_switch(const int drive, struct sd_request *request, int mode, int | |||
1120 | arg = (mode << 31 | 0x00FFFFFF); | 1114 | arg = (mode << 31 | 0x00FFFFFF); |
1121 | arg &= ~(0xF << (group * 4)); | 1115 | arg &= ~(0xF << (group * 4)); |
1122 | arg |= value << (group * 4); | 1116 | arg |= value << (group * 4); |
1123 | sd_send_cmd(drive, request, 6, arg, 1, 64, RESPONSE_R1, resp); | 1117 | sd_send_cmd(drive, request, SD_SWITCH_FUNC, arg, 1, 64, RESPONSE_R1, resp); |
1124 | 1118 | ||
1125 | return 0; | 1119 | return 0; |
1126 | } | 1120 | } |
@@ -1137,7 +1131,7 @@ static int sd_read_switch(const int drive, struct sd_request *request) | |||
1137 | 1131 | ||
1138 | if (((unsigned char *)status)[13] & 0x02) | 1132 | if (((unsigned char *)status)[13] & 0x02) |
1139 | return 0; | 1133 | return 0; |
1140 | else | 1134 | else |
1141 | return 1; | 1135 | return 1; |
1142 | } | 1136 | } |
1143 | 1137 | ||
@@ -1174,13 +1168,10 @@ static int sd_select_card(const int drive) | |||
1174 | } | 1168 | } |
1175 | } | 1169 | } |
1176 | num_6[drive] = 3; | 1170 | num_6[drive] = 3; |
1177 | sd_simple_cmd(drive, &request, SD_APP_CMD, card[drive].rca, | 1171 | retval = sd_exec_acmd(drive, &request, SD_SET_BUS_WIDTH, 2); |
1178 | RESPONSE_R1); | ||
1179 | retval = sd_unpack_r1(&request, &r1); | ||
1180 | if (retval) | 1172 | if (retval) |
1181 | return retval; | 1173 | return retval; |
1182 | sd_simple_cmd(drive, &request, SD_SET_BUS_WIDTH, 2, RESPONSE_R1); | 1174 | retval = sd_exec_acmd(drive, &request, SD_SET_CLR_CARD_DETECT, 0); |
1183 | retval = sd_unpack_r1(&request, &r1); | ||
1184 | if (retval) | 1175 | if (retval) |
1185 | return retval; | 1176 | return retval; |
1186 | 1177 | ||
@@ -1192,8 +1183,8 @@ static int sd_select_card(const int drive) | |||
1192 | static int sd_init_device(const int drive) | 1183 | static int sd_init_device(const int drive) |
1193 | { | 1184 | { |
1194 | int retval = 0; | 1185 | int retval = 0; |
1186 | long deadline; | ||
1195 | struct sd_request init_req; | 1187 | struct sd_request init_req; |
1196 | register int timeout = 1000; | ||
1197 | 1188 | ||
1198 | mutex_lock(&sd_mtx); | 1189 | mutex_lock(&sd_mtx); |
1199 | 1190 | ||
@@ -1212,7 +1203,11 @@ static int sd_init_device(const int drive) | |||
1212 | 1203 | ||
1213 | sleep(HZ/2); /* Give the card/controller some rest */ | 1204 | sleep(HZ/2); /* Give the card/controller some rest */ |
1214 | 1205 | ||
1215 | while(timeout-- && ((retval = sd_init_card_state(drive, &init_req)) == SD_INIT_DOING)); | 1206 | deadline = current_tick + HZ; |
1207 | do { | ||
1208 | retval = sd_init_card_state(drive, &init_req); | ||
1209 | } while (TIME_BEFORE(current_tick, deadline) && (retval == SD_INIT_DOING)); | ||
1210 | |||
1216 | retval = (retval == SD_INIT_PASSED ? sd_select_card(drive) : -1); | 1211 | retval = (retval == SD_INIT_PASSED ? sd_select_card(drive) : -1); |
1217 | 1212 | ||
1218 | if (drive == SD_SLOT_1) | 1213 | if (drive == SD_SLOT_1) |
@@ -1238,8 +1233,17 @@ int sd_init(void) | |||
1238 | 1233 | ||
1239 | if(!inited) | 1234 | if(!inited) |
1240 | { | 1235 | { |
1241 | // semaphore_init(&sd_wakeup, 1, 0); | 1236 | |
1237 | #if SD_DMA_INTERRUPT | ||
1238 | semaphore_init(&sd_wakeup, 1, 0); | ||
1239 | #endif | ||
1242 | mutex_init(&sd_mtx); | 1240 | mutex_init(&sd_mtx); |
1241 | |||
1242 | #if SD_DMA_ENABLE && SD_DMA_INTERRUPT | ||
1243 | system_enable_irq(DMA_IRQ(DMA_SD_RX_CHANNEL)); | ||
1244 | system_enable_irq(DMA_IRQ(DMA_SD_TX_CHANNEL)); | ||
1245 | #endif | ||
1246 | |||
1243 | inited = true; | 1247 | inited = true; |
1244 | } | 1248 | } |
1245 | 1249 | ||
@@ -1279,107 +1283,63 @@ static inline void sd_stop_transfer(const int drive) | |||
1279 | mutex_unlock(&sd_mtx); | 1283 | mutex_unlock(&sd_mtx); |
1280 | } | 1284 | } |
1281 | 1285 | ||
1282 | int sd_read_sectors(const int drive, unsigned long start, int count, void* buf) | 1286 | int sd_transfer_sectors(IF_MD(const int drive,) unsigned long start, int count, void* buf, bool write) |
1283 | { | 1287 | { |
1284 | sd_start_transfer(drive); | ||
1285 | |||
1286 | struct sd_request request; | 1288 | struct sd_request request; |
1287 | struct sd_response_r1 r1; | 1289 | struct sd_response_r1 r1; |
1288 | int retval = -1; | 1290 | int retval = -1; |
1291 | #ifndef HAVE_MULTIDRIVE | ||
1292 | const int drive = 0; | ||
1293 | #endif | ||
1289 | 1294 | ||
1290 | if (!card_detect_target(drive) || count == 0 || start > card[drive].numblocks) | 1295 | sd_start_transfer(drive); |
1296 | |||
1297 | if (!card_detect_target(drive) || count < 1 || (start + count) > card[drive].numblocks) | ||
1291 | goto err; | 1298 | goto err; |
1292 | 1299 | ||
1293 | if(card[drive].initialized == 0 && !sd_init_device(drive)) | 1300 | if(card[drive].initialized == 0 && !sd_init_device(drive)) |
1294 | goto err; | 1301 | goto err; |
1295 | 1302 | ||
1296 | sd_simple_cmd(drive, &request, SD_SEND_STATUS, card[drive].rca, RESPONSE_R1); | 1303 | sd_simple_cmd(drive, &request, SD_SEND_STATUS, card[drive].rca, RESPONSE_R1); |
1297 | retval = sd_unpack_r1(&request, &r1); | 1304 | if ((retval = sd_unpack_r1(&request, &r1))) |
1298 | if (retval && (retval != SD_ERROR_STATE_MISMATCH)) | ||
1299 | goto err; | 1305 | goto err; |
1300 | 1306 | ||
1301 | sd_simple_cmd(drive, &request, SD_SET_BLOCKLEN, SD_BLOCK_SIZE, RESPONSE_R1); | 1307 | sd_simple_cmd(drive, &request, SD_SET_BLOCKLEN, SD_BLOCK_SIZE, RESPONSE_R1); |
1302 | if ((retval = sd_unpack_r1(&request, &r1))) | 1308 | if ((retval = sd_unpack_r1(&request, &r1))) |
1303 | goto err; | 1309 | goto err; |
1304 | 1310 | ||
1305 | if (sd2_0[drive]) | 1311 | sd_send_cmd(drive, &request, |
1306 | { | 1312 | (count > 1) ? |
1307 | sd_send_cmd(drive, &request, SD_READ_MULTIPLE_BLOCK, start, | 1313 | (write ? SD_WRITE_MULTIPLE_BLOCK : SD_READ_MULTIPLE_BLOCK) : |
1308 | count, SD_BLOCK_SIZE, RESPONSE_R1, buf); | 1314 | (write ? SD_WRITE_BLOCK : SD_READ_SINGLE_BLOCK), |
1309 | if ((retval = sd_unpack_r1(&request, &r1))) | 1315 | sd2_0[drive] ? start : (start * SD_BLOCK_SIZE), |
1310 | goto err; | 1316 | count, SD_BLOCK_SIZE, RESPONSE_R1, buf); |
1311 | } | ||
1312 | else | ||
1313 | { | ||
1314 | sd_send_cmd(drive, &request, SD_READ_MULTIPLE_BLOCK, | ||
1315 | start * SD_BLOCK_SIZE, count, | ||
1316 | SD_BLOCK_SIZE, RESPONSE_R1, buf); | ||
1317 | if ((retval = sd_unpack_r1(&request, &r1))) | ||
1318 | goto err; | ||
1319 | } | ||
1320 | |||
1321 | last_disk_activity = current_tick; | ||
1322 | |||
1323 | sd_simple_cmd(drive, &request, SD_STOP_TRANSMISSION, 0, RESPONSE_R1B); | ||
1324 | if ((retval = sd_unpack_r1(&request, &r1))) | 1317 | if ((retval = sd_unpack_r1(&request, &r1))) |
1325 | goto err; | 1318 | goto err; |
1326 | 1319 | ||
1320 | if (count > 1) | ||
1321 | { | ||
1322 | sd_simple_cmd(drive, &request, SD_STOP_TRANSMISSION, 0, RESPONSE_R1B); | ||
1323 | retval = sd_unpack_r1(&request, &r1); | ||
1324 | if (!write && retval == SD_ERROR_OUT_OF_RANGE) | ||
1325 | retval = 0; | ||
1326 | } | ||
1327 | |||
1327 | err: | 1328 | err: |
1329 | last_disk_activity = current_tick; | ||
1328 | sd_stop_transfer(drive); | 1330 | sd_stop_transfer(drive); |
1329 | 1331 | ||
1330 | return retval; | 1332 | return retval; |
1331 | } | 1333 | } |
1332 | 1334 | ||
1333 | int sd_write_sectors(const int drive, unsigned long start, int count, const void* buf) | 1335 | int sd_read_sectors(IF_MD(int drive,) unsigned long start, int count, void* buf) |
1334 | { | 1336 | { |
1335 | sd_start_transfer(drive); | 1337 | return sd_transfer_sectors(IF_MD(drive,) start, count, buf, false); |
1336 | 1338 | } | |
1337 | struct sd_request request; | ||
1338 | struct sd_response_r1 r1; | ||
1339 | int retval = -1; | ||
1340 | |||
1341 | if (!card_detect_target(drive) || count == 0 || start > card[drive].numblocks) | ||
1342 | goto err; | ||
1343 | |||
1344 | if(card[drive].initialized == 0 && !sd_init_device(drive)) | ||
1345 | goto err; | ||
1346 | |||
1347 | sd_simple_cmd(drive, &request, SD_SEND_STATUS, card[drive].rca, RESPONSE_R1); | ||
1348 | retval = sd_unpack_r1(&request, &r1); | ||
1349 | if (retval && (retval != SD_ERROR_STATE_MISMATCH)) | ||
1350 | goto err; | ||
1351 | |||
1352 | sd_simple_cmd(drive, &request, SD_SET_BLOCKLEN, SD_BLOCK_SIZE, RESPONSE_R1); | ||
1353 | if ((retval = sd_unpack_r1(&request, &r1))) | ||
1354 | goto err; | ||
1355 | |||
1356 | if (sd2_0[drive]) | ||
1357 | { | ||
1358 | sd_send_cmd(drive, &request, SD_WRITE_MULTIPLE_BLOCK, start, | ||
1359 | count, SD_BLOCK_SIZE, RESPONSE_R1, | ||
1360 | (void*)buf); | ||
1361 | if ((retval = sd_unpack_r1(&request, &r1))) | ||
1362 | goto err; | ||
1363 | } | ||
1364 | else | ||
1365 | { | ||
1366 | sd_send_cmd(drive, &request, SD_WRITE_MULTIPLE_BLOCK, | ||
1367 | start * SD_BLOCK_SIZE, count, | ||
1368 | SD_BLOCK_SIZE, RESPONSE_R1, (void*)buf); | ||
1369 | if ((retval = sd_unpack_r1(&request, &r1))) | ||
1370 | goto err; | ||
1371 | } | ||
1372 | |||
1373 | last_disk_activity = current_tick; | ||
1374 | |||
1375 | sd_simple_cmd(drive, &request, SD_STOP_TRANSMISSION, 0, RESPONSE_R1B); | ||
1376 | if ((retval = sd_unpack_r1(&request, &r1))) | ||
1377 | goto err; | ||
1378 | |||
1379 | err: | ||
1380 | sd_stop_transfer(drive); | ||
1381 | 1339 | ||
1382 | return retval; | 1340 | int sd_write_sectors(IF_MD(int drive,) unsigned long start, int count, const void* buf) |
1341 | { | ||
1342 | return sd_transfer_sectors(IF_MD(drive,) start, count, (void*)buf, true); | ||
1383 | } | 1343 | } |
1384 | 1344 | ||
1385 | long sd_last_disk_activity(void) | 1345 | long sd_last_disk_activity(void) |
@@ -1474,8 +1434,8 @@ int sd_event(long id, intptr_t data) | |||
1474 | * clear if the last attempt to init failed with an error. */ | 1434 | * clear if the last attempt to init failed with an error. */ |
1475 | mutex_lock(&sd_mtx); /* lock-out card activity */ | 1435 | mutex_lock(&sd_mtx); /* lock-out card activity */ |
1476 | card[data].initialized = 0; | 1436 | card[data].initialized = 0; |
1477 | if (id == SYS_HOTSWAP_INSERTED) | 1437 | // if (id == SYS_HOTSWAP_INSERTED) |
1478 | sd_init_device(data); | 1438 | // sd_init_device(data); |
1479 | mutex_unlock(&sd_mtx); | 1439 | mutex_unlock(&sd_mtx); |
1480 | break; | 1440 | break; |
1481 | #endif /* HAVE_HOTSWAP */ | 1441 | #endif /* HAVE_HOTSWAP */ |