diff --git a/external/asf4-drivers/Config/conf_sd_mmc.h b/external/asf4-drivers/Config/conf_sd_mmc.h new file mode 100644 index 0000000000..3b8f7ca29b --- /dev/null +++ b/external/asf4-drivers/Config/conf_sd_mmc.h @@ -0,0 +1,79 @@ +/* Auto-generated config file conf_sd_mmc.h */ +#ifndef CONF_SD_MMC_H +#define CONF_SD_MMC_H + +// <<< Use Configuration Wizard in Context Menu >>> + +// Enable the SDIO support +// conf_sdio_support +#ifndef CONF_SDIO_SUPPORT +#define CONF_SDIO_SUPPORT 1 +#endif + +// Enable the MMC card support +// conf_mmc_support +#ifndef CONF_MMC_SUPPORT +#define CONF_MMC_SUPPORT 0 +#endif + +// Enable the OS support +// conf_sd_mmc_os_support +#ifndef CONF_OS_SUPPORT +#define CONF_OS_SUPPORT 0 +#endif + +// Detection (card/write protect) timeout (ms/ticks) +// conf_sd_mmc_debounce +#ifndef CONF_SD_MMC_DEBOUNCE +#define CONF_SD_MMC_DEBOUNCE 1000 +#endif + +#ifndef CONF_SD_MMC_MEM_CNT +#define CONF_SD_MMC_MEM_CNT 1 +#endif + +// SD/MMC Slot 0 +// conf_sd_mmc_0_enable +#ifndef CONF_SD_MMC_0_ENABLE +#define CONF_SD_MMC_0_ENABLE 1 +#endif + +// Card Detect (CD) 0 Enable +// conf_sd_mmc_0_cd_detect_en +#ifndef CONF_SD_MMC_0_CD_DETECT_EN +#define CONF_SD_MMC_0_CD_DETECT_EN 1 +#endif + +// Card Detect (CD) detection level +// <1=> High +// <0=> Low +// conf_sd_mmc_0_cd_detect_value +#ifndef CONF_SD_MMC_0_CD_DETECT_VALUE +#define CONF_SD_MMC_0_CD_DETECT_VALUE 0 +#endif +// + +// Write Protect (WP) 0 Enable +// conf_sd_mmc_0_wp_detect_en +#ifndef CONF_SD_MMC_0_WP_DETECT_EN +#define CONF_SD_MMC_0_WP_DETECT_EN 0 +#endif + +// Write Protect (WP) detection level +// <1=> High +// <0=> Low +// conf_sd_mmc_0_wp_detect_value +#ifndef CONF_SD_MMC_0_WP_DETECT_VALUE +#define CONF_SD_MMC_0_WP_DETECT_VALUE 1 +#endif +// + +// + +#ifndef CONF_MCI_OS_SUPPORT +#define CONF_MCI_OS_SUPPORT 0 +#endif + +// <<< end of configuration section >>> + +#endif // CONF_SD_MMC_H diff --git a/external/asf4-drivers/Config/hpl_gclk_config.h b/external/asf4-drivers/Config/hpl_gclk_config.h index e62eab55bc..331ec261e2 100644 --- a/external/asf4-drivers/Config/hpl_gclk_config.h +++ b/external/asf4-drivers/Config/hpl_gclk_config.h @@ -387,7 +387,7 @@ // Indicates whether generic clock 5 configuration is enabled or not // enable_gclk_gen_5 #ifndef CONF_GCLK_GENERATOR_5_CONFIG -#define CONF_GCLK_GENERATOR_5_CONFIG 0 +#define CONF_GCLK_GENERATOR_5_CONFIG 1 #endif // Generic Clock Generator Control @@ -404,7 +404,7 @@ // This defines the clock source for generic clock generator 5 // gclk_gen_5_oscillator #ifndef CONF_GCLK_GEN_5_SOURCE -#define CONF_GCLK_GEN_5_SOURCE GCLK_GENCTRL_SRC_GCLKGEN1 +#define CONF_GCLK_GEN_5_SOURCE GCLK_GENCTRL_SRC_DFLL #endif // Run in Standby @@ -446,7 +446,7 @@ // Indicates whether Generic Clock Generator Enable is enabled or not // gclk_arch_gen_5_enable #ifndef CONF_GCLK_GEN_5_GENEN -#define CONF_GCLK_GEN_5_GENEN 0 +#define CONF_GCLK_GEN_5_GENEN 1 #endif // @@ -454,7 +454,7 @@ // Generic clock generator 5 division <0x0000-0xFFFF> // gclk_gen_5_div #ifndef CONF_GCLK_GEN_5_DIV -#define CONF_GCLK_GEN_5_DIV 62 +#define CONF_GCLK_GEN_5_DIV 6 #endif // // diff --git a/external/asf4-drivers/Config/peripheral_clk_config.h b/external/asf4-drivers/Config/peripheral_clk_config.h index d557fe9e81..4dadfdff7f 100644 --- a/external/asf4-drivers/Config/peripheral_clk_config.h +++ b/external/asf4-drivers/Config/peripheral_clk_config.h @@ -340,7 +340,7 @@ // Select the slow clock source. #ifndef CONF_GCLK_SERCOM5_SLOW_SRC -#define CONF_GCLK_SERCOM5_SLOW_SRC GCLK_PCHCTRL_GEN_GCLK2_Val +#define CONF_GCLK_SERCOM5_SLOW_SRC GCLK_PCHCTRL_GEN_GCLK4_Val #endif /** @@ -356,7 +356,7 @@ * \brief SERCOM5's Slow Clock frequency */ #ifndef CONF_GCLK_SERCOM5_SLOW_FREQUENCY -#define CONF_GCLK_SERCOM5_SLOW_FREQUENCY 12000000 +#define CONF_GCLK_SERCOM5_SLOW_FREQUENCY 32768 #endif // SDHC Clock Settings @@ -389,7 +389,7 @@ // Select the clock source for SDHC. // sdhc_gclk_selection #ifndef CONF_GCLK_SDHC0_SRC -#define CONF_GCLK_SDHC0_SRC GCLK_PCHCTRL_GEN_GCLK3_Val +#define CONF_GCLK_SDHC0_SRC GCLK_PCHCTRL_GEN_GCLK5_Val #endif // SDHC clock slow source @@ -430,7 +430,7 @@ * \brief SDHC's Clock frequency */ #ifndef CONF_SDHC0_FREQUENCY -#define CONF_SDHC0_FREQUENCY 48000000 +#define CONF_SDHC0_FREQUENCY 8000000 #endif /** diff --git a/external/asf4-drivers/sd_mmc/sd_mmc.c b/external/asf4-drivers/sd_mmc/sd_mmc.c index c5b8572a2b..2a4b5931da 100644 --- a/external/asf4-drivers/sd_mmc/sd_mmc.c +++ b/external/asf4-drivers/sd_mmc/sd_mmc.c @@ -3,52 +3,47 @@ * * \brief Common SD/MMC stack * - * Copyright (c) 2016 - 2017 Atmel Corporation. All rights reserved. + * Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries. * * \asf_license_start * * \page License * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. The name of Atmel may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * 4. This software may only be redistributed and used in connection with an - * Atmel microcontroller product. - * - * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE - * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. * * \asf_license_stop * */ /* - * Support and FAQ: visit Atmel Support + * Support and FAQ: visit Microchip Support */ #include +#include "conf_sd_mmc.h" + #include "sd_mmc_protocol.h" #include "sd_mmc.h" +#if CONF_OS_SUPPORT +#include +#endif #include #include #include @@ -70,14 +65,37 @@ /* Macros to switch SD MMC stack to the correct driver (MCI or SPI) */ #if (CONF_SD_MMC_MEM_CNT != 0) +#if CONF_MCI_OS_SUPPORT +#include "hal_mci_os.h" +#else #include "hal_mci_sync.h" +#endif #define driver mci #else #error No MCI or HSMCI interfaces are defined for SD MMC stack. \ CONF_SD_MMC_MEM_CNT must be added in board.h file. #endif +#if CONF_MCI_OS_SUPPORT +#define driver_select_device ATPASTE2(driver, _os_select_device) +#define driver_deselect_device ATPASTE2(driver, _os_deselect_device) +#define driver_get_bus_width ATPASTE2(driver, _os_get_bus_width) +#define driver_is_high_speed_capable ATPASTE2(driver, _os_is_high_speed_capable) +#define driver_send_clock ATPASTE2(driver, _os_send_init_sequence) +#define driver_send_cmd ATPASTE2(driver, _os_send_cmd) +#define driver_get_response ATPASTE2(driver, _os_get_response) +#define driver_get_response_128 ATPASTE2(driver, _os_get_response_128) +#define driver_adtc_start ATPASTE2(driver, _os_adtc_start) +#define driver_adtc_stop ATPASTE2(driver, _os_send_cmd) +#define driver_read_word ATPASTE2(driver, _os_read_bytes) +#define driver_write_word ATPASTE2(driver, _os_write_bytes) +#define driver_start_read_blocks ATPASTE2(driver, _os_start_read_blocks) +#define driver_wait_end_of_read_blocks ATPASTE2(driver, _os_wait_end_of_read_blocks) +#define driver_start_write_blocks ATPASTE2(driver, _os_start_write_blocks) +#define driver_wait_end_of_write_blocks ATPASTE2(driver, _os_wait_end_of_write_blocks) +#else #define driver_select_device ATPASTE2(driver, _sync_select_device) +#define driver_deselect_device ATPASTE2(driver, _sync_deselect_device) #define driver_get_bus_width ATPASTE2(driver, _sync_get_bus_width) #define driver_is_high_speed_capable ATPASTE2(driver, _sync_is_high_speed_capable) #define driver_send_clock ATPASTE2(driver, _sync_send_clock) @@ -92,33 +110,38 @@ #define driver_wait_end_of_read_blocks ATPASTE2(driver, _sync_wait_end_of_read_blocks) #define driver_start_write_blocks ATPASTE2(driver, _sync_start_write_blocks) #define driver_wait_end_of_write_blocks ATPASTE2(driver, _sync_wait_end_of_write_blocks) +#endif +#if (CONF_SDIO_SUPPORT == 1) #define IS_SDIO() (sd_mmc_card->type & CARD_TYPE_SDIO) +#else +#define IS_SDIO() false +#endif /** This SD MMC stack supports only the high voltage */ #define SD_MMC_VOLTAGE_SUPPORT \ - (OCR_VDD_27_28 | OCR_VDD_28_29 | OCR_VDD_29_30 | OCR_VDD_30_31 | OCR_VDD_31_32 | OCR_VDD_32_33) + (OCR_VDD_27_28 | OCR_VDD_28_29 | OCR_VDD_29_30 | OCR_VDD_30_31 | OCR_VDD_31_32 | OCR_VDD_32_33) /** SD/MMC card states */ enum card_state { - SD_MMC_CARD_STATE_READY = 0, /**< Ready to use */ - SD_MMC_CARD_STATE_DEBOUNCE = 1, /**< Debounce on going */ - SD_MMC_CARD_STATE_INIT = 2, /**< Initialization on going */ - SD_MMC_CARD_STATE_UNUSABLE = 3, /**< Unusable card */ - SD_MMC_CARD_STATE_NO_CARD = 4 /**< No SD/MMC card inserted */ + SD_MMC_CARD_STATE_READY = 0, /**< Ready to use */ + SD_MMC_CARD_STATE_DEBOUNCE = 1, /**< Debounce on going */ + SD_MMC_CARD_STATE_INIT = 2, /**< Initialization on going */ + SD_MMC_CARD_STATE_UNUSABLE = 3, /**< Unusable card */ + SD_MMC_CARD_STATE_NO_CARD = 4 /**< No SD/MMC card inserted */ }; /** SD/MMC card information structure */ struct sd_mmc_card { - uint32_t clock; /**< Card access clock */ - uint32_t capacity; /**< Card capacity in KBytes */ - uint16_t rca; /**< Relative card address */ - enum card_state state; /**< Card state */ - card_type_t type; /**< Card type */ - card_version_t version; /**< Card version */ - uint8_t bus_width; /**< Number of DATA lin on bus (MCI only) */ - uint8_t csd[CSD_REG_BSIZE]; /**< CSD register */ - uint8_t high_speed; /**< High speed card (1) */ + uint32_t clock; /**< Card access clock */ + uint32_t capacity; /**< Card capacity in KBytes */ + uint16_t rca; /**< Relative card address */ + enum card_state state; /**< Card state */ + card_type_t type; /**< Card type */ + card_version_t version; /**< Card version */ + uint8_t bus_width; /**< Number of DATA lin on bus (MCI only) */ + uint8_t csd[CSD_REG_BSIZE]; /**< CSD register */ + uint8_t high_speed; /**< High speed card (1) */ }; /** Card detect pin */ @@ -150,6 +173,13 @@ const uint32_t mmc_trans_multipliers[16] = {0, 10, 12, 13, 15, 20, 26, 30, 35, 4 /** \name MMC, SD and SDIO commands process */ /** @{ */ +#if CONF_MMC_SUPPORT +static bool mmc_mci_op_cond(void); +static bool mmc_cmd6_set_bus_width(uint8_t bus_width); +static bool mmc_cmd6_set_high_speed(void); +static bool mmc_cmd8(uint8_t *b_authorize_high_speed); +static void mmc_decode_csd(void); +#endif static bool sd_mci_op_cond(uint8_t v2); static bool sdio_op_cond(void); static bool sdio_get_max_speed(void); @@ -160,9 +190,11 @@ static bool sd_cmd8(uint8_t *v2); static bool sd_mmc_cmd9_mci(void); static void sd_decode_csd(void); static bool sd_mmc_cmd13(void); +#if (CONF_SDIO_SUPPORT == 1) static bool sdio_cmd52(uint8_t rw_flag, uint8_t func_nb, uint32_t reg_addr, uint8_t rd_after_wr, uint8_t *io_data); static bool sdio_cmd53(uint8_t rw_flag, uint8_t func_nb, uint32_t reg_addr, uint8_t inc_addr, uint32_t size, bool access_block); +#endif static bool sd_acmd6(void); static bool sd_acmd51(void); /** @} */ @@ -170,10 +202,64 @@ static bool sd_acmd51(void); /** \name Internal function to process the initialization and install */ /** @{ */ static sd_mmc_err_t sd_mmc_select_slot(uint8_t slot); -static void sd_mmc_configure_slot(void); -static bool sd_mmc_mci_card_init(void); +static void sd_mmc_configure_slot(void); +static void sd_mmc_deselect_slot(void); +static bool sd_mmc_mci_card_init(void); +#if CONF_MMC_SUPPORT +static bool sd_mmc_mci_install_mmc(void); +#endif /** @} */ +/** \name Internal functions to manage a large timeout after a card insertion */ +/** @{ */ +#if CONF_OS_SUPPORT +#define SD_MMC_START_TIMEOUT() os_sleep(CONF_SD_MMC_DEBOUNCE) +#else +#define SD_MMC_START_TIMEOUT() +#endif +#define SD_MMC_IS_TIMEOUT() true +#define SD_MMC_STOP_TIMEOUT() +/** @} */ + +#if CONF_MMC_SUPPORT +/** + * \brief Sends operation condition command and read OCR (MCI only) + * - CMD1 sends operation condition command + * - CMD1 reads OCR + * + * \return true if success, otherwise false + */ +static bool mmc_mci_op_cond(void) +{ + uint32_t retry, resp; + + /* + * Timeout 1s = 400KHz / ((6+6)*8) cylces = 4200 retry + * 6 = cmd byte size + * 6 = response byte size + */ + retry = 4200; + do { + if (!driver_send_cmd(sd_mmc_hal, MMC_MCI_CMD1_SEND_OP_COND, SD_MMC_VOLTAGE_SUPPORT | OCR_ACCESS_MODE_SECTOR)) { + return false; + } + /* Check busy flag */ + resp = driver_get_response(sd_mmc_hal); + if (resp & OCR_POWER_UP_BUSY) { + /* Check OCR value */ + if ((resp & OCR_ACCESS_MODE_MASK) == OCR_ACCESS_MODE_SECTOR) { + sd_mmc_card->type |= CARD_TYPE_HC; + } + break; + } + if (retry-- == 0) { + return false; + } + } while (1); + return true; +} +#endif + /** * \brief Ask to all cards to send their operations conditions (MCI only). * - ACMD41 sends operation condition command. @@ -185,47 +271,48 @@ static bool sd_mmc_mci_card_init(void); */ static bool sd_mci_op_cond(uint8_t v2) { - uint32_t arg, retry, resp; - - /* - * Timeout 1s = 400KHz / ((6+6+6+6)*8) cylces = 2100 retry - * 6 = cmd byte size - * 6 = response byte size - * 6 = cmd byte size - * 6 = response byte size - */ - retry = 2100; - do { - /* CMD55 - Indicate to the card that the next command is an - * application specific command rather than a standard command.*/ - if (!driver_send_cmd(sd_mmc_hal, SDMMC_CMD55_APP_CMD, 0)) { - return false; - } - - /* (ACMD41) Sends host OCR register */ - arg = SD_MMC_VOLTAGE_SUPPORT; - if (v2) { - arg |= SD_ACMD41_HCS; - } - /* Check response */ - if (!driver_send_cmd(sd_mmc_hal, SD_MCI_ACMD41_SD_SEND_OP_COND, arg)) { - return false; - } - resp = driver_get_response(sd_mmc_hal); - if (resp & OCR_POWER_UP_BUSY) { - /* Card is ready */ - if ((resp & OCR_CCS) != 0) { - sd_mmc_card->type |= CARD_TYPE_HC; - } - break; - } - if (retry-- == 0) { - return false; - } - } while (1); - return true; + uint32_t arg, retry, resp; + + /* + * Timeout 1s = 400KHz / ((6+6+6+6)*8) cylces = 2100 retry + * 6 = cmd byte size + * 6 = response byte size + * 6 = cmd byte size + * 6 = response byte size + */ + retry = 2100; + do { + /* CMD55 - Indicate to the card that the next command is an + * application specific command rather than a standard command.*/ + if (!driver_send_cmd(sd_mmc_hal, SDMMC_CMD55_APP_CMD, 0)) { + return false; + } + + /* (ACMD41) Sends host OCR register */ + arg = SD_MMC_VOLTAGE_SUPPORT; + if (v2) { + arg |= SD_ACMD41_HCS; + } + /* Check response */ + if (!driver_send_cmd(sd_mmc_hal, SD_MCI_ACMD41_SD_SEND_OP_COND, arg)) { + return false; + } + resp = driver_get_response(sd_mmc_hal); + if (resp & OCR_POWER_UP_BUSY) { + /* Card is ready */ + if ((resp & OCR_CCS) != 0) { + sd_mmc_card->type |= CARD_TYPE_HC; + } + break; + } + if (retry-- == 0) { + return false; + } + } while (1); + return true; } +#if (CONF_SDIO_SUPPORT == 1) /** * \brief Try to get the SDIO card's operating condition * - CMD5 to read OCR NF field @@ -237,44 +324,44 @@ static bool sd_mci_op_cond(uint8_t v2) */ static bool sdio_op_cond(void) { - uint32_t resp; - - /* CMD5 - SDIO send operation condition (OCR) command. */ - if (!driver_send_cmd(sd_mmc_hal, SDIO_CMD5_SEND_OP_COND, 0)) { - return true; /* No error but card type not updated */ - } - resp = driver_get_response(sd_mmc_hal); - if ((resp & OCR_SDIO_NF) == 0) { - return true; /* No error but card type not updated */ - } - - /* - * Wait card ready - * Timeout 1s = 400KHz / ((6+4)*8) cylces = 5000 retry - * 6 = cmd byte size - * 4(SPI) 6(MCI) = response byte size - */ - uint32_t cmd5_retry = 5000; - while (1) { - /* CMD5 - SDIO send operation condition (OCR) command.*/ - if (!driver_send_cmd(sd_mmc_hal, SDIO_CMD5_SEND_OP_COND, resp & SD_MMC_VOLTAGE_SUPPORT)) { - return false; - } - resp = driver_get_response(sd_mmc_hal); - if ((resp & OCR_POWER_UP_BUSY) == OCR_POWER_UP_BUSY) { - break; - } - if (cmd5_retry-- == 0) { - return false; - } - } - /* Update card type at the end of busy */ - if ((resp & OCR_SDIO_MP) > 0) { - sd_mmc_card->type = CARD_TYPE_SD_COMBO; - } else { - sd_mmc_card->type = CARD_TYPE_SDIO; - } - return true; /* No error and card type updated with SDIO type */ + uint32_t resp; + + /* CMD5 - SDIO send operation condition (OCR) command. */ + if (!driver_send_cmd(sd_mmc_hal, SDIO_CMD5_SEND_OP_COND, 0)) { + return true; /* No error but card type not updated */ + } + resp = driver_get_response(sd_mmc_hal); + if ((resp & OCR_SDIO_NF) == 0) { + return true; /* No error but card type not updated */ + } + + /* + * Wait card ready + * Timeout 1s = 400KHz / ((6+4)*8) cylces = 5000 retry + * 6 = cmd byte size + * 4(SPI) 6(MCI) = response byte size + */ + uint32_t cmd5_retry = 5000; + while (1) { + /* CMD5 - SDIO send operation condition (OCR) command.*/ + if (!driver_send_cmd(sd_mmc_hal, SDIO_CMD5_SEND_OP_COND, resp & SD_MMC_VOLTAGE_SUPPORT)) { + return false; + } + resp = driver_get_response(sd_mmc_hal); + if ((resp & OCR_POWER_UP_BUSY) == OCR_POWER_UP_BUSY) { + break; + } + if (cmd5_retry-- == 0) { + return false; + } + } + /* Update card type at the end of busy */ + if ((resp & OCR_SDIO_MP) > 0) { + sd_mmc_card->type = CARD_TYPE_SD_COMBO; + } else { + sd_mmc_card->type = CARD_TYPE_SDIO; + } + return true; /* No error and card type updated with SDIO type */ } /** @@ -289,73 +376,73 @@ static bool sdio_op_cond(void) */ static bool sdio_get_max_speed(void) { - uint32_t addr_new, addr_old; - uint8_t buf[6]; - uint32_t unit; - uint32_t mul; - uint8_t tplfe_max_tran_speed, i; - uint8_t addr_cis[4]; - - /* Read CIS area address in CCCR area */ - addr_old = SDIO_CCCR_CIS_PTR; - for (i = 0; i < 4; i++) { - sdio_cmd52(SDIO_CMD52_READ_FLAG, SDIO_CIA, addr_old, 0, &addr_cis[i]); - addr_old++; - } - addr_old = addr_cis[0] + (addr_cis[1] << 8) + (addr_cis[2] << 16) + (addr_cis[3] << 24); - addr_new = addr_old; - - while (1) { - /* Read a sample of CIA area */ - for (i = 0; i < 3; i++) { - sdio_cmd52(SDIO_CMD52_READ_FLAG, SDIO_CIA, addr_new, 0, &buf[i]); - addr_new++; - } - if (buf[0] == SDIO_CISTPL_END) { - return false; /* Tuple error */ - } - if (buf[0] == SDIO_CISTPL_FUNCE && buf[2] == 0x00) { - break; /* Fun0 tuple found */ - } - if (buf[1] == 0) { - return false; /* Tuple error */ - } - /* Next address */ - addr_new += buf[1] - 1; - if (addr_new > (addr_old + 256)) { - return false; /* Outoff CIS area */ - } - } - - /* Read all Fun0 tuple fields: fn0_blk_siz & max_tran_speed */ - addr_new -= 3; - for (i = 0; i < 6; i++) { - sdio_cmd52(SDIO_CMD52_READ_FLAG, SDIO_CIA, addr_new, 0, &buf[i]); - addr_new++; - } - - tplfe_max_tran_speed = buf[5]; - if (tplfe_max_tran_speed > 0x32) { - /* Error on SDIO register, the high speed is not activated - * and the clock can not be more than 25MHz. - * This error is present on specific SDIO card - * (H&D wireless card - HDG104 WiFi SIP). - */ - tplfe_max_tran_speed = 0x32; /* 25Mhz */ - } - - /* Decode transfer speed in Hz.*/ - unit = sd_mmc_trans_units[tplfe_max_tran_speed & 0x7]; - mul = sd_trans_multipliers[(tplfe_max_tran_speed >> 3) & 0xF]; - sd_mmc_card->clock = unit * mul * 1000; - /** - * Note: A combo card shall be a Full-Speed SDIO card - * which supports upto 25MHz. - * A SDIO card alone can be: - * - a Low-Speed SDIO card which supports 400Khz minimum - * - a Full-Speed SDIO card which supports upto 25MHz - */ - return true; + uint32_t addr_new, addr_old; + uint8_t buf[6]; + uint32_t unit; + uint32_t mul; + uint8_t tplfe_max_tran_speed, i; + uint8_t addr_cis[4]; + + /* Read CIS area address in CCCR area */ + addr_old = SDIO_CCCR_CIS_PTR; + for (i = 0; i < 4; i++) { + sdio_cmd52(SDIO_CMD52_READ_FLAG, SDIO_CIA, addr_old, 0, &addr_cis[i]); + addr_old++; + } + addr_old = addr_cis[0] + (addr_cis[1] << 8) + (addr_cis[2] << 16) + (addr_cis[3] << 24); + addr_new = addr_old; + + while (1) { + /* Read a sample of CIA area */ + for (i = 0; i < 3; i++) { + sdio_cmd52(SDIO_CMD52_READ_FLAG, SDIO_CIA, addr_new, 0, &buf[i]); + addr_new++; + } + if (buf[0] == SDIO_CISTPL_END) { + return false; /* Tuple error */ + } + if (buf[0] == SDIO_CISTPL_FUNCE && buf[2] == 0x00) { + break; /* Fun0 tuple found */ + } + if (buf[1] == 0) { + return false; /* Tuple error */ + } + /* Next address */ + addr_new += buf[1] - 1; + if (addr_new > (addr_old + 256)) { + return false; /* Outoff CIS area */ + } + } + + /* Read all Fun0 tuple fields: fn0_blk_siz & max_tran_speed */ + addr_new -= 3; + for (i = 0; i < 6; i++) { + sdio_cmd52(SDIO_CMD52_READ_FLAG, SDIO_CIA, addr_new, 0, &buf[i]); + addr_new++; + } + + tplfe_max_tran_speed = buf[5]; + if (tplfe_max_tran_speed > 0x32) { + /* Error on SDIO register, the high speed is not activated + * and the clock can not be more than 25MHz. + * This error is present on specific SDIO card + * (H&D wireless card - HDG104 WiFi SIP). + */ + tplfe_max_tran_speed = 0x32; /* 25Mhz */ + } + + /* Decode transfer speed in Hz.*/ + unit = sd_mmc_trans_units[tplfe_max_tran_speed & 0x7]; + mul = sd_trans_multipliers[(tplfe_max_tran_speed >> 3) & 0xF]; + sd_mmc_card->clock = unit * mul * 1000; + /** + * Note: A combo card shall be a Full-Speed SDIO card + * which supports upto 25MHz. + * A SDIO card alone can be: + * - a Low-Speed SDIO card which supports 400Khz minimum + * - a Full-Speed SDIO card which supports upto 25MHz + */ + return true; } /** @@ -367,29 +454,29 @@ static bool sdio_get_max_speed(void) */ static bool sdio_cmd52_set_bus_width(void) { - /** - * A SD memory card always supports bus 4bit - * A SD COMBO card always supports bus 4bit - * A SDIO Full-Speed alone always supports 4bit - * A SDIO Low-Speed alone can supports 4bit (Optional) - */ - uint8_t u8_value; - - /* Check 4bit support in 4BLS of "Card Capability" register */ - if (!sdio_cmd52(SDIO_CMD52_READ_FLAG, SDIO_CIA, SDIO_CCCR_CAP, 0, &u8_value)) { - return false; - } - if ((u8_value & SDIO_CAP_4BLS) != SDIO_CAP_4BLS) { - /* No supported, it is not a protocol error */ - return true; - } - /* HS mode possible, then enable */ - u8_value = SDIO_BUSWIDTH_4B; - if (!sdio_cmd52(SDIO_CMD52_WRITE_FLAG, SDIO_CIA, SDIO_CCCR_BUS_CTRL, 1, &u8_value)) { - return false; - } - sd_mmc_card->bus_width = 4; - return true; + /** + * A SD memory card always supports bus 4bit + * A SD COMBO card always supports bus 4bit + * A SDIO Full-Speed alone always supports 4bit + * A SDIO Low-Speed alone can supports 4bit (Optional) + */ + uint8_t u8_value; + + /* Check 4bit support in 4BLS of "Card Capability" register */ + if (!sdio_cmd52(SDIO_CMD52_READ_FLAG, SDIO_CIA, SDIO_CCCR_CAP, 0, &u8_value)) { + return false; + } + if ((u8_value & SDIO_CAP_4BLS) != SDIO_CAP_4BLS) { + /* No supported, it is not a protocol error */ + return true; + } + /* HS mode possible, then enable */ + u8_value = SDIO_BUSWIDTH_4B; + if (!sdio_cmd52(SDIO_CMD52_WRITE_FLAG, SDIO_CIA, SDIO_CCCR_BUS_CTRL, 1, &u8_value)) { + return false; + } + sd_mmc_card->bus_width = 4; + return true; } /** @@ -402,25 +489,44 @@ static bool sdio_cmd52_set_bus_width(void) */ static bool sdio_cmd52_set_high_speed(void) { - uint8_t u8_value; - - /* Check CIA.HS */ - if (!sdio_cmd52(SDIO_CMD52_READ_FLAG, SDIO_CIA, SDIO_CCCR_HS, 0, &u8_value)) { - return false; - } - if ((u8_value & SDIO_SHS) != SDIO_SHS) { - /* No supported, it is not a protocol error */ - return true; - } - /* HS mode possible, then enable */ - u8_value = SDIO_EHS; - if (!sdio_cmd52(SDIO_CMD52_WRITE_FLAG, SDIO_CIA, SDIO_CCCR_HS, 1, &u8_value)) { - return false; - } - sd_mmc_card->high_speed = 1; - sd_mmc_card->clock *= 2; - return true; + uint8_t u8_value; + + /* Check CIA.HS */ + if (!sdio_cmd52(SDIO_CMD52_READ_FLAG, SDIO_CIA, SDIO_CCCR_HS, 0, &u8_value)) { + return false; + } + if ((u8_value & SDIO_SHS) != SDIO_SHS) { + /* No supported, it is not a protocol error */ + return true; + } + /* HS mode possible, then enable */ + u8_value = SDIO_EHS; + if (!sdio_cmd52(SDIO_CMD52_WRITE_FLAG, SDIO_CIA, SDIO_CCCR_HS, 1, &u8_value)) { + return false; + } + sd_mmc_card->high_speed = 1; + sd_mmc_card->clock *= 2; + return true; +} + +#else +static bool sdio_op_cond(void) +{ + return true; /* No error but card type not updated */ +} +static bool sdio_get_max_speed(void) +{ + return false; +} +static bool sdio_cmd52_set_bus_width(void) +{ + return false; +} +static bool sdio_cmd52_set_high_speed(void) +{ + return false; } +#endif /** * \brief CMD6 for SD - Switch card in high speed mode @@ -433,44 +539,106 @@ static bool sdio_cmd52_set_high_speed(void) */ static bool sd_cm6_set_high_speed(void) { - uint8_t switch_status[SD_SW_STATUS_BSIZE] = {0}; - - if (!driver_adtc_start(sd_mmc_hal, - SD_CMD6_SWITCH_FUNC, - SD_CMD6_MODE_SWITCH | SD_CMD6_GRP6_NO_INFLUENCE | SD_CMD6_GRP5_NO_INFLUENCE - | SD_CMD6_GRP4_NO_INFLUENCE - | SD_CMD6_GRP3_NO_INFLUENCE - | SD_CMD6_GRP2_DEFAULT - | SD_CMD6_GRP1_HIGH_SPEED, - SD_SW_STATUS_BSIZE, - 1, - true)) { - return false; - } - if (!driver_start_read_blocks(sd_mmc_hal, switch_status, 1)) { - return false; - } - if (!driver_wait_end_of_read_blocks(sd_mmc_hal)) { - return false; - } - - if (driver_get_response(sd_mmc_hal) & CARD_STATUS_SWITCH_ERROR) { - return false; - } - if (SD_SW_STATUS_FUN_GRP1_RC(switch_status) == SD_SW_STATUS_FUN_GRP_RC_ERROR) { - /* No supported, it is not a protocol error */ - return true; - } - if (SD_SW_STATUS_FUN_GRP1_BUSY(switch_status)) { - return false; - } - /* CMD6 function switching period is within 8 clocks - * after the end bit of status data.*/ - driver_send_clock(sd_mmc_hal); - sd_mmc_card->high_speed = 1; - sd_mmc_card->clock *= 2; - return true; + uint8_t switch_status[SD_SW_STATUS_BSIZE] = {0}; + + if (!driver_adtc_start(sd_mmc_hal, + SD_CMD6_SWITCH_FUNC, + SD_CMD6_MODE_SWITCH | SD_CMD6_GRP6_NO_INFLUENCE | SD_CMD6_GRP5_NO_INFLUENCE + | SD_CMD6_GRP4_NO_INFLUENCE | SD_CMD6_GRP3_NO_INFLUENCE | SD_CMD6_GRP2_DEFAULT + | SD_CMD6_GRP1_HIGH_SPEED, + SD_SW_STATUS_BSIZE, + 1, + true)) { + return false; + } + if (!driver_start_read_blocks(sd_mmc_hal, switch_status, 1)) { + return false; + } + if (!driver_wait_end_of_read_blocks(sd_mmc_hal)) { + return false; + } + + if (driver_get_response(sd_mmc_hal) & CARD_STATUS_SWITCH_ERROR) { + return false; + } + if (SD_SW_STATUS_FUN_GRP1_RC(switch_status) == SD_SW_STATUS_FUN_GRP_RC_ERROR) { + /* No supported, it is not a protocol error */ + return true; + } + if (SD_SW_STATUS_FUN_GRP1_BUSY(switch_status)) { + return false; + } + /* CMD6 function switching period is within 8 clocks + * after the end bit of status data.*/ + driver_send_clock(sd_mmc_hal); + sd_mmc_card->high_speed = 1; + sd_mmc_card->clock *= 2; + return true; +} + +#if CONF_MMC_SUPPORT + +/** + * \brief CMD6 for MMC - Switches the bus width mode + * + * \note CMD6 is valid under the "trans" state. + * \note sd_mmc_card->bus_width is updated. + * + * \param bus_width Bus width to set + * + * \return true if success, otherwise false + */ +static bool mmc_cmd6_set_bus_width(uint8_t bus_width) +{ + uint32_t arg; + + switch (bus_width) { + case 8: + arg = MMC_CMD6_ACCESS_SET_BITS | MMC_CMD6_INDEX_BUS_WIDTH | MMC_CMD6_VALUE_BUS_WIDTH_8BIT; + break; + case 4: + arg = MMC_CMD6_ACCESS_SET_BITS | MMC_CMD6_INDEX_BUS_WIDTH | MMC_CMD6_VALUE_BUS_WIDTH_4BIT; + break; + default: + arg = MMC_CMD6_ACCESS_SET_BITS | MMC_CMD6_INDEX_BUS_WIDTH | MMC_CMD6_VALUE_BUS_WIDTH_1BIT; + break; + } + if (!driver_send_cmd(sd_mmc_hal, MMC_CMD6_SWITCH, arg)) { + return false; + } + if (driver_get_response(sd_mmc_hal) & CARD_STATUS_SWITCH_ERROR) { + /* No supported, it is not a protocol error */ + return false; + } + sd_mmc_card->bus_width = bus_width; + return true; +} + +/** + * \brief CMD6 for MMC - Switches in high speed mode + * + * \note CMD6 is valid under the "trans" state. + * \note sd_mmc_card->high_speed is updated. + * \note sd_mmc_card->clock is updated. + * + * \return true if success, otherwise false + */ +static bool mmc_cmd6_set_high_speed(void) +{ + if (!driver_send_cmd(sd_mmc_hal, + MMC_CMD6_SWITCH, + MMC_CMD6_ACCESS_WRITE_BYTE | MMC_CMD6_INDEX_HS_TIMING | MMC_CMD6_VALUE_HS_TIMING_ENABLE)) { + return false; + } + if (driver_get_response(sd_mmc_hal) & CARD_STATUS_SWITCH_ERROR) { + /* No supported, it is not a protocol error */ + return false; + } + sd_mmc_card->high_speed = 1; + sd_mmc_card->clock = 52000000lu; + return true; } +#endif /** * \brief CMD8 for SD card - Send Interface Condition Command. @@ -487,26 +655,76 @@ static bool sd_cm6_set_high_speed(void) */ static bool sd_cmd8(uint8_t *v2) { - uint32_t resp; - - *v2 = 0; - /* Test for SD version 2 */ - if (!driver_send_cmd(sd_mmc_hal, SD_CMD8_SEND_IF_COND, SD_CMD8_PATTERN | SD_CMD8_HIGH_VOLTAGE)) { - return true; /* It is not a V2 */ - } - /* Check R7 response */ - resp = driver_get_response(sd_mmc_hal); - if (resp == 0xFFFFFFFF) { - /* No compliance R7 value */ - return true; /* It is not a V2 */ - } - if ((resp & (SD_CMD8_MASK_PATTERN | SD_CMD8_MASK_VOLTAGE)) != (SD_CMD8_PATTERN | SD_CMD8_HIGH_VOLTAGE)) { - return false; - } - *v2 = 1; - return true; + uint32_t resp; + + *v2 = 0; + /* Test for SD version 2 */ + if (!driver_send_cmd(sd_mmc_hal, SD_CMD8_SEND_IF_COND, SD_CMD8_PATTERN | SD_CMD8_HIGH_VOLTAGE)) { + return true; /* It is not a V2 */ + } + /* Check R7 response */ + resp = driver_get_response(sd_mmc_hal); + if (resp == 0xFFFFFFFF) { + /* No compliance R7 value */ + return true; /* It is not a V2 */ + } + if ((resp & (SD_CMD8_MASK_PATTERN | SD_CMD8_MASK_VOLTAGE)) != (SD_CMD8_PATTERN | SD_CMD8_HIGH_VOLTAGE)) { + return false; + } + *v2 = 1; + return true; } +#if CONF_MMC_SUPPORT +/** + * \brief CMD8 - The card sends its EXT_CSD register as a block of data. + * + * \param b_authorize_high_speed Pointer to update with the high speed + * support information + * + * \return true if success, otherwise false + */ +static bool mmc_cmd8(uint8_t *b_authorize_high_speed) +{ + uint16_t i; + uint32_t ext_csd; + uint32_t sec_count; + + if (!driver_adtc_start(sd_mmc_hal, MMC_CMD8_SEND_EXT_CSD, 0, EXT_CSD_BSIZE, 1, false)) { + return false; + } + /* Read and decode Extended Extended CSD + * Note: The read access is done in byte to avoid a buffer + * of EXT_CSD_BSIZE Byte in stack.*/ + + /* Read card type */ + for (i = 0; i < (EXT_CSD_CARD_TYPE_INDEX + 4) / 4; i++) { + if (!driver_read_word(sd_mmc_hal, &ext_csd)) { + return false; + } + } + *b_authorize_high_speed = (ext_csd >> ((EXT_CSD_CARD_TYPE_INDEX % 4) * 8)) & MMC_CTYPE_52MHZ; + + if (MMC_CSD_C_SIZE(sd_mmc_card->csd) == 0xFFF) { + /* For high capacity SD/MMC card, + * memory capacity = SEC_COUNT * 512 byte */ + for (; i < (EXT_CSD_SEC_COUNT_INDEX + 4) / 4; i++) { + if (!driver_read_word(sd_mmc_hal, &sec_count)) { + return false; + } + } + sd_mmc_card->capacity = sec_count / 2; + } + for (; i < EXT_CSD_BSIZE / 4; i++) { + if (!driver_read_word(sd_mmc_hal, &sec_count)) { + return false; + } + } + return true; +} + +#endif + /** * \brief CMD9: Addressed card sends its card-specific * data (CSD) on the CMD line mci. @@ -515,48 +733,109 @@ static bool sd_cmd8(uint8_t *v2) */ static bool sd_mmc_cmd9_mci(void) { - if (!driver_send_cmd(sd_mmc_hal, SDMMC_MCI_CMD9_SEND_CSD, (uint32_t)sd_mmc_card->rca << 16)) { - return false; - } - driver_get_response_128(sd_mmc_hal, sd_mmc_card->csd); - return true; + if (!driver_send_cmd(sd_mmc_hal, SDMMC_MCI_CMD9_SEND_CSD, (uint32_t)sd_mmc_card->rca << 16)) { + return false; + } + driver_get_response_128(sd_mmc_hal, sd_mmc_card->csd); + return true; +} + +#if CONF_MMC_SUPPORT +/** + * \brief Decodes MMC CSD register + */ +static void mmc_decode_csd(void) +{ + uint32_t unit; + uint32_t mul; + uint32_t tran_speed; + + /* Get MMC System Specification version supported by the card */ + switch (MMC_CSD_SPEC_VERS(sd_mmc_card->csd)) { + default: + case 0: + sd_mmc_card->version = CARD_VER_MMC_1_2; + break; + + case 1: + sd_mmc_card->version = CARD_VER_MMC_1_4; + break; + + case 2: + sd_mmc_card->version = CARD_VER_MMC_2_2; + break; + + case 3: + sd_mmc_card->version = CARD_VER_MMC_3; + break; + + case 4: + sd_mmc_card->version = CARD_VER_MMC_4; + break; + } + + /* Get MMC memory max transfer speed in Hz.*/ + tran_speed = CSD_TRAN_SPEED(sd_mmc_card->csd); + unit = sd_mmc_trans_units[tran_speed & 0x7]; + mul = mmc_trans_multipliers[(tran_speed >> 3) & 0xF]; + sd_mmc_card->clock = unit * mul * 1000; + + /* + * Get card capacity. + * ---------------------------------------------------- + * For normal SD/MMC card: + * memory capacity = BLOCKNR * BLOCK_LEN + * Where + * BLOCKNR = (C_SIZE+1) * MULT + * MULT = 2 ^ (C_SIZE_MULT+2) (C_SIZE_MULT < 8) + * BLOCK_LEN = 2 ^ READ_BL_LEN (READ_BL_LEN < 12) + * ---------------------------------------------------- + * For high capacity SD/MMC card: + * memory capacity = SEC_COUNT * 512 byte + */ + if (MMC_CSD_C_SIZE(sd_mmc_card->csd) != 0xFFF) { + uint32_t blocknr + = ((MMC_CSD_C_SIZE(sd_mmc_card->csd) + 1) * (1 << (MMC_CSD_C_SIZE_MULT(sd_mmc_card->csd) + 2))); + sd_mmc_card->capacity = blocknr * (1 << MMC_CSD_READ_BL_LEN(sd_mmc_card->csd)) / 1024; + } } +#endif /** * \brief Decodes SD CSD register */ static void sd_decode_csd(void) { - uint32_t unit; - uint32_t mul; - uint32_t tran_speed; - - /* Get SD memory maximum transfer speed in Hz. */ - tran_speed = CSD_TRAN_SPEED(sd_mmc_card->csd); - unit = sd_mmc_trans_units[tran_speed & 0x7]; - mul = sd_trans_multipliers[(tran_speed >> 3) & 0xF]; - sd_mmc_card->clock = unit * mul * 1000; - - /* - * Get card capacity. - * ---------------------------------------------------- - * For normal SD/MMC card: - * memory capacity = BLOCKNR * BLOCK_LEN - * Where - * BLOCKNR = (C_SIZE+1) * MULT - * MULT = 2 ^ (C_SIZE_MULT+2) (C_SIZE_MULT < 8) - * BLOCK_LEN = 2 ^ READ_BL_LEN (READ_BL_LEN < 12) - * ---------------------------------------------------- - * For high capacity SD card: - * memory capacity = (C_SIZE+1) * 512K byte - */ - if (CSD_STRUCTURE_VERSION(sd_mmc_card->csd) >= SD_CSD_VER_2_0) { - sd_mmc_card->capacity = (SD_CSD_2_0_C_SIZE(sd_mmc_card->csd) + 1) * 512; - } else { - uint32_t blocknr - = ((SD_CSD_1_0_C_SIZE(sd_mmc_card->csd) + 1) * (1 << (SD_CSD_1_0_C_SIZE_MULT(sd_mmc_card->csd) + 2))); - sd_mmc_card->capacity = blocknr * (1 << SD_CSD_1_0_READ_BL_LEN(sd_mmc_card->csd)) / 1024; - } + uint32_t unit; + uint32_t mul; + uint32_t tran_speed; + + /* Get SD memory maximum transfer speed in Hz. */ + tran_speed = CSD_TRAN_SPEED(sd_mmc_card->csd); + unit = sd_mmc_trans_units[tran_speed & 0x7]; + mul = sd_trans_multipliers[(tran_speed >> 3) & 0xF]; + sd_mmc_card->clock = unit * mul * 1000; + + /* + * Get card capacity. + * ---------------------------------------------------- + * For normal SD/MMC card: + * memory capacity = BLOCKNR * BLOCK_LEN + * Where + * BLOCKNR = (C_SIZE+1) * MULT + * MULT = 2 ^ (C_SIZE_MULT+2) (C_SIZE_MULT < 8) + * BLOCK_LEN = 2 ^ READ_BL_LEN (READ_BL_LEN < 12) + * ---------------------------------------------------- + * For high capacity SD card: + * memory capacity = (C_SIZE+1) * 512K byte + */ + if (CSD_STRUCTURE_VERSION(sd_mmc_card->csd) >= SD_CSD_VER_2_0) { + sd_mmc_card->capacity = (SD_CSD_2_0_C_SIZE(sd_mmc_card->csd) + 1) * 512; + } else { + uint32_t blocknr + = ((SD_CSD_1_0_C_SIZE(sd_mmc_card->csd) + 1) * (1 << (SD_CSD_1_0_C_SIZE_MULT(sd_mmc_card->csd) + 2))); + sd_mmc_card->capacity = blocknr * (1 << SD_CSD_1_0_READ_BL_LEN(sd_mmc_card->csd)) / 1024; + } } /** @@ -567,30 +846,31 @@ static void sd_decode_csd(void) */ static bool sd_mmc_cmd13(void) { - uint32_t nec_timeout; - - /* Wait for data ready status. - * Nec timing: 0 to unlimited - * However a timeout is used. - * 200 000 * 8 cycles - */ - nec_timeout = 200000; - do { - if (!driver_send_cmd(sd_mmc_hal, SDMMC_MCI_CMD13_SEND_STATUS, (uint32_t)sd_mmc_card->rca << 16)) { - return false; - } - /* Check busy flag */ - if (driver_get_response(sd_mmc_hal) & CARD_STATUS_READY_FOR_DATA) { - break; - } - if (nec_timeout-- == 0) { - return false; - } - } while (1); - - return true; + uint32_t nec_timeout; + + /* Wait for data ready status. + * Nec timing: 0 to unlimited + * However a timeout is used. + * 200 000 * 8 cycles + */ + nec_timeout = 200000; + do { + if (!driver_send_cmd(sd_mmc_hal, SDMMC_MCI_CMD13_SEND_STATUS, (uint32_t)sd_mmc_card->rca << 16)) { + return false; + } + /* Check busy flag */ + if (driver_get_response(sd_mmc_hal) & CARD_STATUS_READY_FOR_DATA) { + break; + } + if (nec_timeout-- == 0) { + return false; + } + } while (1); + + return true; } +#if (CONF_SDIO_SUPPORT == 1) /** * \brief CMD52 - SDIO IO_RW_DIRECT command * @@ -604,17 +884,17 @@ static bool sd_mmc_cmd13(void) */ static bool sdio_cmd52(uint8_t rw_flag, uint8_t func_nb, uint32_t reg_addr, uint8_t rd_after_wr, uint8_t *io_data) { - ASSERT(io_data != NULL); - if (!driver_send_cmd(sd_mmc_hal, - SDIO_CMD52_IO_RW_DIRECT, - ((uint32_t)*io_data << SDIO_CMD52_WR_DATA) | ((uint32_t)rw_flag << SDIO_CMD52_RW_FLAG) - | ((uint32_t)func_nb << SDIO_CMD52_FUNCTION_NUM) - | ((uint32_t)rd_after_wr << SDIO_CMD52_RAW_FLAG) - | ((uint32_t)reg_addr << SDIO_CMD52_REG_ADRR))) { - return false; - } - *io_data = driver_get_response(sd_mmc_hal) & 0xFF; - return true; + ASSERT(io_data != NULL); + if (!driver_send_cmd(sd_mmc_hal, + SDIO_CMD52_IO_RW_DIRECT, + ((uint32_t)*io_data << SDIO_CMD52_WR_DATA) | ((uint32_t)rw_flag << SDIO_CMD52_RW_FLAG) + | ((uint32_t)func_nb << SDIO_CMD52_FUNCTION_NUM) + | ((uint32_t)rd_after_wr << SDIO_CMD52_RAW_FLAG) + | ((uint32_t)reg_addr << SDIO_CMD52_REG_ADRR))) { + return false; + } + *io_data = driver_get_response(sd_mmc_hal) & 0xFF; + return true; } /** @@ -635,21 +915,20 @@ static bool sdio_cmd52(uint8_t rw_flag, uint8_t func_nb, uint32_t reg_addr, uint static bool sdio_cmd53(uint8_t rw_flag, uint8_t func_nb, uint32_t reg_addr, uint8_t inc_addr, uint32_t size, bool access_block) { - ASSERT(size != 0); - ASSERT(size <= 512); - - return driver_adtc_start(sd_mmc_hal, - (rw_flag == SDIO_CMD53_READ_FLAG) ? SDIO_CMD53_IO_R_BYTE_EXTENDED - : SDIO_CMD53_IO_W_BYTE_EXTENDED, - ((size % 512) << SDIO_CMD53_COUNT) | ((uint32_t)reg_addr << SDIO_CMD53_REG_ADDR) - | ((uint32_t)inc_addr << SDIO_CMD53_OP_CODE) - | ((uint32_t)0 << SDIO_CMD53_BLOCK_MODE) - | ((uint32_t)func_nb << SDIO_CMD53_FUNCTION_NUM) - | ((uint32_t)rw_flag << SDIO_CMD53_RW_FLAG), - size, - 1, - access_block); + ASSERT(size != 0); + ASSERT(size <= 512); + + return driver_adtc_start( + sd_mmc_hal, + (rw_flag == SDIO_CMD53_READ_FLAG) ? SDIO_CMD53_IO_R_BYTE_EXTENDED : SDIO_CMD53_IO_W_BYTE_EXTENDED, + ((size % 512) << SDIO_CMD53_COUNT) | ((uint32_t)reg_addr << SDIO_CMD53_REG_ADDR) + | ((uint32_t)inc_addr << SDIO_CMD53_OP_CODE) | ((uint32_t)0 << SDIO_CMD53_BLOCK_MODE) + | ((uint32_t)func_nb << SDIO_CMD53_FUNCTION_NUM) | ((uint32_t)rw_flag << SDIO_CMD53_RW_FLAG), + size, + 1, + access_block); } +#endif /** * \brief ACMD6 - Define the data bus width to 4 bits bus @@ -658,17 +937,17 @@ static bool sdio_cmd53(uint8_t rw_flag, uint8_t func_nb, uint32_t reg_addr, uint */ static bool sd_acmd6(void) { - /* CMD55 - Indicate to the card that the next command is an - * application specific command rather than a standard command.*/ - if (!driver_send_cmd(sd_mmc_hal, SDMMC_CMD55_APP_CMD, (uint32_t)sd_mmc_card->rca << 16)) { - return false; - } - /* 10b = 4 bits bus */ - if (!driver_send_cmd(sd_mmc_hal, SD_ACMD6_SET_BUS_WIDTH, 0x2)) { - return false; - } - sd_mmc_card->bus_width = 4; - return true; + /* CMD55 - Indicate to the card that the next command is an + * application specific command rather than a standard command.*/ + if (!driver_send_cmd(sd_mmc_hal, SDMMC_CMD55_APP_CMD, (uint32_t)sd_mmc_card->rca << 16)) { + return false; + } + /* 10b = 4 bits bus */ + if (!driver_send_cmd(sd_mmc_hal, SD_ACMD6_SET_BUS_WIDTH, 0x2)) { + return false; + } + sd_mmc_card->bus_width = 4; + return true; } /** @@ -684,46 +963,46 @@ static bool sd_acmd6(void) */ static bool sd_acmd51(void) { - uint8_t scr[SD_SCR_REG_BSIZE]; - - /* CMD55 - Indicate to the card that the next command is an - * application specific command rather than a standard command.*/ - if (!driver_send_cmd(sd_mmc_hal, SDMMC_CMD55_APP_CMD, (uint32_t)sd_mmc_card->rca << 16)) { - return false; - } - if (!driver_adtc_start(sd_mmc_hal, SD_ACMD51_SEND_SCR, 0, SD_SCR_REG_BSIZE, 1, true)) { - return false; - } - if (!driver_start_read_blocks(sd_mmc_hal, scr, 1)) { - return false; - } - if (!driver_wait_end_of_read_blocks(sd_mmc_hal)) { - return false; - } - - /* Get SD Memory Card - Spec. Version */ - switch (SD_SCR_SD_SPEC(scr)) { - case SD_SCR_SD_SPEC_1_0_01: - sd_mmc_card->version = CARD_VER_SD_1_0; - break; - - case SD_SCR_SD_SPEC_1_10: - sd_mmc_card->version = CARD_VER_SD_1_10; - break; - - case SD_SCR_SD_SPEC_2_00: - if (SD_SCR_SD_SPEC3(scr) == SD_SCR_SD_SPEC_3_00) { - sd_mmc_card->version = CARD_VER_SD_3_0; - } else { - sd_mmc_card->version = CARD_VER_SD_2_0; - } - break; - - default: - sd_mmc_card->version = CARD_VER_SD_1_0; - break; - } - return true; + uint8_t scr[SD_SCR_REG_BSIZE]; + + /* CMD55 - Indicate to the card that the next command is an + * application specific command rather than a standard command.*/ + if (!driver_send_cmd(sd_mmc_hal, SDMMC_CMD55_APP_CMD, (uint32_t)sd_mmc_card->rca << 16)) { + return false; + } + if (!driver_adtc_start(sd_mmc_hal, SD_ACMD51_SEND_SCR, 0, SD_SCR_REG_BSIZE, 1, true)) { + return false; + } + if (!driver_start_read_blocks(sd_mmc_hal, scr, 1)) { + return false; + } + if (!driver_wait_end_of_read_blocks(sd_mmc_hal)) { + return false; + } + + /* Get SD Memory Card - Spec. Version */ + switch (SD_SCR_SD_SPEC(scr)) { + case SD_SCR_SD_SPEC_1_0_01: + sd_mmc_card->version = CARD_VER_SD_1_0; + break; + + case SD_SCR_SD_SPEC_1_10: + sd_mmc_card->version = CARD_VER_SD_1_10; + break; + + case SD_SCR_SD_SPEC_2_00: + if (SD_SCR_SD_SPEC3(scr) == SD_SCR_SD_SPEC_3_00) { + sd_mmc_card->version = CARD_VER_SD_3_0; + } else { + sd_mmc_card->version = CARD_VER_SD_2_0; + } + break; + + default: + sd_mmc_card->version = CARD_VER_SD_1_0; + break; + } + return true; } /** @@ -739,38 +1018,61 @@ static bool sd_acmd51(void) */ static sd_mmc_err_t sd_mmc_select_slot(uint8_t slot) { - if (slot >= CONF_SD_MMC_MEM_CNT) { - return SD_MMC_ERR_SLOT; - } - - /** Card Detect sanity check */ - if(!_cd || _cd[slot].pin == -1) { - return SD_MMC_ERR_PARAM; - } - - if (gpio_get_pin_level(_cd[slot].pin) != _cd[slot].val) { - sd_mmc_cards[slot].state = SD_MMC_CARD_STATE_NO_CARD; - return SD_MMC_ERR_NO_CARD; - } - if (sd_mmc_cards[slot].state == SD_MMC_CARD_STATE_NO_CARD) { - /* Card is not initialized */ - sd_mmc_cards[slot].state = SD_MMC_CARD_STATE_INIT; - /* Set 1-bit bus width and low clock for initialization */ - sd_mmc_cards[slot].clock = SDMMC_CLOCK_INIT; - sd_mmc_cards[slot].bus_width = 1; - sd_mmc_cards[slot].high_speed = 0; - } - if (sd_mmc_cards[slot].state == SD_MMC_CARD_STATE_UNUSABLE) { - return SD_MMC_ERR_UNUSABLE; - } - - ASSERT(!(sd_mmc_slot_sel != slot && sd_mmc_nb_block_remaining != 0)); - - /* Initialize interface */ - sd_mmc_slot_sel = slot; - sd_mmc_card = &sd_mmc_cards[slot]; - sd_mmc_configure_slot(); - return (sd_mmc_cards[slot].state == SD_MMC_CARD_STATE_INIT) ? SD_MMC_INIT_ONGOING : SD_MMC_OK; // returns 1 for INIT ongoing + if (slot >= CONF_SD_MMC_MEM_CNT) { + return SD_MMC_ERR_SLOT; + } + + if (_cd && _cd[slot].pin != -1) { + /** Card Detect pins */ + if (gpio_get_pin_level(_cd[slot].pin) != _cd[slot].val) { + if (sd_mmc_cards[slot].state == SD_MMC_CARD_STATE_DEBOUNCE) { + SD_MMC_STOP_TIMEOUT(); + } + sd_mmc_cards[slot].state = SD_MMC_CARD_STATE_NO_CARD; + return SD_MMC_ERR_NO_CARD; + } + if (sd_mmc_cards[slot].state == SD_MMC_CARD_STATE_NO_CARD) { + /* A card plug on going, but this is not initialized */ + sd_mmc_cards[slot].state = SD_MMC_CARD_STATE_DEBOUNCE; + /* Debounce + Power On Setup */ + SD_MMC_START_TIMEOUT(); + return SD_MMC_ERR_NO_CARD; + } + if (sd_mmc_cards[slot].state == SD_MMC_CARD_STATE_DEBOUNCE) { + if (!SD_MMC_IS_TIMEOUT()) { + /* Debounce on going */ + return SD_MMC_ERR_NO_CARD; + } + /* Card is not initialized */ + sd_mmc_cards[slot].state = SD_MMC_CARD_STATE_INIT; + /* Set 1-bit bus width and low clock for initialization */ + sd_mmc_cards[slot].clock = SDMMC_CLOCK_INIT; + sd_mmc_cards[slot].bus_width = 1; + sd_mmc_cards[slot].high_speed = 0; + } + if (sd_mmc_cards[slot].state == SD_MMC_CARD_STATE_UNUSABLE) { + return SD_MMC_ERR_UNUSABLE; + } + } else { + /* No pin card detection, then always try to install it */ + if ((sd_mmc_cards[slot].state == SD_MMC_CARD_STATE_NO_CARD) + || (sd_mmc_cards[slot].state == SD_MMC_CARD_STATE_UNUSABLE)) { + /* Card is not initialized */ + sd_mmc_cards[slot].state = SD_MMC_CARD_STATE_INIT; + /* Set 1-bit bus width and low clock for initialization */ + sd_mmc_cards[slot].clock = SDMMC_CLOCK_INIT; + sd_mmc_cards[slot].bus_width = 1; + sd_mmc_cards[slot].high_speed = 0; + } + } + + ASSERT(!(sd_mmc_slot_sel != slot && sd_mmc_nb_block_remaining != 0)); + + /* Initialize interface */ + sd_mmc_slot_sel = slot; + sd_mmc_card = &sd_mmc_cards[slot]; + sd_mmc_configure_slot(); + return (sd_mmc_cards[slot].state == SD_MMC_CARD_STATE_INIT) ? SD_MMC_INIT_ONGOING : SD_MMC_OK; } /** @@ -778,8 +1080,18 @@ static sd_mmc_err_t sd_mmc_select_slot(uint8_t slot) */ static void sd_mmc_configure_slot(void) { - driver_select_device( - sd_mmc_hal, sd_mmc_slot_sel, sd_mmc_card->clock, sd_mmc_card->bus_width, sd_mmc_card->high_speed); + driver_select_device( + sd_mmc_hal, sd_mmc_slot_sel, sd_mmc_card->clock, sd_mmc_card->bus_width, sd_mmc_card->high_speed); +} + +/** + * \brief Deselect the current card slot + */ +static void sd_mmc_deselect_slot(void) +{ + if (sd_mmc_slot_sel < CONF_SD_MMC_MEM_CNT) { + driver_deselect_device(sd_mmc_hal, sd_mmc_slot_sel); + } } /** @@ -794,448 +1106,570 @@ static void sd_mmc_configure_slot(void) */ static bool sd_mmc_mci_card_init(void) { - uint8_t v2 = 0; - uint8_t data = 0x08; - - /* In first, try to install SD/SDIO card */ - sd_mmc_card->type = CARD_TYPE_SD; - sd_mmc_card->version = CARD_VER_UNKNOWN; - sd_mmc_card->rca = 0; - - /* Card need of 74 cycles clock minimum to start */ - driver_send_clock(sd_mmc_hal); - - /* CMD52 Reset SDIO */ - sdio_cmd52(SDIO_CMD52_WRITE_FLAG, SDIO_CIA, SDIO_CCCR_IOA, 0, &data); - delay_ms(10); - - /* CMD0 - Reset all cards to idle state.*/ - if (!driver_send_cmd(sd_mmc_hal, SDMMC_MCI_CMD0_GO_IDLE_STATE, 0)) { - return false; - } - if (!sd_cmd8(&v2)) { - return false; - } - delay_ms(1); - /* Try to get the SDIO card's operating condition */ - if (!sdio_op_cond()) { - return false; - } - delay_ms(1); - - if (sd_mmc_card->type & CARD_TYPE_SD) { - /* Try to get the SD card's operating condition */ - if (!sd_mci_op_cond(v2)) { - /* It is not a SD card */ - sd_mmc_card->type = CARD_TYPE_UNKNOWN; - return false; - } - } - - if (sd_mmc_card->type & CARD_TYPE_SD) { - /* SD MEMORY, Put the Card in Identify Mode - * Note: The CID is not used in this stack */ - if (!driver_send_cmd(sd_mmc_hal, SDMMC_CMD2_ALL_SEND_CID, 0)) { - return false; - } - } - /* Ask the card to publish a new relative address (RCA).*/ - if (!driver_send_cmd(sd_mmc_hal, SD_CMD3_SEND_RELATIVE_ADDR, 0)) { - return false; - } - sd_mmc_card->rca = (driver_get_response(sd_mmc_hal) >> 16) & 0xFFFF; - - /* SD MEMORY, Get the Card-Specific Data */ - if (sd_mmc_card->type & CARD_TYPE_SD) { - if (!sd_mmc_cmd9_mci()) { - return false; - } - sd_decode_csd(); - } - /* Select the and put it into Transfer Mode */ - if (!driver_send_cmd(sd_mmc_hal, SDMMC_CMD7_SELECT_CARD_CMD, (uint32_t)sd_mmc_card->rca << 16)) { - return false; - } - - /* SD MEMORY, Read the SCR to get card version */ - if (sd_mmc_card->type & CARD_TYPE_SD) { - if (!sd_acmd51()) { - return false; - } - } - if (IS_SDIO()) { - if (!sdio_get_max_speed()) { - return false; - } - } - if ((4 <= driver_get_bus_width(sd_mmc_hal, sd_mmc_slot_sel))) { - /* TRY to enable 4-bit mode */ - if (IS_SDIO()) { - if (!sdio_cmd52_set_bus_width()) { - return false; - } - } - if (sd_mmc_card->type & CARD_TYPE_SD) { - if (!sd_acmd6()) { - return false; - } - } - /* Switch to selected bus mode */ - sd_mmc_configure_slot(); - } - if (driver_is_high_speed_capable(sd_mmc_hal)) { - /* TRY to enable High-Speed Mode */ - if (IS_SDIO()) { - if (!sdio_cmd52_set_high_speed()) { - return false; - } - } - if (sd_mmc_card->type & CARD_TYPE_SD) { - if (sd_mmc_card->version > CARD_VER_SD_1_0) { - if (!sd_cm6_set_high_speed()) { - return false; - } - } - } - /* Valid new configuration */ - sd_mmc_configure_slot(); - } - /* SD MEMORY, Set default block size */ - if (sd_mmc_card->type & CARD_TYPE_SD) { - if (!driver_send_cmd(sd_mmc_hal, SDMMC_CMD16_SET_BLOCKLEN, SD_MMC_BLOCK_SIZE)) { - return false; - } - } - return true; + uint8_t v2 = 0; +#if (CONF_SDIO_SUPPORT == 1) + uint8_t data = 0x08; +#endif + + /* In first, try to install SD/SDIO card */ + sd_mmc_card->type = CARD_TYPE_SD; + sd_mmc_card->version = CARD_VER_UNKNOWN; + sd_mmc_card->rca = 0; + + /* Card need of 74 cycles clock minimum to start */ + driver_send_clock(sd_mmc_hal); + +#if (CONF_SDIO_SUPPORT == 1) + /* CMD52 Reset SDIO */ + sdio_cmd52(SDIO_CMD52_WRITE_FLAG, SDIO_CIA, SDIO_CCCR_IOA, 0, &data); + delay_ms(10); +#endif + + /* CMD0 - Reset all cards to idle state.*/ + if (!driver_send_cmd(sd_mmc_hal, SDMMC_MCI_CMD0_GO_IDLE_STATE, 0)) { + return false; + } + if (!sd_cmd8(&v2)) { + return false; + } + delay_ms(1); + /* Try to get the SDIO card's operating condition */ + if (!sdio_op_cond()) { + return false; + } + delay_ms(1); + + if (sd_mmc_card->type & CARD_TYPE_SD) { + /* Try to get the SD card's operating condition */ + if (!sd_mci_op_cond(v2)) { + /* It is not a SD card */ +#if CONF_MMC_SUPPORT + sd_mmc_card->type = CARD_TYPE_MMC; + return sd_mmc_mci_install_mmc(); +#else + sd_mmc_card->type = CARD_TYPE_UNKNOWN; + return false; +#endif + } + } + + if (sd_mmc_card->type & CARD_TYPE_SD) { + /* SD MEMORY, Put the Card in Identify Mode + * Note: The CID is not used in this stack */ + if (!driver_send_cmd(sd_mmc_hal, SDMMC_CMD2_ALL_SEND_CID, 0)) { + return false; + } + } + /* Ask the card to publish a new relative address (RCA).*/ + if (!driver_send_cmd(sd_mmc_hal, SD_CMD3_SEND_RELATIVE_ADDR, 0)) { + return false; + } + sd_mmc_card->rca = (driver_get_response(sd_mmc_hal) >> 16) & 0xFFFF; + + /* SD MEMORY, Get the Card-Specific Data */ + if (sd_mmc_card->type & CARD_TYPE_SD) { + if (!sd_mmc_cmd9_mci()) { + return false; + } + sd_decode_csd(); + } + /* Select the and put it into Transfer Mode */ + if (!driver_send_cmd(sd_mmc_hal, SDMMC_CMD7_SELECT_CARD_CMD, (uint32_t)sd_mmc_card->rca << 16)) { + return false; + } + /* SD MEMORY, Read the SCR to get card version */ + if (sd_mmc_card->type & CARD_TYPE_SD) { + if (!sd_acmd51()) { + return false; + } + } + if (IS_SDIO()) { + if (!sdio_get_max_speed()) { + return false; + } + } + if ((4 <= driver_get_bus_width(sd_mmc_hal, sd_mmc_slot_sel))) { + /* TRY to enable 4-bit mode */ + if (IS_SDIO()) { + if (!sdio_cmd52_set_bus_width()) { + return false; + } + } + if (sd_mmc_card->type & CARD_TYPE_SD) { + if (!sd_acmd6()) { + return false; + } + } + /* Switch to selected bus mode */ + sd_mmc_configure_slot(); + } + if (driver_is_high_speed_capable(sd_mmc_hal)) { + /* TRY to enable High-Speed Mode */ + if (IS_SDIO()) { + if (!sdio_cmd52_set_high_speed()) { + return false; + } + } + if (sd_mmc_card->type & CARD_TYPE_SD) { + if (sd_mmc_card->version > CARD_VER_SD_1_0) { + if (!sd_cm6_set_high_speed()) { + return false; + } + } + } + /* Valid new configuration */ + sd_mmc_configure_slot(); + } + /* SD MEMORY, Set default block size */ + if (sd_mmc_card->type & CARD_TYPE_SD) { + if (!driver_send_cmd(sd_mmc_hal, SDMMC_CMD16_SET_BLOCKLEN, SD_MMC_BLOCK_SIZE)) { + return false; + } + } + return true; } +#if CONF_MMC_SUPPORT +/** + * \brief Initialize the MMC card in MCI mode. + * + * \note + * This function runs the initialization procedure and the identification + * process, then it sets the SD/MMC card in transfer state. + * At last, it will automaticly enable maximum bus width and transfer speed. + * + * \return true if success, otherwise false + */ +static bool sd_mmc_mci_install_mmc(void) +{ + uint8_t b_authorize_high_speed; + + /* CMD0 - Reset all cards to idle state. */ + if (!driver_send_cmd(sd_mmc_hal, SDMMC_MCI_CMD0_GO_IDLE_STATE, 0)) { + return false; + } + + if (!mmc_mci_op_cond()) { + return false; + } + + /* Put the Card in Identify Mode + * Note: The CID is not used in this stack*/ + if (!driver_send_cmd(sd_mmc_hal, SDMMC_CMD2_ALL_SEND_CID, 0)) { + return false; + } + /* Assign relative address to the card.*/ + sd_mmc_card->rca = 1; + if (!driver_send_cmd(sd_mmc_hal, MMC_CMD3_SET_RELATIVE_ADDR, (uint32_t)sd_mmc_card->rca << 16)) { + return false; + } + /* Get the Card-Specific Data */ + if (!sd_mmc_cmd9_mci()) { + return false; + } + mmc_decode_csd(); + /* Select the and put it into Transfer Mode */ + if (!driver_send_cmd(sd_mmc_hal, SDMMC_CMD7_SELECT_CARD_CMD, (uint32_t)sd_mmc_card->rca << 16)) { + return false; + } + if (sd_mmc_card->version >= CARD_VER_MMC_4) { + /* For MMC 4.0 Higher version + * Get EXT_CSD */ + if (!mmc_cmd8(&b_authorize_high_speed)) { + return false; + } + if (4 <= driver_get_bus_width(sd_mmc_hal, sd_mmc_slot_sel)) { + /* Enable more bus width */ + if (!mmc_cmd6_set_bus_width(driver_get_bus_width(sd_mmc_hal, sd_mmc_slot_sel))) { + return false; + } + /* Reinitialize the slot with the bus width */ + sd_mmc_configure_slot(); + } + if (driver_is_high_speed_capable(sd_mmc_hal) && b_authorize_high_speed) { + /* Enable HS */ + if (!mmc_cmd6_set_high_speed()) { + return false; + } + /* Reinitialize the slot with the new speed */ + sd_mmc_configure_slot(); + } + } else { + /* Reinitialize the slot with the new speed */ + sd_mmc_configure_slot(); + } + + uint8_t retry = 10; + while (retry--) { + /* Retry is a WORKAROUND for no compliance card (Atmel Internal ref. MMC19): + * These cards seem not ready immediatly + * after the end of busy of mmc_cmd6_set_high_speed()*/ + + /* Set default block size */ + if (driver_send_cmd(sd_mmc_hal, SDMMC_CMD16_SET_BLOCKLEN, SD_MMC_BLOCK_SIZE)) { + return true; + } + } + return false; +} +#endif + /*--------------------- PUBLIC FUNCTIONS ----------------------------*/ void sd_mmc_init(void *hal, sd_mmc_detect_t *card_detects, sd_mmc_detect_t *wp_detects) { - /* GPIO will be used to detect card and write protect. - * The related clocks and pinmux must be configurated in good - * condition. */ - - for (uint8_t slot = 0; slot < CONF_SD_MMC_MEM_CNT; slot++) { - sd_mmc_cards[slot].state = SD_MMC_CARD_STATE_NO_CARD; - } - sd_mmc_slot_sel = 0xFF; /* No slot configurated */ - sd_mmc_hal = hal; - _cd = card_detects; - _wp = wp_detects; + /* GPIO will be used to detect card and write protect. + * The related clocks and pinmux must be configurated in good + * condition. */ + + for (uint8_t slot = 0; slot < CONF_SD_MMC_MEM_CNT; slot++) { + sd_mmc_cards[slot].state = SD_MMC_CARD_STATE_NO_CARD; + } + sd_mmc_slot_sel = 0xFF; /* No slot configurated */ + sd_mmc_hal = hal; + _cd = card_detects; + _wp = wp_detects; } uint8_t sd_mmc_nb_slot(void) { - return CONF_SD_MMC_MEM_CNT; + return CONF_SD_MMC_MEM_CNT; } sd_mmc_err_t sd_mmc_check(uint8_t slot) { - sd_mmc_err_t sd_mmc_err; - - sd_mmc_err = sd_mmc_select_slot(slot); - - if (sd_mmc_err != SD_MMC_INIT_ONGOING) { - return sd_mmc_err; - } - - /* Initialization of the card requested */ - if (sd_mmc_mci_card_init()) { - sd_mmc_card->state = SD_MMC_CARD_STATE_READY; - /* To notify that the card has been just initialized - * It is necessary for USB Device MSC */ - return SD_MMC_INIT_ONGOING; - } - - sd_mmc_card->state = SD_MMC_CARD_STATE_UNUSABLE; - return SD_MMC_ERR_UNUSABLE; + sd_mmc_err_t sd_mmc_err; + + sd_mmc_err = sd_mmc_select_slot(slot); + if (sd_mmc_err != SD_MMC_INIT_ONGOING) { + sd_mmc_deselect_slot(); + return sd_mmc_err; + } + + /* Initialization of the card requested */ + if (sd_mmc_mci_card_init()) { + sd_mmc_card->state = SD_MMC_CARD_STATE_READY; + sd_mmc_deselect_slot(); + /* To notify that the card has been just initialized + * It is necessary for USB Device MSC */ + return SD_MMC_INIT_ONGOING; + } + sd_mmc_card->state = SD_MMC_CARD_STATE_UNUSABLE; + sd_mmc_deselect_slot(); + return SD_MMC_ERR_UNUSABLE; } card_type_t sd_mmc_get_type(uint8_t slot) { - if (SD_MMC_OK != sd_mmc_select_slot(slot)) { - return CARD_TYPE_UNKNOWN; - } - return sd_mmc_card->type; + if (SD_MMC_OK != sd_mmc_select_slot(slot)) { + return CARD_TYPE_UNKNOWN; + } + sd_mmc_deselect_slot(); + return sd_mmc_card->type; } card_version_t sd_mmc_get_version(uint8_t slot) { - if (SD_MMC_OK != sd_mmc_select_slot(slot)) { - return CARD_VER_UNKNOWN; - } - return sd_mmc_card->version; + if (SD_MMC_OK != sd_mmc_select_slot(slot)) { + return CARD_VER_UNKNOWN; + } + sd_mmc_deselect_slot(); + return sd_mmc_card->version; } uint32_t sd_mmc_get_capacity(uint8_t slot) { - if (SD_MMC_OK != sd_mmc_select_slot(slot)) { - return 0; - } - return sd_mmc_card->capacity; + if (SD_MMC_OK != sd_mmc_select_slot(slot)) { + return 0; + } + sd_mmc_deselect_slot(); + return sd_mmc_card->capacity; } bool sd_mmc_is_write_protected(uint8_t slot) { - /* No detection, always writable */ - if (!_wp || _wp[slot].pin == -1) { - return false; - } - /* Write Protect Detect */ - if (gpio_get_pin_level(_wp[slot].pin) == _wp[slot].val) { - return true; - } - return false; + /* No detection, always writable */ + if (!_wp || _wp[slot].pin == -1) { + return false; + } + /* Write Protect Detect */ + if (gpio_get_pin_level(_wp[slot].pin) == _wp[slot].val) { + return true; + } + return false; } sd_mmc_err_t sd_mmc_init_read_blocks(uint8_t slot, uint32_t start, uint16_t nb_block) { - sd_mmc_err_t sd_mmc_err; - uint32_t cmd, arg, resp; - - sd_mmc_err = sd_mmc_select_slot(slot); - if (sd_mmc_err != SD_MMC_OK) { - return sd_mmc_err; - } - - /* Wait for data ready status */ - if (!sd_mmc_cmd13()) { - return SD_MMC_ERR_COMM; - } - - if (nb_block > 1) { - cmd = SDMMC_CMD18_READ_MULTIPLE_BLOCK; - } else { - cmd = SDMMC_CMD17_READ_SINGLE_BLOCK; - } - /* - * SDSC Card (CCS=0) uses byte unit address, - * SDHC and SDXC Cards (CCS=1) use block unit address (512 Bytes unit). - */ - if (sd_mmc_card->type & CARD_TYPE_HC) { - arg = start; - } else { - arg = (start * SD_MMC_BLOCK_SIZE); - } - - if (!driver_adtc_start(sd_mmc_hal, cmd, arg, SD_MMC_BLOCK_SIZE, nb_block, true)) { - return SD_MMC_ERR_COMM; - } - /* Check response */ - resp = driver_get_response(sd_mmc_hal); - if (resp & CARD_STATUS_ERR_RD_WR) { - return SD_MMC_ERR_COMM; - } - - sd_mmc_nb_block_remaining = nb_block; - sd_mmc_nb_block_to_tranfer = nb_block; - return SD_MMC_OK; + sd_mmc_err_t sd_mmc_err; + uint32_t cmd, arg, resp; + + sd_mmc_err = sd_mmc_select_slot(slot); + if (sd_mmc_err != SD_MMC_OK) { + return sd_mmc_err; + } + + /* Wait for data ready status */ + if (!sd_mmc_cmd13()) { + sd_mmc_deselect_slot(); + return SD_MMC_ERR_COMM; + } + + if (nb_block > 1) { + cmd = SDMMC_CMD18_READ_MULTIPLE_BLOCK; + } else { + cmd = SDMMC_CMD17_READ_SINGLE_BLOCK; + } + /* + * SDSC Card (CCS=0) uses byte unit address, + * SDHC and SDXC Cards (CCS=1) use block unit address (512 Bytes unit). + */ + if (sd_mmc_card->type & CARD_TYPE_HC) { + arg = start; + } else { + arg = (start * SD_MMC_BLOCK_SIZE); + } + + if (!driver_adtc_start(sd_mmc_hal, cmd, arg, SD_MMC_BLOCK_SIZE, nb_block, true)) { + sd_mmc_deselect_slot(); + return SD_MMC_ERR_COMM; + } + /* Check response */ + resp = driver_get_response(sd_mmc_hal); + if (resp & CARD_STATUS_ERR_RD_WR) { + sd_mmc_deselect_slot(); + return SD_MMC_ERR_COMM; + } + + sd_mmc_nb_block_remaining = nb_block; + sd_mmc_nb_block_to_tranfer = nb_block; + return SD_MMC_OK; } sd_mmc_err_t sd_mmc_start_read_blocks(void *dest, uint16_t nb_block) { - ASSERT(sd_mmc_nb_block_remaining >= nb_block); - - if (!driver_start_read_blocks(sd_mmc_hal, dest, nb_block)) { - sd_mmc_nb_block_remaining = 0; - return SD_MMC_ERR_COMM; - } - sd_mmc_nb_block_remaining -= nb_block; - return SD_MMC_OK; + ASSERT(sd_mmc_nb_block_remaining >= nb_block); + + if (!driver_start_read_blocks(sd_mmc_hal, dest, nb_block)) { + sd_mmc_nb_block_remaining = 0; + return SD_MMC_ERR_COMM; + } + sd_mmc_nb_block_remaining -= nb_block; + return SD_MMC_OK; } sd_mmc_err_t sd_mmc_wait_end_of_read_blocks(bool abort) { - if (!driver_wait_end_of_read_blocks(sd_mmc_hal)) { - return SD_MMC_ERR_COMM; - } - if (abort) { - sd_mmc_nb_block_remaining = 0; - } else if (sd_mmc_nb_block_remaining) { - return SD_MMC_OK; - } - - /* All blocks are transfered then stop read operation */ - if (sd_mmc_nb_block_to_tranfer == 1) { - /* Single block transfer, then nothing to do */ - return SD_MMC_OK; - } - /* WORKAROUND for no compliance card (Atmel Internal ref. !MMC7 !SD19): - * The errors on this command must be ignored - * and one retry can be necessary in SPI mode for no compliance card.*/ - if (!driver_adtc_stop(sd_mmc_hal, SDMMC_CMD12_STOP_TRANSMISSION, 0)) { - driver_adtc_stop(sd_mmc_hal, SDMMC_CMD12_STOP_TRANSMISSION, 0); - } - return SD_MMC_OK; + if (!driver_wait_end_of_read_blocks(sd_mmc_hal)) { + return SD_MMC_ERR_COMM; + } + if (abort) { + sd_mmc_nb_block_remaining = 0; + } else if (sd_mmc_nb_block_remaining) { + return SD_MMC_OK; + } + + /* All blocks are transfered then stop read operation */ + if (sd_mmc_nb_block_to_tranfer == 1) { + /* Single block transfer, then nothing to do */ + sd_mmc_deselect_slot(); + return SD_MMC_OK; + } + /* WORKAROUND for no compliance card (Atmel Internal ref. !MMC7 !SD19): + * The errors on this command must be ignored + * and one retry can be necessary in SPI mode for no compliance card.*/ + if (!driver_adtc_stop(sd_mmc_hal, SDMMC_CMD12_STOP_TRANSMISSION, 0)) { + driver_adtc_stop(sd_mmc_hal, SDMMC_CMD12_STOP_TRANSMISSION, 0); + } + sd_mmc_deselect_slot(); + return SD_MMC_OK; } sd_mmc_err_t sd_mmc_init_write_blocks(uint8_t slot, uint32_t start, uint16_t nb_block) { - sd_mmc_err_t sd_mmc_err; - uint32_t cmd, arg, resp; - - sd_mmc_err = sd_mmc_select_slot(slot); - if (sd_mmc_err != SD_MMC_OK) { - return sd_mmc_err; - } - if (sd_mmc_is_write_protected(slot)) { - return SD_MMC_ERR_WP; - } - - if (nb_block > 1) { - cmd = SDMMC_CMD25_WRITE_MULTIPLE_BLOCK; - } else { - cmd = SDMMC_CMD24_WRITE_BLOCK; - } - /* - * SDSC Card (CCS=0) uses byte unit address, - * SDHC and SDXC Cards (CCS=1) use block unit address (512 Bytes unit). - */ - if (sd_mmc_card->type & CARD_TYPE_HC) { - arg = start; - } else { - arg = (start * SD_MMC_BLOCK_SIZE); - } - if (!driver_adtc_start(sd_mmc_hal, cmd, arg, SD_MMC_BLOCK_SIZE, nb_block, true)) { - return SD_MMC_ERR_COMM; - } - /* Check response */ - resp = driver_get_response(sd_mmc_hal); - if (resp & CARD_STATUS_ERR_RD_WR) { - return SD_MMC_ERR_COMM; - } - - sd_mmc_nb_block_remaining = nb_block; - sd_mmc_nb_block_to_tranfer = nb_block; - return SD_MMC_OK; + sd_mmc_err_t sd_mmc_err; + uint32_t cmd, arg, resp; + + sd_mmc_err = sd_mmc_select_slot(slot); + if (sd_mmc_err != SD_MMC_OK) { + return sd_mmc_err; + } + if (sd_mmc_is_write_protected(slot)) { + sd_mmc_deselect_slot(); + return SD_MMC_ERR_WP; + } + + if (nb_block > 1) { + cmd = SDMMC_CMD25_WRITE_MULTIPLE_BLOCK; + } else { + cmd = SDMMC_CMD24_WRITE_BLOCK; + } + /* + * SDSC Card (CCS=0) uses byte unit address, + * SDHC and SDXC Cards (CCS=1) use block unit address (512 Bytes unit). + */ + if (sd_mmc_card->type & CARD_TYPE_HC) { + arg = start; + } else { + arg = (start * SD_MMC_BLOCK_SIZE); + } + if (!driver_adtc_start(sd_mmc_hal, cmd, arg, SD_MMC_BLOCK_SIZE, nb_block, true)) { + sd_mmc_deselect_slot(); + return SD_MMC_ERR_COMM; + } + /* Check response */ + resp = driver_get_response(sd_mmc_hal); + if (resp & CARD_STATUS_ERR_RD_WR) { + sd_mmc_deselect_slot(); + return SD_MMC_ERR_COMM; + } + + sd_mmc_nb_block_remaining = nb_block; + sd_mmc_nb_block_to_tranfer = nb_block; + return SD_MMC_OK; } sd_mmc_err_t sd_mmc_start_write_blocks(const void *src, uint16_t nb_block) { - ASSERT(sd_mmc_nb_block_remaining >= nb_block); - if (!driver_start_write_blocks(sd_mmc_hal, src, nb_block)) { - sd_mmc_nb_block_remaining = 0; - return SD_MMC_ERR_COMM; - } - sd_mmc_nb_block_remaining -= nb_block; - return SD_MMC_OK; + ASSERT(sd_mmc_nb_block_remaining >= nb_block); + if (!driver_start_write_blocks(sd_mmc_hal, src, nb_block)) { + sd_mmc_nb_block_remaining = 0; + return SD_MMC_ERR_COMM; + } + sd_mmc_nb_block_remaining -= nb_block; + return SD_MMC_OK; } sd_mmc_err_t sd_mmc_wait_end_of_write_blocks(bool abort) { - if (!driver_wait_end_of_write_blocks(sd_mmc_hal)) { - return SD_MMC_ERR_COMM; - } - if (abort) { - sd_mmc_nb_block_remaining = 0; - } else if (sd_mmc_nb_block_remaining) { - return SD_MMC_OK; - } - - /* All blocks are transfered then stop write operation */ - if (sd_mmc_nb_block_to_tranfer == 1) { - /* Single block transfer, then nothing to do */ - return SD_MMC_OK; - } - - /* Note: SPI multiblock writes terminate using a special - * token, not a STOP_TRANSMISSION request.*/ - if (!driver_adtc_stop(sd_mmc_hal, SDMMC_CMD12_STOP_TRANSMISSION, 0)) { - return SD_MMC_ERR_COMM; - } - - return SD_MMC_OK; + if (!driver_wait_end_of_write_blocks(sd_mmc_hal)) { + return SD_MMC_ERR_COMM; + } + if (abort) { + sd_mmc_nb_block_remaining = 0; + } else if (sd_mmc_nb_block_remaining) { + return SD_MMC_OK; + } + + /* All blocks are transfered then stop write operation */ + if (sd_mmc_nb_block_to_tranfer == 1) { + /* Single block transfer, then nothing to do */ + sd_mmc_deselect_slot(); + return SD_MMC_OK; + } + + /* Note: SPI multiblock writes terminate using a special + * token, not a STOP_TRANSMISSION request.*/ + if (!driver_adtc_stop(sd_mmc_hal, SDMMC_CMD12_STOP_TRANSMISSION, 0)) { + sd_mmc_deselect_slot(); + return SD_MMC_ERR_COMM; + } + + sd_mmc_deselect_slot(); + return SD_MMC_OK; } +#if (CONF_SDIO_SUPPORT == 1) sd_mmc_err_t sdio_read_direct(uint8_t slot, uint8_t func_num, uint32_t addr, uint8_t *dest) { - sd_mmc_err_t sd_mmc_err; - - if (dest == NULL) { - return SD_MMC_ERR_PARAM; - } - - sd_mmc_err = sd_mmc_select_slot(slot); - if (sd_mmc_err != SD_MMC_OK) { - return sd_mmc_err; - } - - if (!sdio_cmd52(SDIO_CMD52_READ_FLAG, func_num, addr, 0, dest)) { - return SD_MMC_ERR_COMM; - } - return SD_MMC_OK; + sd_mmc_err_t sd_mmc_err; + + if (dest == NULL) { + return SD_MMC_ERR_PARAM; + } + + sd_mmc_err = sd_mmc_select_slot(slot); + if (sd_mmc_err != SD_MMC_OK) { + return sd_mmc_err; + } + + if (!sdio_cmd52(SDIO_CMD52_READ_FLAG, func_num, addr, 0, dest)) { + sd_mmc_deselect_slot(); + return SD_MMC_ERR_COMM; + } + sd_mmc_deselect_slot(); + return SD_MMC_OK; } sd_mmc_err_t sdio_write_direct(uint8_t slot, uint8_t func_num, uint32_t addr, uint8_t data) { - sd_mmc_err_t sd_mmc_err; + sd_mmc_err_t sd_mmc_err; - sd_mmc_err = sd_mmc_select_slot(slot); - if (sd_mmc_err != SD_MMC_OK) { - return sd_mmc_err; - } + sd_mmc_err = sd_mmc_select_slot(slot); + if (sd_mmc_err != SD_MMC_OK) { + return sd_mmc_err; + } - if (!sdio_cmd52(SDIO_CMD52_WRITE_FLAG, func_num, addr, 0, &data)) { - return SD_MMC_ERR_COMM; - } + if (!sdio_cmd52(SDIO_CMD52_WRITE_FLAG, func_num, addr, 0, &data)) { + sd_mmc_deselect_slot(); + return SD_MMC_ERR_COMM; + } - return SD_MMC_OK; + sd_mmc_deselect_slot(); + return SD_MMC_OK; } sd_mmc_err_t sdio_read_extended(uint8_t slot, uint8_t func_num, uint32_t addr, uint8_t inc_addr, uint8_t *dest, uint16_t size) { - sd_mmc_err_t sd_mmc_err; - - if ((size == 0) || (size > 512)) { - return SD_MMC_ERR_PARAM; - } - - sd_mmc_err = sd_mmc_select_slot(slot); - if (sd_mmc_err != SD_MMC_OK) { - return sd_mmc_err; - } - - if (!sdio_cmd53(SDIO_CMD53_READ_FLAG, func_num, addr, inc_addr, size, true)) { - return SD_MMC_ERR_COMM; - } - if (!driver_start_read_blocks(sd_mmc_hal, dest, 1)) { - return SD_MMC_ERR_COMM; - } - if (!driver_wait_end_of_read_blocks(sd_mmc_hal)) { - return SD_MMC_ERR_COMM; - } - - return SD_MMC_OK; + sd_mmc_err_t sd_mmc_err; + + if ((size == 0) || (size > 512)) { + return SD_MMC_ERR_PARAM; + } + + sd_mmc_err = sd_mmc_select_slot(slot); + if (sd_mmc_err != SD_MMC_OK) { + return sd_mmc_err; + } + + if (!sdio_cmd53(SDIO_CMD53_READ_FLAG, func_num, addr, inc_addr, size, true)) { + sd_mmc_deselect_slot(); + return SD_MMC_ERR_COMM; + } + if (!driver_start_read_blocks(sd_mmc_hal, dest, 1)) { + sd_mmc_deselect_slot(); + return SD_MMC_ERR_COMM; + } + if (!driver_wait_end_of_read_blocks(sd_mmc_hal)) { + sd_mmc_deselect_slot(); + return SD_MMC_ERR_COMM; + } + + sd_mmc_deselect_slot(); + return SD_MMC_OK; } sd_mmc_err_t sdio_write_extended(uint8_t slot, uint8_t func_num, uint32_t addr, uint8_t inc_addr, uint8_t *src, uint16_t size) { - sd_mmc_err_t sd_mmc_err; - - if ((size == 0) || (size > 512)) { - return SD_MMC_ERR_PARAM; - } - - sd_mmc_err = sd_mmc_select_slot(slot); - if (sd_mmc_err != SD_MMC_OK) { - return sd_mmc_err; - } - - if (!sdio_cmd53(SDIO_CMD53_WRITE_FLAG, func_num, addr, inc_addr, size, true)) { - return SD_MMC_ERR_COMM; - } - if (!driver_start_write_blocks(sd_mmc_hal, src, 1)) { - return SD_MMC_ERR_COMM; - } - if (!driver_wait_end_of_write_blocks(sd_mmc_hal)) { - return SD_MMC_ERR_COMM; - } - - return SD_MMC_OK; + sd_mmc_err_t sd_mmc_err; + + if ((size == 0) || (size > 512)) { + return SD_MMC_ERR_PARAM; + } + + sd_mmc_err = sd_mmc_select_slot(slot); + if (sd_mmc_err != SD_MMC_OK) { + return sd_mmc_err; + } + + if (!sdio_cmd53(SDIO_CMD53_WRITE_FLAG, func_num, addr, inc_addr, size, true)) { + sd_mmc_deselect_slot(); + return SD_MMC_ERR_COMM; + } + if (!driver_start_write_blocks(sd_mmc_hal, src, 1)) { + sd_mmc_deselect_slot(); + return SD_MMC_ERR_COMM; + } + if (!driver_wait_end_of_write_blocks(sd_mmc_hal)) { + sd_mmc_deselect_slot(); + return SD_MMC_ERR_COMM; + } + + sd_mmc_deselect_slot(); + return SD_MMC_OK; } +#endif /** @} */ diff --git a/external/asf4-drivers/sd_mmc/sd_mmc.h b/external/asf4-drivers/sd_mmc/sd_mmc.h index 958e748cd7..1437e5efd5 100644 --- a/external/asf4-drivers/sd_mmc/sd_mmc.h +++ b/external/asf4-drivers/sd_mmc/sd_mmc.h @@ -3,51 +3,42 @@ * * \brief Common SD/MMC stack header file * - * Copyright (c) 2012-2016 Atmel Corporation. All rights reserved. + * Copyright (c) 2012-2018 Microchip Technology Inc. and its subsidiaries. * * \asf_license_start * * \page License * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. The name of Atmel may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * 4. This software may only be redistributed and used in connection with an - * Atmel microcontroller product. - * - * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE - * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. * * \asf_license_stop * */ /* - * Support and FAQ: visit Atmel Support + * Support and FAQ: visit Microchip Support */ #ifndef SD_MMC_H_INCLUDED #define SD_MMC_H_INCLUDED #include "compiler.h" +#include "conf_sd_mmc.h" #ifdef __cplusplus extern "C" { @@ -68,8 +59,6 @@ extern "C" { * @{ */ -#define CONF_SD_MMC_MEM_CNT 1 /**< Number of card slots available */ - typedef uint8_t sd_mmc_err_t; /**< Type of return error code */ /** \name Return error codes */ @@ -115,8 +104,8 @@ typedef uint8_t card_version_t; /**< Type of card version */ /** Card detect setting */ typedef struct sd_mmc_detect { - int16_t pin; /**< Detection pin, -1 if no such pin */ - uint16_t val; /**< Detection value */ + int16_t pin; /**< Detection pin, -1 if no such pin */ + uint16_t val; /**< Detection value */ } sd_mmc_detect_t; /** This SD MMC stack uses the maximum block size autorized (512 bytes) */ @@ -251,6 +240,7 @@ sd_mmc_err_t sd_mmc_start_write_blocks(const void *src, uint16_t nb_block); */ sd_mmc_err_t sd_mmc_wait_end_of_write_blocks(bool abort); +#if (CONF_SDIO_SUPPORT == 1) /** * \brief Read one byte from SDIO using RW_DIRECT command. * @@ -309,6 +299,7 @@ sd_mmc_err_t sdio_read_extended(uint8_t slot, uint8_t func_num, uint32_t addr, u */ sd_mmc_err_t sdio_write_extended(uint8_t slot, uint8_t func_num, uint32_t addr, uint8_t inc_addr, uint8_t *src, uint16_t size); +#endif /* SDIO_SUPPORT_ENABLE */ /** @} */ diff --git a/external/asf4-drivers/sd_mmc/sd_mmc_protocol.h b/external/asf4-drivers/sd_mmc/sd_mmc_protocol.h index 84aee8fe40..0516e4fd10 100644 --- a/external/asf4-drivers/sd_mmc/sd_mmc_protocol.h +++ b/external/asf4-drivers/sd_mmc/sd_mmc_protocol.h @@ -3,45 +3,35 @@ * * \brief SD/MMC protocol definitions. * - * Copyright (c) 2014-2016 Atmel Corporation. All rights reserved. + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. * * \asf_license_start * * \page License * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. The name of Atmel may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * 4. This software may only be redistributed and used in connection with an - * Atmel microcontroller product. - * - * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE - * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. * * \asf_license_stop * */ /* - * Support and FAQ: visit Atmel Support + * Support and FAQ: visit Microchip Support */ #ifndef SD_MMC_PROTOCOL_H_INCLUDED @@ -736,15 +726,15 @@ static inline uint32_t SDMMC_UNSTUFF_BITS(uint8_t *reg, uint16_t reg_size, uint1 if (((pos % 8) + size) > 16) { value |= (uint32_t)reg[((reg_size - pos + 7) / 8) - 3] << (16 - (pos % 8)); } - if (((pos % 8) + size) > 16) { - value |= (uint32_t)reg[((reg_size - pos + 7) / 8) - 3] << (16 - (pos % 8)); + if (((pos % 8) + size) > 24) { + value |= (uint32_t)reg[((reg_size - pos + 7) / 8) - 3] << (24 - (pos % 8)); } value &= ((uint32_t)1 << size) - 1; return value; } -//! \name CSD Fields -//! @{ + //! \name CSD Fields + //! @{ #define CSD_REG_BIT_SIZE 128 //!< 128 bits #define CSD_REG_BSIZE (CSD_REG_BIT_SIZE / 8) //!< 16 bytes #define CSD_STRUCTURE(csd, pos, size) SDMMC_UNSTUFF_BITS(csd, CSD_REG_BIT_SIZE, pos, size) @@ -763,10 +753,10 @@ static inline uint32_t SDMMC_UNSTUFF_BITS(uint8_t *reg, uint16_t reg_size, uint1 #define MMC_CSD_C_SIZE_MULT(csd) CSD_STRUCTURE(csd, 47, 3) #define MMC_CSD_READ_BL_LEN(csd) CSD_STRUCTURE(csd, 80, 4) #define MMC_CSD_SPEC_VERS(csd) CSD_STRUCTURE(csd, 122, 4) -//! @} + //! @} -//! \name OCR Register Fields -//! @{ + //! \name OCR Register Fields + //! @{ #define OCR_REG_BSIZE (32 / 8) /**< 32 bits, 4 bytes */ #define OCR_VDD_170_195 (1lu << 7) #define OCR_VDD_20_21 (1lu << 8) @@ -793,10 +783,10 @@ static inline uint32_t SDMMC_UNSTUFF_BITS(uint8_t *reg, uint16_t reg_size, uint1 #define OCR_ACCESS_MODE_SECTOR (2lu << 29) /**< (MMC) Sector access mode */ #define OCR_CCS (1lu << 30) /**< (SD) Card Capacity Status */ #define OCR_POWER_UP_BUSY (1lu << 31) /**< Card power up status bit */ - //! @} + //! @} -//! \name SD SCR Register Fields -//! @{ + //! \name SD SCR Register Fields + //! @{ #define SD_SCR_REG_BIT_SIZE 64 //!< 64 bits #define SD_SCR_REG_BSIZE (SD_SCR_REG_BIT_SIZE / 8) //!< 8 bytes #define SD_SCR_STRUCTURE(scr, pos, size) SDMMC_UNSTUFF_BITS(scr, SD_SCR_REG_BIT_SIZE, pos, size) @@ -820,10 +810,10 @@ static inline uint32_t SDMMC_UNSTUFF_BITS(uint8_t *reg, uint16_t reg_size, uint1 #define SD_SCR_SD_SPEC_3_00 1 #define SD_SCR_SD_EX_SECURITY(scr) SD_SCR_STRUCTURE(scr, 43, 4) #define SD_SCR_SD_CMD_SUPPORT(scr) SD_SCR_STRUCTURE(scr, 32, 2) -//! @} + //! @} -//! \name SD Switch Status Fields -//! @{ + //! \name SD Switch Status Fields + //! @{ #define SD_SW_STATUS_BIT_SIZE 512 //!< 512 bits #define SD_SW_STATUS_BSIZE (SD_SW_STATUS_BIT_SIZE / 8) //!< 64 bytes #define SD_SW_STATUS_STRUCTURE(sd_sw_status, pos, size) \ @@ -849,10 +839,10 @@ static inline uint32_t SDMMC_UNSTUFF_BITS(uint8_t *reg, uint16_t reg_size, uint1 #define SD_SW_STATUS_FUN_GRP3_BUSY(status) SD_SW_STATUS_STRUCTURE(status, 304, 16) #define SD_SW_STATUS_FUN_GRP2_BUSY(status) SD_SW_STATUS_STRUCTURE(status, 288, 16) #define SD_SW_STATUS_FUN_GRP1_BUSY(status) SD_SW_STATUS_STRUCTURE(status, 272, 16) -//! @} + //! @} -//! \name Card Status Fields -//! @{ + //! \name Card Status Fields + //! @{ #define CARD_STATUS_APP_CMD (1lu << 5) #define CARD_STATUS_SWITCH_ERROR (1lu << 7) #define CARD_STATUS_READY_FOR_DATA (1lu << 8) @@ -887,19 +877,16 @@ static inline uint32_t SDMMC_UNSTUFF_BITS(uint8_t *reg, uint16_t reg_size, uint1 #define CARD_STATUS_ERR_RD_WR \ (CARD_STATUS_ADDR_OUT_OF_RANGE | CARD_STATUS_ADDRESS_MISALIGN | CARD_STATUS_BLOCK_LEN_ERROR \ - | CARD_STATUS_WP_VIOLATION \ - | CARD_STATUS_ILLEGAL_COMMAND \ - | CARD_STATUS_CC_ERROR \ - | CARD_STATUS_ERROR) -//! @} + | CARD_STATUS_WP_VIOLATION | CARD_STATUS_ILLEGAL_COMMAND | CARD_STATUS_CC_ERROR | CARD_STATUS_ERROR) + //! @} -//! \name SD Status Field -//! @{ + //! \name SD Status Field + //! @{ #define SD_STATUS_BSIZE (512 / 8) /**< 512 bits, 64bytes */ - //! @} + //! @} -//! \name MMC Extended CSD Register Field -//! @{ + //! \name MMC Extended CSD Register Field + //! @{ #define EXT_CSD_BSIZE 512 /**< 512 bytes. */ /* Below belongs to Properties Segment */ #define EXT_CSD_S_CMD_SET_INDEX 504lu @@ -941,7 +928,7 @@ static inline uint32_t SDMMC_UNSTUFF_BITS(uint8_t *reg, uint16_t reg_size, uint1 #define EXT_CSD_BOOT_CONFIG_INDEX 179lu #define EXT_CSD_BOOT_BUS_WIDTH_INDEX 177lu #define EXT_CSD_ERASE_GROUP_DEF_INDEX 175lu -//! @} + //! @} //! @} //! \name Definition for SPI mode only @@ -990,9 +977,9 @@ static inline uint32_t SDMMC_UNSTUFF_BITS(uint8_t *reg, uint16_t reg_size, uint1 #define SPI_TOKEN_DATA_ERROR_CC_ERROR (1lu << 1) #define SPI_TOKEN_DATA_ERROR_ECC_ERROR (1lu << 2) #define SPI_TOKEN_DATA_ERROR_OUT_RANGE (1lu << 3) -//! @} -//! \name Tokens used for a write operation -//! @{ + //! @} + //! \name Tokens used for a write operation + //! @{ #define SPI_TOKEN_SINGLE_WRITE 0xFE #define SPI_TOKEN_MULTI_WRITE 0xFC #define SPI_TOKEN_STOP_TRAN 0xFD @@ -1001,11 +988,11 @@ static inline uint32_t SDMMC_UNSTUFF_BITS(uint8_t *reg, uint16_t reg_size, uint1 #define SPI_TOKEN_DATA_RESP_ACCEPTED (2lu << 1) #define SPI_TOKEN_DATA_RESP_CRC_ERR (5lu << 1) #define SPI_TOKEN_DATA_RESP_WRITE_ERR (6lu << 1) -//! @} -//! @} -//! @} + //! @} + //! @} + //! @} -//! @} end of sd_mmc_protocol + //! @} end of sd_mmc_protocol #ifdef __cplusplus } diff --git a/src/sd.c b/src/sd.c index 8d0462a4cc..d1e4e69ec5 100644 --- a/src/sd.c +++ b/src/sd.c @@ -315,10 +315,11 @@ bool sd_card_inserted(void) return true; #else sd_mmc_err_t err = sd_mmc_check(0); - /* If initialization is ongoing, wait up to 1 second for it to initialize */ - if (err == SD_MMC_INIT_ONGOING) { - for (int i = 0; i < 10; ++i) { - delay_ms(100); + /* If initialization is ongoing, wait up to 1 second for it to initialize. */ + /* The first time sd_mmc_check is called it may return SD_MMC_ERR_NO_CARD. */ + if (err == SD_MMC_ERR_NO_CARD || err == SD_MMC_INIT_ONGOING) { + for (int i = 0; i < 100; ++i) { + delay_ms(10); err = sd_mmc_check(0); if (err != SD_MMC_INIT_ONGOING) { break; @@ -334,7 +335,7 @@ bool sd_card_inserted(void) util_log("sd_mmc_check returned \"SD_MMC_ERR_UNUSABLE\""); break; case SD_MMC_INIT_ONGOING: - util_log("sd_mmc_check returned \"SD_MMC_INIT_ONGOING\" after 10 retries"); + util_log("sd_mmc_check returned \"SD_MMC_INIT_ONGOING\" after 1s"); break; default: util_log("sd_mmc_check returned %d", err);