drivers: USDHC: Enable detection using DAT3 pulldown

Enable USDHC host to detect inserted SD card via DAT3 line pulldown.

Signed-off-by: Daniel DeGrasse <daniel.degrasse@nxp.com>
This commit is contained in:
Daniel DeGrasse 2021-11-15 11:45:02 -06:00 committed by Anas Nashif
commit 57f35bbf5a
7 changed files with 125 additions and 2 deletions

View file

@ -41,6 +41,10 @@ config SDMMC_USDHC
File system on a SDHC card accessed over
NXP USDHC.
if SDMMC_USDHC
source "drivers/disk/Kconfig.usdhc"
endif
config SDMMC_STM32
bool "STM32 SDMMC driver"
depends on HAS_STM32CUBE

View file

@ -0,0 +1,18 @@
# Copyright (c) 2021 NXP
# SPDX-License-Identifier: Apache-2.0
# USDHC peripheral require the SD card to power cycle after DAT3 is
# pulled low
config SDMMC_USDHC_DAT3_PWR_TOGGLE
bool
help
USDHC peripheral requires the SD card power to be cycled after DAT3 is
pulled high, before the USDHC peripheral can detect the SD card via DAT3
pull
config SDMMC_USDHC_DAT3_PWR_DELAY
int
default 0
help
Period in milliseconds to delay between powering off the SD card and
applying power again, whenever the SD card power will be cycled.

View file

@ -388,6 +388,8 @@ struct usdhc_config {
uint8_t detect_pin;
gpio_dt_flags_t detect_flags;
bool detect_dat3;
bool no_1_8_v;
uint32_t data_timeout;
@ -515,6 +517,9 @@ enum usdhc_xfer_data_type {
#define CARD_BUS_STRENGTH_6 (6U)
#define CARD_BUS_STRENGTH_7 (7U)
#define USDHC_DAT3_PULL_DOWN 0U /*!< Data 3 pull down */
#define USDHC_DAT3_PULL_UP 1U /*!< Data 3 pull up */
enum usdhc_adma_flag {
USDHC_ADMA_SINGLE_FLAG = 0U,
USDHC_ADMA_MUTI_FLAG = 1U,
@ -2604,6 +2609,33 @@ APP_SEND_OP_COND_AGAIN:
static K_MUTEX_DEFINE(z_usdhc_init_lock);
static int usdhc_dat3_pull(bool pullup, struct usdhc_priv *priv)
{
int ret = 0U;
/* Call board specific function to pull down DAT3 */
imxrt_usdhc_dat3_pull(pullup);
#ifdef CONFIG_SDMMC_USDHC_DAT3_PWR_TOGGLE
if (!pullup) {
/* Power off the card to clear DAT3 legacy status */
if (priv->pwr_gpio) {
ret = gpio_pin_set(priv->pwr_gpio, priv->config->pwr_pin, 0);
if (ret) {
return ret;
}
/* Delay for card power off to complete */
usdhc_millsec_delay(CONFIG_SDMMC_USDHC_DAT3_PWR_DELAY);
ret = gpio_pin_set(priv->pwr_gpio, priv->config->pwr_pin, 1);
if (ret) {
return ret;
}
}
}
#endif
return ret;
}
static int usdhc_board_access_init(struct usdhc_priv *priv)
{
const struct usdhc_config *config = priv->config;
@ -2626,6 +2658,11 @@ static int usdhc_board_access_init(struct usdhc_priv *priv)
}
}
if (config->detect_dat3) {
priv->detect_type = SD_DETECT_HOST_DATA3;
}
if (priv->pwr_gpio) {
ret = gpio_pin_configure(priv->pwr_gpio,
config->pwr_pin,
@ -2643,10 +2680,21 @@ static int usdhc_board_access_init(struct usdhc_priv *priv)
if (!priv->detect_gpio) {
LOG_INF("USDHC detection other than GPIO");
/* DATA3 does not monitor card insertion */
base->PROT_CTRL &= ~USDHC_PROT_CTRL_D3CD_MASK;
if (config->detect_dat3) {
base->PROT_CTRL |= USDHC_PROT_CTRL_D3CD_MASK;
/* Pull down DAT3 */
usdhc_dat3_pull(USDHC_DAT3_PULL_DOWN, priv);
} else {
/* DATA3 does not monitor card insertion */
base->PROT_CTRL &= ~USDHC_PROT_CTRL_D3CD_MASK;
}
if ((base->PRES_STATE & USDHC_PRES_STATE_CINST_MASK) != 0) {
priv->inserted = true;
if (config->detect_dat3) {
usdhc_dat3_pull(USDHC_DAT3_PULL_UP, priv);
/* Disable DAT3 detect function */
base->PROT_CTRL &= ~USDHC_PROT_CTRL_D3CD_MASK;
}
} else {
priv->inserted = false;
return -ENODEV;
@ -2853,6 +2901,7 @@ static int disk_usdhc_init(const struct device *dev)
DISK_ACCESS_USDHC_INIT_PWR(n) \
DISK_ACCESS_USDHC_INIT_CD(n) \
.no_1_8_v = DT_INST_PROP(n, no_1_8_v), \
.detect_dat3 = DT_INST_PROP(n, detect_dat3), \
.data_timeout = USDHC_DATA_TIMEOUT, \
.endian = USDHC_LITTLE_ENDIAN, \
.read_watermark = USDHC_READ_WATERMARK_LEVEL, \

View file

@ -36,5 +36,13 @@ properties:
When the external SD card circuit does not support 1.8V, add this
property to disable 1.8v card voltage of SD card controller.
detect-dat3:
type: boolean
required: false
description: |
Enable the host to detect an SD card via the DAT3 line of the SD card
connection. Requires the board to define a function to pull DAT3 low or
high using pullup/pulldown resistors.
label:
required: true

View file

@ -32,6 +32,12 @@ void imxrt_usdhc_pinmux(uint16_t nusdhc,
void imxrt_usdhc_pinmux_cb_register(usdhc_pin_cfg_cb cb);
typedef void (*usdhc_dat3_cfg_cb)(bool pullup);
void imxrt_usdhc_dat3_cb_register(usdhc_dat3_cfg_cb cb);
void imxrt_usdhc_dat3_pull(bool pullup);
#endif
#ifdef __cplusplus

View file

@ -261,6 +261,25 @@ void imxrt_usdhc_pinmux(uint16_t nusdhc, bool init,
g_usdhc_pin_cfg_cb(nusdhc, init,
speed, strength);
}
/* Usdhc driver needs to reconfigure the dat3 line to a pullup in order to
* detect an SD card on the bus. Expose a callback to do that here. The board
* must register this callback in its init function.
*/
static usdhc_dat3_cfg_cb g_usdhc_dat3_cfg_cb;
void imxrt_usdhc_dat3_cb_register(usdhc_dat3_cfg_cb cb)
{
g_usdhc_dat3_cfg_cb = cb;
}
void imxrt_usdhc_dat3_pull(bool pullup)
{
if (g_usdhc_dat3_cfg_cb) {
g_usdhc_dat3_cfg_cb(pullup);
}
}
#endif
/**

View file

@ -426,6 +426,25 @@ void imxrt_usdhc_pinmux(uint16_t nusdhc, bool init,
g_usdhc_pin_cfg_cb(nusdhc, init,
speed, strength);
}
/* Usdhc driver needs to reconfigure the dat3 line to a pullup in order to
* detect an SD card on the bus. Expose a callback to do that here. The board
* must register this callback in its init function.
*/
static usdhc_dat3_cfg_cb g_usdhc_dat3_cfg_cb;
void imxrt_usdhc_dat3_cb_register(usdhc_dat3_cfg_cb cb)
{
g_usdhc_dat3_cfg_cb = cb;
}
void imxrt_usdhc_dat3_pull(bool pullup)
{
if (g_usdhc_dat3_cfg_cb) {
g_usdhc_dat3_cfg_cb(pullup);
}
}
#endif
/**