| 403 | static int sd_card_send_register_command( sd_card_driver_entry *e, uint32_t command, uint32_t argument, uint32_t *reg) |
| 404 | { |
| 405 | int rv = 0; |
| 406 | |
| 407 | rv = sd_card_send_command( e, command, argument); |
| 408 | RTEMS_CHECK_RV( rv, "Send command"); |
| 409 | |
| 410 | if (e->response_index + 5 > SD_CARD_COMMAND_SIZE) { |
| 411 | /* |
| 412 | * TODO: If this happens in the wild we need to implement a |
| 413 | * more sophisticated response query. |
| 414 | */ |
| 415 | RTEMS_SYSLOG_ERROR( "Unexpected response position\n"); |
| 416 | return -RTEMS_IO_ERROR; |
| 417 | } |
| 418 | |
| 419 | *reg = sd_card_get_uint32( e->response + e->response_index + 1); |
| 420 | |
| 421 | return 0; |
| 422 | } |
| 423 | |
| 668 | /* |
| 669 | * Get interface condition, CMD8. This is new for SD 2.x and enables |
| 670 | * getting the High Capacity Support flag HCS and checks that the |
| 671 | * voltage is right. Some MMCs accept this command but will still fail |
| 672 | * on ACMD41. SD 1.x cards will fails this command and do not support |
| 673 | * HCS (> 2G capacity). SD spec requires the correct CRC7 be sent even |
| 674 | * when in SPI mode. So this will just change the default CRC7 and |
| 675 | * keep it there for all subsequent commands (which just require a do |
| 676 | * not care CRC byte). |
| 677 | */ |
| 678 | SD_CARD_COMMAND_SET_CRC7( e->command, 0x43U); |
| 679 | rv = sd_card_send_register_command( e, SD_CARD_CMD_SEND_IF_COND, if_cond_reg, &if_cond_reg); |
| 680 | |
| 681 | /* |
| 682 | * Regardless of whether CMD8 above passes or fails, send ACMD41. If |
| 683 | * card is MMC it will fail. But older SD < 2.0 (which fail CMD8) will |
| 684 | * always stay "idle" if cmd_arg is non-zero, so set to 0 above on |
| 685 | * fail. |
| 686 | */ |
| 687 | if (rv < 0) { |
| 688 | /* Failed CMD8, so SD 1.x or MMC */ |
| 689 | cmd_arg = 0; |
| 690 | } else { |
| 691 | cmd_arg = SD_CARD_FLAG_HCS; |
| 692 | } |
| 693 | |
616 | | rv = sd_card_send_command( e, SD_CARD_CMD_APP_CMD, 0); |
617 | | RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_CMD_APP_CMD"); |
618 | | rv = sd_card_send_command( e, SD_CARD_ACMD_SD_SEND_OP_COND, 0); |
619 | | RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_ACMD_SD_SEND_OP_COND"); |
| 696 | if (assume_sd) { |
| 697 | /* This command (CMD55) supported by SD and (most?) MMCs */ |
| 698 | rv = sd_card_send_command( e, SD_CARD_CMD_APP_CMD, 0); |
| 699 | if (rv < 0) { |
| 700 | RTEMS_SYSLOG( "CMD55 failed. Assume MMC and try CMD1\n"); |
| 701 | assume_sd = false; |
| 702 | continue; |
| 703 | } |
| 704 | |
| 705 | /* |
| 706 | * This command (ACMD41) only supported by SD. Always |
| 707 | * fails if MMC. |
| 708 | */ |
| 709 | rv = sd_card_send_command( e, SD_CARD_ACMD_SD_SEND_OP_COND, cmd_arg); |
| 710 | if (rv < 0) { |
| 711 | /* |
| 712 | * This *will* fail for MMC. If fails, bad/no |
| 713 | * card or card is MMC, do CMD58 then CMD1. |
| 714 | */ |
| 715 | RTEMS_SYSLOG( "ACMD41 failed. Assume MMC and do CMD58 (once) then CMD1\n"); |
| 716 | assume_sd = false; |
| 717 | cmd_arg = SD_CARD_FLAG_HCS; |
| 718 | do_cmd58 = true; |
| 719 | continue; |
| 720 | } else { |
| 721 | /* |
| 722 | * Passed ACMD41 so SD. It is now save to |
| 723 | * check if_cond_reg from CMD8. Reject the |
| 724 | * card in case of a indicated bad voltage. |
| 725 | */ |
| 726 | if (if_cond_reg != if_cond_test) { |
| 727 | RTEMS_CLEANUP_RV_SC( -1, sc, sd_card_driver_init_cleanup, "Bad voltage for SD"); |
| 728 | } |
| 729 | } |
| 730 | } else { |
| 731 | /* |
| 732 | * Does not seem to be SD card. Do init for MMC. |
| 733 | * First send CMD58 once to enable check for HCS |
| 734 | * (similar to CMD8 of SD) with bits 30:29 set to 10b. |
| 735 | * This will work for MMC >= 4.2. Older cards (<= 4.1) |
| 736 | * may may not respond to CMD1 unless CMD58 is sent |
| 737 | * again with zero argument. |
| 738 | */ |
| 739 | if (do_cmd58) { |
| 740 | rv = sd_card_send_command( e, SD_CARD_CMD_READ_OCR, cmd_arg); |
| 741 | RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Failed CMD58 for MMC"); |
| 742 | |
| 743 | /* A one-shot call */ |
| 744 | do_cmd58 = false; |
| 745 | } |
| 746 | |
| 747 | /* Do CMD1 */ |
| 748 | rv = sd_card_send_command( e, SD_CARD_CMD_SEND_OP_COND, 0); |
| 749 | if (rv < 0) { |
| 750 | if (cmd_arg != 0) { |
| 751 | /* |
| 752 | * Send CMD58 again with zero argument |
| 753 | * value. Proves card is not |
| 754 | * high_capacity. |
| 755 | */ |
| 756 | cmd_arg = 0; |
| 757 | do_cmd58 = true; |
| 758 | high_capacity = false; |
| 759 | continue; |
| 760 | } |
| 761 | |
| 762 | RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Failed to initialize MMC"); |
| 763 | } |
| 764 | } |
628 | | }; |
| 778 | } |
| 779 | |
| 780 | /* Now we know if we are SD or MMC */ |
| 781 | if (assume_sd) { |
| 782 | if (cmd_arg == 0) { |
| 783 | /* SD is < 2.0 so never high capacity (<= 2G) */ |
| 784 | high_capacity = 0; |
| 785 | } else { |
| 786 | uint32_t reg = 0; |
| 787 | |
| 788 | /* |
| 789 | * SD is definitely 2.x. Now need to send CMD58 to get |
| 790 | * the OCR to see if the HCS bit is set (capacity > 2G) |
| 791 | * or if bit is off (capacity <= 2G, standard |
| 792 | * capacity). |
| 793 | */ |
| 794 | rv = sd_card_send_register_command( e, SD_CARD_CMD_READ_OCR, 0, ®); |
| 795 | RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Failed CMD58 for SD 2.x"); |
| 796 | |
| 797 | /* Check HCS bit of OCR */ |
| 798 | high_capacity = (reg & SD_CARD_FLAG_HCS) != 0; |
| 799 | } |
| 800 | } else { |
| 801 | /* |
| 802 | * Card is MMC. Unless already proven to be not HCS (< 4.2) |
| 803 | * must do CMD58 again to check the OCR bits 30:29. |
| 804 | */ |
| 805 | if (high_capacity) { |
| 806 | uint32_t reg = 0; |
| 807 | |
| 808 | /* |
| 809 | * The argument should still be correct since was never |
| 810 | * set to 0 |
| 811 | */ |
| 812 | rv = sd_card_send_register_command( e, SD_CARD_CMD_READ_OCR, cmd_arg, ®); |
| 813 | RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Failed CMD58 for MMC 4.2"); |
| 814 | |
| 815 | /* Check HCS bit of the OCR */ |
| 816 | high_capacity = (reg & 0x600000) == SD_CARD_FLAG_HCS; |
| 817 | } |
| 818 | } |
655 | 847 | rv = sd_card_send_command( e, SD_CARD_CMD_SEND_CSD, 0); |
656 | 848 | RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Send: SD_CARD_CMD_SEND_CSD"); |
657 | 849 | rv = sd_card_read( e, SD_CARD_START_BLOCK_SINGLE_BLOCK_READ, block, SD_CARD_CSD_SIZE); |
658 | 850 | RTEMS_CLEANUP_RV_SC( rv, sc, sd_card_driver_init_cleanup, "Read: SD_CARD_CMD_SEND_CSD"); |
662 | | read_block_size = 1U << SD_CARD_CSD_GET_READ_BLK_LEN( block); |
663 | | e->block_size_shift = SD_CARD_CSD_GET_READ_BLK_LEN( block); |
664 | | write_block_size = 1U << e->block_size_shift; |
665 | | if (read_block_size < write_block_size) { |
666 | | RTEMS_SYSLOG_ERROR( "Read block size smaller than write block size\n"); |
667 | | return -RTEMS_IO_ERROR; |
| 859 | |
| 860 | /* Block sizes and capacity */ |
| 861 | if (csd_structure == 0 || !assume_sd) { |
| 862 | /* Treat MMC same as CSD Version 1.0 */ |
| 863 | |
| 864 | read_block_size = 1U << SD_CARD_CSD_GET_READ_BLK_LEN( block); |
| 865 | e->block_size_shift = SD_CARD_CSD_GET_WRITE_BLK_LEN( block); |
| 866 | write_block_size = 1U << e->block_size_shift; |
| 867 | if (read_block_size < write_block_size) { |
| 868 | RTEMS_SYSLOG_ERROR( "Read block size smaller than write block size\n"); |
| 869 | return -RTEMS_IO_ERROR; |
| 870 | } |
| 871 | e->block_size = write_block_size; |
| 872 | e->block_number = sd_card_block_number( block); |
| 873 | capacity = sd_card_capacity( block); |
| 874 | } else if (csd_structure == 1) { |
| 875 | uint32_t c_size = SD_CARD_CSD_1_GET_C_SIZE( block); |
| 876 | |
| 877 | /* Block size is fixed in CSD Version 2.0 */ |
| 878 | e->block_size_shift = 9; |
| 879 | e->block_size = 512; |
| 880 | |
| 881 | e->block_number = (c_size + 1) * 1024; |
| 882 | capacity = (c_size + 1) * 512 * 1024; |
| 883 | read_block_size = 512; |
| 884 | write_block_size = 512; |
| 885 | } else { |
| 886 | RTEMS_DO_CLEANUP_SC( RTEMS_IO_ERROR, sc, sd_card_driver_init_cleanup, "Unexpected CSD Structure number"); |