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:
parent
4712913872
commit
57f35bbf5a
7 changed files with 125 additions and 2 deletions
|
@ -41,6 +41,10 @@ config SDMMC_USDHC
|
||||||
File system on a SDHC card accessed over
|
File system on a SDHC card accessed over
|
||||||
NXP USDHC.
|
NXP USDHC.
|
||||||
|
|
||||||
|
if SDMMC_USDHC
|
||||||
|
source "drivers/disk/Kconfig.usdhc"
|
||||||
|
endif
|
||||||
|
|
||||||
config SDMMC_STM32
|
config SDMMC_STM32
|
||||||
bool "STM32 SDMMC driver"
|
bool "STM32 SDMMC driver"
|
||||||
depends on HAS_STM32CUBE
|
depends on HAS_STM32CUBE
|
||||||
|
|
18
drivers/disk/Kconfig.usdhc
Normal file
18
drivers/disk/Kconfig.usdhc
Normal 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.
|
|
@ -388,6 +388,8 @@ struct usdhc_config {
|
||||||
uint8_t detect_pin;
|
uint8_t detect_pin;
|
||||||
gpio_dt_flags_t detect_flags;
|
gpio_dt_flags_t detect_flags;
|
||||||
|
|
||||||
|
bool detect_dat3;
|
||||||
|
|
||||||
bool no_1_8_v;
|
bool no_1_8_v;
|
||||||
|
|
||||||
uint32_t data_timeout;
|
uint32_t data_timeout;
|
||||||
|
@ -515,6 +517,9 @@ enum usdhc_xfer_data_type {
|
||||||
#define CARD_BUS_STRENGTH_6 (6U)
|
#define CARD_BUS_STRENGTH_6 (6U)
|
||||||
#define CARD_BUS_STRENGTH_7 (7U)
|
#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 {
|
enum usdhc_adma_flag {
|
||||||
USDHC_ADMA_SINGLE_FLAG = 0U,
|
USDHC_ADMA_SINGLE_FLAG = 0U,
|
||||||
USDHC_ADMA_MUTI_FLAG = 1U,
|
USDHC_ADMA_MUTI_FLAG = 1U,
|
||||||
|
@ -2604,6 +2609,33 @@ APP_SEND_OP_COND_AGAIN:
|
||||||
|
|
||||||
static K_MUTEX_DEFINE(z_usdhc_init_lock);
|
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)
|
static int usdhc_board_access_init(struct usdhc_priv *priv)
|
||||||
{
|
{
|
||||||
const struct usdhc_config *config = priv->config;
|
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) {
|
if (priv->pwr_gpio) {
|
||||||
ret = gpio_pin_configure(priv->pwr_gpio,
|
ret = gpio_pin_configure(priv->pwr_gpio,
|
||||||
config->pwr_pin,
|
config->pwr_pin,
|
||||||
|
@ -2643,10 +2680,21 @@ static int usdhc_board_access_init(struct usdhc_priv *priv)
|
||||||
|
|
||||||
if (!priv->detect_gpio) {
|
if (!priv->detect_gpio) {
|
||||||
LOG_INF("USDHC detection other than GPIO");
|
LOG_INF("USDHC detection other than GPIO");
|
||||||
/* DATA3 does not monitor card insertion */
|
if (config->detect_dat3) {
|
||||||
base->PROT_CTRL &= ~USDHC_PROT_CTRL_D3CD_MASK;
|
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) {
|
if ((base->PRES_STATE & USDHC_PRES_STATE_CINST_MASK) != 0) {
|
||||||
priv->inserted = true;
|
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 {
|
} else {
|
||||||
priv->inserted = false;
|
priv->inserted = false;
|
||||||
return -ENODEV;
|
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_PWR(n) \
|
||||||
DISK_ACCESS_USDHC_INIT_CD(n) \
|
DISK_ACCESS_USDHC_INIT_CD(n) \
|
||||||
.no_1_8_v = DT_INST_PROP(n, no_1_8_v), \
|
.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, \
|
.data_timeout = USDHC_DATA_TIMEOUT, \
|
||||||
.endian = USDHC_LITTLE_ENDIAN, \
|
.endian = USDHC_LITTLE_ENDIAN, \
|
||||||
.read_watermark = USDHC_READ_WATERMARK_LEVEL, \
|
.read_watermark = USDHC_READ_WATERMARK_LEVEL, \
|
||||||
|
|
|
@ -36,5 +36,13 @@ properties:
|
||||||
When the external SD card circuit does not support 1.8V, add this
|
When the external SD card circuit does not support 1.8V, add this
|
||||||
property to disable 1.8v card voltage of SD card controller.
|
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:
|
label:
|
||||||
required: true
|
required: true
|
||||||
|
|
|
@ -32,6 +32,12 @@ void imxrt_usdhc_pinmux(uint16_t nusdhc,
|
||||||
|
|
||||||
void imxrt_usdhc_pinmux_cb_register(usdhc_pin_cfg_cb cb);
|
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
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -261,6 +261,25 @@ void imxrt_usdhc_pinmux(uint16_t nusdhc, bool init,
|
||||||
g_usdhc_pin_cfg_cb(nusdhc, init,
|
g_usdhc_pin_cfg_cb(nusdhc, init,
|
||||||
speed, strength);
|
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
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -426,6 +426,25 @@ void imxrt_usdhc_pinmux(uint16_t nusdhc, bool init,
|
||||||
g_usdhc_pin_cfg_cb(nusdhc, init,
|
g_usdhc_pin_cfg_cb(nusdhc, init,
|
||||||
speed, strength);
|
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
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue