diff options
Diffstat (limited to 'firmware/target/arm/tcc780x/sd-tcc780x.c')
-rw-r--r-- | firmware/target/arm/tcc780x/sd-tcc780x.c | 94 |
1 files changed, 48 insertions, 46 deletions
diff --git a/firmware/target/arm/tcc780x/sd-tcc780x.c b/firmware/target/arm/tcc780x/sd-tcc780x.c index c80c3b746f..3ef8972ee9 100644 --- a/firmware/target/arm/tcc780x/sd-tcc780x.c +++ b/firmware/target/arm/tcc780x/sd-tcc780x.c | |||
@@ -104,19 +104,19 @@ static bool sd_poll_status(unsigned int trigger, long timeout) | |||
104 | return true; | 104 | return true; |
105 | } | 105 | } |
106 | 106 | ||
107 | static int sd_command(unsigned int cmd, unsigned int arg, | 107 | static int sd_command(unsigned int cmd, unsigned int arg, |
108 | unsigned long* response, unsigned int resp_type) | 108 | unsigned long* response, unsigned int resp_type) |
109 | { | 109 | { |
110 | int sdi_cmd = cmd; | 110 | int sdi_cmd = cmd; |
111 | 111 | ||
112 | sdi_cmd |= (127<<12) | (1<<11); /* max wait time | enable */ | 112 | sdi_cmd |= (127<<12) | (1<<11); /* max wait time | enable */ |
113 | 113 | ||
114 | if (resp_type) | 114 | if (resp_type) |
115 | { | 115 | { |
116 | /* response type & response required flag */ | 116 | /* response type & response required flag */ |
117 | sdi_cmd |= (resp_type<<7) | (1<<6); | 117 | sdi_cmd |= (resp_type<<7) | (1<<6); |
118 | } | 118 | } |
119 | 119 | ||
120 | if (cmd == SD_READ_SINGLE_BLOCK || | 120 | if (cmd == SD_READ_SINGLE_BLOCK || |
121 | cmd == SD_READ_MULTIPLE_BLOCK || | 121 | cmd == SD_READ_MULTIPLE_BLOCK || |
122 | cmd == SD_WRITE_BLOCK || | 122 | cmd == SD_WRITE_BLOCK || |
@@ -124,18 +124,18 @@ static int sd_command(unsigned int cmd, unsigned int arg, | |||
124 | { | 124 | { |
125 | sdi_cmd |= (1<<10); /* request data transfer */ | 125 | sdi_cmd |= (1<<10); /* request data transfer */ |
126 | } | 126 | } |
127 | 127 | ||
128 | if (!sd_poll_status(SDISTATUS_CMD_PATH_RDY, 100000)) | 128 | if (!sd_poll_status(SDISTATUS_CMD_PATH_RDY, 100000)) |
129 | return -EC_COMMAND; | 129 | return -EC_COMMAND; |
130 | 130 | ||
131 | SDIARGU = arg; | 131 | SDIARGU = arg; |
132 | SDICMD = sdi_cmd; | 132 | SDICMD = sdi_cmd; |
133 | 133 | ||
134 | udelay(10); | 134 | udelay(10); |
135 | 135 | ||
136 | if (response == NULL) | 136 | if (response == NULL) |
137 | return 0; | 137 | return 0; |
138 | 138 | ||
139 | if (!sd_poll_status(SDISTATUS_RESP_RCVD, 100000)) | 139 | if (!sd_poll_status(SDISTATUS_RESP_RCVD, 100000)) |
140 | return -EC_COMMAND; | 140 | return -EC_COMMAND; |
141 | 141 | ||
@@ -150,7 +150,7 @@ static int sd_command(unsigned int cmd, unsigned int arg, | |||
150 | { | 150 | { |
151 | response[0] = SDIRSPARGU0; | 151 | response[0] = SDIRSPARGU0; |
152 | } | 152 | } |
153 | 153 | ||
154 | return 0; | 154 | return 0; |
155 | } | 155 | } |
156 | 156 | ||
@@ -220,7 +220,7 @@ static int sd1_oneshot_callback(struct timeout *tmo) | |||
220 | void EXT0(void) | 220 | void EXT0(void) |
221 | { | 221 | { |
222 | static struct timeout sd1_oneshot; | 222 | static struct timeout sd1_oneshot; |
223 | 223 | ||
224 | timeout_register(&sd1_oneshot, sd1_oneshot_callback, (3*HZ/10), 0); | 224 | timeout_register(&sd1_oneshot, sd1_oneshot_callback, (3*HZ/10), 0); |
225 | } | 225 | } |
226 | 226 | ||
@@ -248,7 +248,7 @@ bool sd_removable(IF_MD_NONVOID(int card_no)) | |||
248 | const int card_no = 0; | 248 | const int card_no = 0; |
249 | #endif | 249 | #endif |
250 | (void)card_no; | 250 | (void)card_no; |
251 | 251 | ||
252 | return false; | 252 | return false; |
253 | } | 253 | } |
254 | 254 | ||
@@ -259,7 +259,7 @@ static void sd_init_device(int card_no) | |||
259 | { | 259 | { |
260 | int ret; | 260 | int ret; |
261 | unsigned long response; | 261 | unsigned long response; |
262 | 262 | ||
263 | /* Initialise card data as blank */ | 263 | /* Initialise card data as blank */ |
264 | memset(currcard, 0, sizeof(*currcard)); | 264 | memset(currcard, 0, sizeof(*currcard)); |
265 | 265 | ||
@@ -282,7 +282,7 @@ static void sd_init_device(int card_no) | |||
282 | #endif | 282 | #endif |
283 | 283 | ||
284 | ret = sd_command(SD_GO_IDLE_STATE, 0, NULL, SDICMD_RES_TYPE1); | 284 | ret = sd_command(SD_GO_IDLE_STATE, 0, NULL, SDICMD_RES_TYPE1); |
285 | 285 | ||
286 | if (ret < 0) | 286 | if (ret < 0) |
287 | goto card_init_error; | 287 | goto card_init_error; |
288 | 288 | ||
@@ -290,30 +290,30 @@ static void sd_init_device(int card_no) | |||
290 | SDICLK = (1<<12) | 59; | 290 | SDICLK = (1<<12) | 59; |
291 | 291 | ||
292 | sd_command(SD_SEND_IF_COND, 0x1aa, &response, SDICMD_RES_TYPE3); | 292 | sd_command(SD_SEND_IF_COND, 0x1aa, &response, SDICMD_RES_TYPE3); |
293 | 293 | ||
294 | if (!sd_poll_status(SDISTATUS_CMD_PATH_RDY, 100000)) | 294 | if (!sd_poll_status(SDISTATUS_CMD_PATH_RDY, 100000)) |
295 | goto card_init_error; | 295 | goto card_init_error; |
296 | 296 | ||
297 | currcard->ocr = 0; | 297 | currcard->ocr = 0; |
298 | 298 | ||
299 | long start_tick = current_tick; | 299 | long start_tick = current_tick; |
300 | 300 | ||
301 | while ((currcard->ocr & (1<<31)) == 0 | 301 | while ((currcard->ocr & (1<<31)) == 0 |
302 | && TIME_BEFORE(current_tick, start_tick + HZ)) | 302 | && TIME_BEFORE(current_tick, start_tick + HZ)) |
303 | { | 303 | { |
304 | udelay(100); | 304 | udelay(100); |
305 | sd_command(SD_APP_CMD, 0, NULL, SDICMD_RES_TYPE1); | 305 | sd_command(SD_APP_CMD, 0, NULL, SDICMD_RES_TYPE1); |
306 | 306 | ||
307 | int arg = 0x100000 | ((response == 0x1aa) ? (1<<30):0); | 307 | int arg = 0x100000 | ((response == 0x1aa) ? (1<<30):0); |
308 | sd_command(SD_APP_OP_COND, arg, &currcard->ocr, SDICMD_RES_TYPE3); | 308 | sd_command(SD_APP_OP_COND, arg, &currcard->ocr, SDICMD_RES_TYPE3); |
309 | } | 309 | } |
310 | 310 | ||
311 | if ((currcard->ocr & (1<<31)) == 0) | 311 | if ((currcard->ocr & (1<<31)) == 0) |
312 | { | 312 | { |
313 | ret = -EC_POWER_UP; | 313 | ret = -EC_POWER_UP; |
314 | goto card_init_error; | 314 | goto card_init_error; |
315 | } | 315 | } |
316 | 316 | ||
317 | ret = sd_command | 317 | ret = sd_command |
318 | (SD_ALL_SEND_CID, 0, currcard->cid, SDICMD_RES_TYPE2); | 318 | (SD_ALL_SEND_CID, 0, currcard->cid, SDICMD_RES_TYPE2); |
319 | 319 | ||
@@ -322,39 +322,39 @@ static void sd_init_device(int card_no) | |||
322 | 322 | ||
323 | ret = sd_command | 323 | ret = sd_command |
324 | (SD_SEND_RELATIVE_ADDR, 0, &currcard->rca, SDICMD_RES_TYPE1); | 324 | (SD_SEND_RELATIVE_ADDR, 0, &currcard->rca, SDICMD_RES_TYPE1); |
325 | 325 | ||
326 | if (ret < 0) | 326 | if (ret < 0) |
327 | goto card_init_error; | 327 | goto card_init_error; |
328 | 328 | ||
329 | ret = sd_command | 329 | ret = sd_command |
330 | (SD_SEND_CSD, currcard->rca, currcard->csd, SDICMD_RES_TYPE2); | 330 | (SD_SEND_CSD, currcard->rca, currcard->csd, SDICMD_RES_TYPE2); |
331 | 331 | ||
332 | if (ret < 0) | 332 | if (ret < 0) |
333 | goto card_init_error; | 333 | goto card_init_error; |
334 | 334 | ||
335 | sd_parse_csd(currcard); | 335 | sd_parse_csd(currcard); |
336 | 336 | ||
337 | ret = sd_command | 337 | ret = sd_command |
338 | (SD_SELECT_CARD, currcard->rca, NULL, SDICMD_RES_TYPE1); | 338 | (SD_SELECT_CARD, currcard->rca, NULL, SDICMD_RES_TYPE1); |
339 | 339 | ||
340 | if (ret < 0) | 340 | if (ret < 0) |
341 | goto card_init_error; | 341 | goto card_init_error; |
342 | 342 | ||
343 | ret = sd_command | 343 | ret = sd_command |
344 | (SD_APP_CMD, currcard->rca, NULL, SDICMD_RES_TYPE1); | 344 | (SD_APP_CMD, currcard->rca, NULL, SDICMD_RES_TYPE1); |
345 | 345 | ||
346 | if (ret < 0) | 346 | if (ret < 0) |
347 | goto card_init_error; | 347 | goto card_init_error; |
348 | 348 | ||
349 | ret = sd_command /* 4 bit */ | 349 | ret = sd_command /* 4 bit */ |
350 | (SD_SET_BUS_WIDTH, currcard->rca | 2, NULL, SDICMD_RES_TYPE1); | 350 | (SD_SET_BUS_WIDTH, currcard->rca | 2, NULL, SDICMD_RES_TYPE1); |
351 | 351 | ||
352 | if (ret < 0) | 352 | if (ret < 0) |
353 | goto card_init_error; | 353 | goto card_init_error; |
354 | 354 | ||
355 | ret = sd_command | 355 | ret = sd_command |
356 | (SD_SET_BLOCKLEN, currcard->blocksize, NULL, SDICMD_RES_TYPE1); | 356 | (SD_SET_BLOCKLEN, currcard->blocksize, NULL, SDICMD_RES_TYPE1); |
357 | 357 | ||
358 | if (ret < 0) | 358 | if (ret < 0) |
359 | goto card_init_error; | 359 | goto card_init_error; |
360 | 360 | ||
@@ -386,7 +386,7 @@ static void sd_select_device(int card_no) | |||
386 | } | 386 | } |
387 | } | 387 | } |
388 | 388 | ||
389 | int sd_read_sectors(IF_MD(int card_no,) unsigned long start, int incount, | 389 | int sd_read_sectors(IF_MD(int card_no,) sector_t start, int incount, |
390 | void* inbuf) | 390 | void* inbuf) |
391 | { | 391 | { |
392 | #ifndef HAVE_MULTIDRIVE | 392 | #ifndef HAVE_MULTIDRIVE |
@@ -416,23 +416,24 @@ sd_read_retry: | |||
416 | ret = currcard->initialized; | 416 | ret = currcard->initialized; |
417 | goto sd_read_error; | 417 | goto sd_read_error; |
418 | } | 418 | } |
419 | 419 | ||
420 | last_disk_activity = current_tick; | 420 | last_disk_activity = current_tick; |
421 | 421 | ||
422 | ret = sd_wait_for_state(SD_TRAN, EC_TRAN_READ_ENTRY); | 422 | ret = sd_wait_for_state(SD_TRAN, EC_TRAN_READ_ENTRY); |
423 | 423 | ||
424 | if (ret < 0) | 424 | if (ret < 0) |
425 | goto sd_read_error; | 425 | goto sd_read_error; |
426 | 426 | ||
427 | /* Use full SD clock for data transfer (PCK_SDMMC) */ | 427 | /* Use full SD clock for data transfer (PCK_SDMMC) */ |
428 | SDICLK = (1<<13) | (1<<12); /* bypass divider | enable */ | 428 | SDICLK = (1<<13) | (1<<12); /* bypass divider | enable */ |
429 | 429 | ||
430 | /* Block count | FIFO count | Block size (2^9) | 4-bit bus */ | 430 | /* Block count | FIFO count | Block size (2^9) | 4-bit bus */ |
431 | SDIDCTRL = (incount << 13) | (4<<8) | (9<<4) | (1<<2); | 431 | SDIDCTRL = (incount << 13) | (4<<8) | (9<<4) | (1<<2); |
432 | SDIDCTRL |= (1<<12); /* nReset */ | 432 | SDIDCTRL |= (1<<12); /* nReset */ |
433 | 433 | ||
434 | SDIDCTRL2 = (1<<2); /* multi block, read */ | 434 | SDIDCTRL2 = (1<<2); /* multi block, read */ |
435 | 435 | ||
436 | // XXX 64-bit | ||
436 | if (currcard->ocr & (1<<30)) | 437 | if (currcard->ocr & (1<<30)) |
437 | ret = sd_command(SD_READ_MULTIPLE_BLOCK, start, NULL, SDICMD_RES_TYPE1); | 438 | ret = sd_command(SD_READ_MULTIPLE_BLOCK, start, NULL, SDICMD_RES_TYPE1); |
438 | else | 439 | else |
@@ -500,7 +501,7 @@ sd_read_error: | |||
500 | } | 501 | } |
501 | } | 502 | } |
502 | 503 | ||
503 | int sd_write_sectors(IF_MD(int card_no,) unsigned long start, int count, | 504 | int sd_write_sectors(IF_MD(int card_no,) sector_t start, int count, |
504 | const void* outbuf) | 505 | const void* outbuf) |
505 | { | 506 | { |
506 | /* Write support is not finished yet */ | 507 | /* Write support is not finished yet */ |
@@ -538,21 +539,22 @@ sd_write_retry: | |||
538 | ret = currcard->initialized; | 539 | ret = currcard->initialized; |
539 | goto sd_write_error; | 540 | goto sd_write_error; |
540 | } | 541 | } |
541 | 542 | ||
542 | ret = sd_wait_for_state(SD_TRAN, EC_TRAN_WRITE_ENTRY); | 543 | ret = sd_wait_for_state(SD_TRAN, EC_TRAN_WRITE_ENTRY); |
543 | 544 | ||
544 | if (ret < 0) | 545 | if (ret < 0) |
545 | goto sd_write_error; | 546 | goto sd_write_error; |
546 | 547 | ||
547 | /* Use full SD clock for data transfer (PCK_SDMMC) */ | 548 | /* Use full SD clock for data transfer (PCK_SDMMC) */ |
548 | SDICLK = (1<<13) | (1<<12); /* bypass divider | enable */ | 549 | SDICLK = (1<<13) | (1<<12); /* bypass divider | enable */ |
549 | 550 | ||
550 | /* Block count | FIFO count | Block size (2^9) | 4-bit bus */ | 551 | /* Block count | FIFO count | Block size (2^9) | 4-bit bus */ |
551 | SDIDCTRL = (count<<13) | (4<<8) | (9<<4) | (1<<2); | 552 | SDIDCTRL = (count<<13) | (4<<8) | (9<<4) | (1<<2); |
552 | SDIDCTRL |= (1<<12); /* nReset */ | 553 | SDIDCTRL |= (1<<12); /* nReset */ |
553 | 554 | ||
554 | SDIDCTRL2 = (1<<2) | (1<<1); /* multi block, write */ | 555 | SDIDCTRL2 = (1<<2) | (1<<1); /* multi block, write */ |
555 | 556 | ||
557 | // XXX 64-bit | ||
556 | if (currcard->ocr & (1<<30)) | 558 | if (currcard->ocr & (1<<30)) |
557 | ret = sd_command(SD_WRITE_MULTIPLE_BLOCK, start, NULL, SDICMD_RES_TYPE1); | 559 | ret = sd_command(SD_WRITE_MULTIPLE_BLOCK, start, NULL, SDICMD_RES_TYPE1); |
558 | else | 560 | else |
@@ -578,7 +580,7 @@ sd_write_retry: | |||
578 | else | 580 | else |
579 | { | 581 | { |
580 | int tmp_buf[4]; | 582 | int tmp_buf[4]; |
581 | 583 | ||
582 | memcpy(tmp_buf, outbuf, 16); | 584 | memcpy(tmp_buf, outbuf, 16); |
583 | 585 | ||
584 | SDIWDATA = tmp_buf[0]; | 586 | SDIWDATA = tmp_buf[0]; |
@@ -646,12 +648,12 @@ void sd_enable(bool on) | |||
646 | PCLK_SDMMC &= ~PCK_EN; | 648 | PCLK_SDMMC &= ~PCK_EN; |
647 | } | 649 | } |
648 | } | 650 | } |
649 | 651 | ||
650 | int sd_init(void) | 652 | int sd_init(void) |
651 | { | 653 | { |
652 | static bool initialized = false; | 654 | static bool initialized = false; |
653 | int ret = 0; | 655 | int ret = 0; |
654 | 656 | ||
655 | if (!initialized) | 657 | if (!initialized) |
656 | mutex_init(&sd_mtx); | 658 | mutex_init(&sd_mtx); |
657 | 659 | ||
@@ -678,7 +680,7 @@ int sd_init(void) | |||
678 | GPIOC_DIR |= (1<<24); | 680 | GPIOC_DIR |= (1<<24); |
679 | 681 | ||
680 | sleep(HZ/10); | 682 | sleep(HZ/10); |
681 | 683 | ||
682 | #ifdef HAVE_HOTSWAP | 684 | #ifdef HAVE_HOTSWAP |
683 | /* Configure interrupts for the card slot */ | 685 | /* Configure interrupts for the card slot */ |
684 | TMODE &= ~EXT0_IRQ_MASK; /* edge-triggered */ | 686 | TMODE &= ~EXT0_IRQ_MASK; /* edge-triggered */ |
@@ -696,7 +698,7 @@ long sd_last_disk_activity(void) | |||
696 | } | 698 | } |
697 | 699 | ||
698 | tCardInfo *card_get_info_target(int card_no) | 700 | tCardInfo *card_get_info_target(int card_no) |
699 | { | 701 | { |
700 | return &card_info[card_no]; | 702 | return &card_info[card_no]; |
701 | } | 703 | } |
702 | 704 | ||
@@ -706,7 +708,7 @@ int sd_num_drives(int first_drive) | |||
706 | { | 708 | { |
707 | /* Store which logical drive number(s) we have been assigned */ | 709 | /* Store which logical drive number(s) we have been assigned */ |
708 | sd_first_drive = first_drive; | 710 | sd_first_drive = first_drive; |
709 | 711 | ||
710 | #if defined(HAVE_INTERNAL_SD) && defined(HAVE_HOTSWAP) | 712 | #if defined(HAVE_INTERNAL_SD) && defined(HAVE_HOTSWAP) |
711 | return 2; | 713 | return 2; |
712 | #else | 714 | #else |