mirror of
https://github.com/apache/nuttx.git
synced 2026-05-20 20:44:39 +08:00
imx9: Add proper initialization of the SD card with different bus speeds
- Change the board's sd-card speed configuration to just specify the wanted frequency - Calculate the proper divisors in the driver - If the sd card frequency exceeds 25 MHz, set the card to high-speed mode This makes it easier to adjust the operating speed of the sd cards and fixes an error where cards are being operated in standard mode at over 25MHz speeds. If the speed is higher than 25MHz, the card needs to be set into high-speed mode. Signed-off-by: Jukka Laitinen <jukka.laitinen@tii.ae>
This commit is contained in:
committed by
Matteo Golin
parent
b4ccaf4b1c
commit
191575eac1
@@ -340,6 +340,7 @@
|
||||
# define USDHC_SYSCTL_SDCLKFS_DIV64 (0x20 << USDHC_SYSCTL_SDCLKFS_SHIFT) /* Base clock / 64 */
|
||||
# define USDHC_SYSCTL_SDCLKFS_DIV128 (0x40 << USDHC_SYSCTL_SDCLKFS_SHIFT) /* Base clock / 128 */
|
||||
# define USDHC_SYSCTL_SDCLKFS_DIV256 (0x80 << USDHC_SYSCTL_SDCLKFS_SHIFT) /* Base clock / 256 */
|
||||
# define USDHC_SYSCTL_SDCLKFS_DIV(p) (((p) >> 1) << USDHC_SYSCTL_SDCLKFS_SHIFT)
|
||||
|
||||
#define USDHC_SYSCTL_DTOCV_SHIFT (16) /* Bits 16-19: Data Timeout Counter Value */
|
||||
#define USDHC_SYSCTL_DTOCV_MASK (0xf << USDHC_SYSCTL_DTOCV_SHIFT)
|
||||
|
||||
+221
-120
@@ -221,6 +221,7 @@ struct imx9_dev_s
|
||||
uint32_t sw_cd_gpio; /* If a non USDHCx CD pin is used,
|
||||
* this is its GPIO */
|
||||
uint32_t cd_invert; /* If true invert the CD pin */
|
||||
uint32_t root_clock_freq; /* Root clock frequency */
|
||||
};
|
||||
|
||||
/* Register logging support */
|
||||
@@ -326,10 +327,9 @@ static void imx9_reset(struct sdio_dev_s *dev);
|
||||
static sdio_capset_t imx9_capabilities(struct sdio_dev_s *dev);
|
||||
static sdio_statset_t imx9_status(struct sdio_dev_s *dev);
|
||||
static void imx9_widebus(struct sdio_dev_s *dev, bool enable);
|
||||
|
||||
#ifdef CONFIG_IMX9_USDHC_ABSFREQ
|
||||
static void imx9_frequency(struct sdio_dev_s *dev, uint32_t frequency);
|
||||
#endif
|
||||
static bool imx9_sdcard_hs_mode(struct sdio_dev_s *dev, bool set);
|
||||
static uint32_t imx9_frequency(struct sdio_dev_s *dev,
|
||||
unsigned long frequency);
|
||||
|
||||
static void imx9_clock(struct sdio_dev_s *dev, enum sdio_clock_e rate);
|
||||
static int imx9_attach(struct sdio_dev_s *dev);
|
||||
@@ -1658,6 +1658,141 @@ static void imx9_widebus(struct sdio_dev_s *dev, bool wide)
|
||||
putreg32(regval, priv->addr + IMX9_USDHC_PROCTL_OFFSET);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: imx9_sdcard_hs_mode
|
||||
*
|
||||
* Description:
|
||||
* Check if the high speed mode is supported or try to switch to that
|
||||
* via CMD6
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - An instance of the SDIO device interface
|
||||
* set - Switch to HS mode
|
||||
*
|
||||
* Returned Value:
|
||||
* If "set" is false, return true if card supports high speed mode. If
|
||||
* the "set" is true, return true if the selected mode for group one is
|
||||
* high-speed (1), that is, card is switched to high-speed.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static bool imx9_sdcard_hs_mode(struct sdio_dev_s *dev, bool set)
|
||||
{
|
||||
#ifdef CONFIG_IMX9_USDHC_DMA
|
||||
struct imx9_dev_s *priv = (struct imx9_dev_s *)dev;
|
||||
uint8_t *resp = priv->rxbuffer;
|
||||
#else
|
||||
uint32_t resp_buf[16]; /* 32-bit aligned 64-byte buffer */
|
||||
uint8_t *resp = (uint8_t *)resp_buf;
|
||||
#endif
|
||||
uint32_t r1;
|
||||
int ret;
|
||||
|
||||
/* Construct CMD6 with full 64 byte response */
|
||||
|
||||
const uint32_t cmd6 = (MMCSD_CMDIDX6 | MMCSD_R1_RESPONSE |
|
||||
MMCSD_RDDATAXFR | USDHC_XFERTYP_RSPTYP_LEN48 |
|
||||
USDHC_XFERTYP_CICEN | USDHC_XFERTYP_CCCEN);
|
||||
|
||||
/* CMD6 argument for switching to high-speed mode:
|
||||
* Bit 31: Mode (1 = switch, 0 = check)
|
||||
* Bits 30:24: Reserved (0)
|
||||
* Bits 23:20: Group 6 (0xf = no change)
|
||||
* Bits 19:16: Group 5 (0xf = no change)
|
||||
* Bits 15:12: Group 4 (0xf = no change)
|
||||
* Bits 11:8: Group 3 (0xf = no change)
|
||||
* Bits 7:4: Group 2 (0xf = no change)
|
||||
* Bits 3:0: Group 1 - Access Mode (0x1 = High Speed)
|
||||
*/
|
||||
|
||||
const uint32_t cmd6_arg = set ? 0x80fffff1u : 0x00fffff1u;
|
||||
uint16_t fg1_support;
|
||||
uint8_t fg1_selected;
|
||||
bool hs_supported = false;
|
||||
sdio_eventset_t wait_ret;
|
||||
|
||||
#ifdef CONFIG_SDIO_BLOCKSETUP
|
||||
imx9_blocksetup(dev, 64, 1);
|
||||
#endif
|
||||
imx9_waitenable(dev, SDIOWAIT_TRANSFERDONE | SDIOWAIT_TIMEOUT |
|
||||
SDIOWAIT_ERROR, 100);
|
||||
|
||||
#ifdef CONFIG_IMX9_USDHC_DMA
|
||||
imx9_dmarecvsetup(dev, resp, 64);
|
||||
#else
|
||||
imx9_recvsetup(dev, resp, 64);
|
||||
#endif
|
||||
|
||||
ret = imx9_sendcmd(dev, cmd6, cmd6_arg);
|
||||
if (ret != OK)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = imx9_waitresponse(dev, cmd6);
|
||||
if (ret != OK)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = imx9_recvshortcrc(dev, cmd6, &r1);
|
||||
if (ret != OK)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
wait_ret = imx9_eventwait(dev);
|
||||
if (wait_ret & (SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Parse the switch status block */
|
||||
|
||||
/* FG1 support (16-bit big-endian at bytes 12..13) */
|
||||
|
||||
fg1_support = ((uint16_t)resp[12] << 8) | resp[13];
|
||||
|
||||
/* FG1 selected result at byte 16 low nibble */
|
||||
|
||||
fg1_selected = resp[16] & 0xf;
|
||||
|
||||
if (set)
|
||||
{
|
||||
/* Selected should indicate function 1 */
|
||||
|
||||
hs_supported = fg1_selected == 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Rely on support bits */
|
||||
|
||||
hs_supported = (fg1_support & (1 << 1)) != 0;
|
||||
}
|
||||
|
||||
if (set)
|
||||
{
|
||||
if (hs_supported)
|
||||
{
|
||||
mcinfo("SD card switched to high-speed mode (fg1_selected=%02x)\n",
|
||||
fg1_selected);
|
||||
}
|
||||
else
|
||||
{
|
||||
mcerr("ERROR: Failed to set SD card high-speed mode"
|
||||
" (fg1_selected=%02x, fg1_support=0x%04x)\n",
|
||||
fg1_selected, fg1_support);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mcinfo("High Speed is%s supported by the card (fg1_support=0x%04x)\n",
|
||||
hs_supported ? "" : " not", fg1_support);
|
||||
}
|
||||
|
||||
return hs_supported;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: imx9_frequency
|
||||
*
|
||||
@@ -1669,18 +1804,17 @@ static void imx9_widebus(struct sdio_dev_s *dev, bool wide)
|
||||
* frequency - The frequency to use
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
* frequency divisor bits for the SYSCTL register
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_IMX9_USDHC_ABSFREQ
|
||||
static void imx9_frequency(struct sdio_dev_s *dev, uint32_t frequency)
|
||||
static uint32_t imx9_frequency(struct sdio_dev_s *dev,
|
||||
unsigned long frequency)
|
||||
{
|
||||
uint32_t sdclkfs;
|
||||
uint32_t prescaled;
|
||||
uint32_t regval;
|
||||
unsigned int prescaler;
|
||||
unsigned int divisor;
|
||||
struct imx9_dev_s *priv = (struct imx9_dev_s *)dev;
|
||||
unsigned long root_freq = priv->root_clock_freq;
|
||||
unsigned prescaler;
|
||||
unsigned divisor;
|
||||
|
||||
/* The SDCLK frequency is determined by
|
||||
* (1) the frequency of the base clock that was selected as the
|
||||
@@ -1691,109 +1825,58 @@ static void imx9_frequency(struct sdio_dev_s *dev, uint32_t frequency)
|
||||
*
|
||||
* The prescaler is available only for the values: 2, 4, 8, 16, 32,
|
||||
* 64, 128, and 256. Pick the smallest value of SDCLKFS that would
|
||||
* result in an in-range frequency. For example, if the base clock
|
||||
* frequency is 96 MHz, and the target frequency is 25 MHz, the
|
||||
* following logic will select prescaler:
|
||||
*
|
||||
* NOTE: USDHC_SYSCTL_SDCLKFS_DIVs are for Single Data Rate mode.
|
||||
* See Reference manual for further details.
|
||||
*
|
||||
* 96MHz / 2 <= 25MHz <= 96MHz / 2 /16 -- YES, prescaler == 2
|
||||
*
|
||||
* If the target frequency is 400 kHz, the following logic will
|
||||
* select prescaler:
|
||||
*
|
||||
* 96MHz / 2 <= 400KHz <= 96MHz / 2 / 16 -- NO
|
||||
* 96MHz / 4 <= 400KHz <= 96MHz / 4 / 16 -- NO
|
||||
* 96MHz / 8 <= 400KHz <= 96MHz / 8 / 16 -- NO
|
||||
* 96MHz / 16 <=400KHz <= 96MHz / 16 / 16 -- YES, prescaler == 16
|
||||
* result in an in-range frequency.
|
||||
*/
|
||||
|
||||
if (/* frequency >= (BOARD_CORECLK_FREQ / 2) && */
|
||||
frequency <= (BOARD_CORECLK_FREQ / 2 / 16))
|
||||
prescaler = 1;
|
||||
do
|
||||
{
|
||||
sdclkfs = USDHC_SYSCTL_SDCLKFS_DIV2;
|
||||
prescaler = 2;
|
||||
prescaler *= 2;
|
||||
divisor = root_freq / (frequency * prescaler);
|
||||
|
||||
/* In case of root_freq is not divisible by frequency * prescaler
|
||||
* we need to increase divisor by one to avoid frequency higher
|
||||
* than requested
|
||||
*/
|
||||
|
||||
if (root_freq % (frequency * prescaler))
|
||||
{
|
||||
divisor++;
|
||||
}
|
||||
}
|
||||
else if (frequency >= (BOARD_CORECLK_FREQ / 4) &&
|
||||
frequency <= (BOARD_CORECLK_FREQ / 4 / 16))
|
||||
while (divisor > 16 && prescaler < 256);
|
||||
|
||||
/* Clamp divisor to minimum of 1 */
|
||||
|
||||
if (divisor < 1)
|
||||
{
|
||||
sdclkfs = USDHC_SYSCTL_SDCLKFS_DIV4;
|
||||
prescaler = 4;
|
||||
divisor = 1;
|
||||
}
|
||||
else if (frequency >= (BOARD_CORECLK_FREQ / 8) &&
|
||||
frequency <= (BOARD_CORECLK_FREQ / 8 / 16))
|
||||
|
||||
/* Clamp divisor to maximum 16. This would result too high frequency.
|
||||
* This only triggers if prescaler reached maximum (256) but frequency
|
||||
* is still too high. At 200MHz root clock this would mean that < 50kHZ
|
||||
* frequency was requested, so this is not a real issue.
|
||||
*/
|
||||
|
||||
if (divisor > 16)
|
||||
{
|
||||
sdclkfs = USDHC_SYSCTL_SDCLKFS_DIV8;
|
||||
prescaler = 8;
|
||||
}
|
||||
else if (frequency >= (BOARD_CORECLK_FREQ / 16) &&
|
||||
frequency <= (BOARD_CORECLK_FREQ / 16 / 16))
|
||||
{
|
||||
sdclkfs = USDHC_SYSCTL_SDCLKFS_DIV16;
|
||||
prescaler = 16;
|
||||
}
|
||||
else if (frequency >= (BOARD_CORECLK_FREQ / 32) &&
|
||||
frequency <= (BOARD_CORECLK_FREQ / 32 / 16))
|
||||
{
|
||||
sdclkfs = USDHC_SYSCTL_SDCLKFS_DIV32;
|
||||
prescaler = 32;
|
||||
}
|
||||
else if (frequency >= (BOARD_CORECLK_FREQ / 64) &&
|
||||
frequency <= (BOARD_CORECLK_FREQ / 64 / 16))
|
||||
{
|
||||
sdclkfs = USDHC_SYSCTL_SDCLKFS_DIV64;
|
||||
prescaler = 64;
|
||||
}
|
||||
else if (frequency >= (BOARD_CORECLK_FREQ / 128) &&
|
||||
frequency <= (BOARD_CORECLK_FREQ / 128 / 16))
|
||||
{
|
||||
sdclkfs = USDHC_SYSCTL_SDCLKFS_DIV128;
|
||||
prescaler = 128;
|
||||
divisor = 16;
|
||||
mcerr("ERROR: Frequency too high. Requested: %lu Hz, Actual: %lu Hz "
|
||||
"(prescaler=%u, divisor=%u)\n", frequency,
|
||||
root_freq / (prescaler * divisor), prescaler, divisor);
|
||||
}
|
||||
else
|
||||
{
|
||||
sdclkfs = USDHC_SYSCTL_SDCLKFS_DIV256;
|
||||
prescaler = 256;
|
||||
mcinfo("Requested: %lu Hz, Actual: %lu Hz "
|
||||
"(prescaler=%u, divisor=%u)\n", frequency,
|
||||
root_freq / (prescaler * divisor), prescaler, divisor);
|
||||
}
|
||||
|
||||
/* The optimal divider can than be calculated. For example, if the base
|
||||
* clock frequency is 96 MHz, the target frequency is 25 MHz, and the
|
||||
* selected prescaler value is 2, then
|
||||
*
|
||||
* prescaled = 96MHz / 2 = 48MHz
|
||||
* divisor = (48MHz + 12.5HMz/ 25MHz = 2
|
||||
*
|
||||
* And the resulting frequency will be 24MHz. Or, for example, if the
|
||||
* target frequency is 400 kHz and the selected prescaler is 16, the
|
||||
* following logic will select prescaler:
|
||||
*
|
||||
* prescaled = 96MHz / 16 = 6MHz
|
||||
* divisor = (6MHz + 200KHz) / 400KHz = 15
|
||||
*
|
||||
* And the resulting frequency will be exactly 400KHz.
|
||||
*/
|
||||
/* Return the new divisor information */
|
||||
|
||||
prescaled = frequency / prescaler;
|
||||
divisor = (prescaled + (frequency >> 1)) / frequency;
|
||||
|
||||
/* Set the new divisor information and enable all clocks in the SYSCTRL
|
||||
* register. TODO: Investigate using the automatically gated clocks to
|
||||
* reduce power consumption.
|
||||
*/
|
||||
|
||||
regval = getreg32(priv->addr + IMX9_USDHC_SYSCTL_OFFSET);
|
||||
regval &= ~(USDHC_SYSCTL_SDCLKFS_MASK | USDHC_SYSCTL_DVS_MASK);
|
||||
regval |= (sdclkfs | USDHC_SYSCTL_DVS_DIV(divisor));
|
||||
regval |= (USDHC_SYSCTL_SDCLKEN | USDHC_SYSCTL_PEREN |
|
||||
USDHC_SYSCTL_HCKEN | USDHC_SYSCTL_IPGEN);
|
||||
|
||||
putreg32(regval, priv->addr + IMX9_USDHC_SYSCTL_OFFSET);
|
||||
|
||||
mcinfo("SYSCTRL: %08x\n",
|
||||
getreg32(priv->addr + IMX9_USDHC_SYSCTL_OFFSET));
|
||||
return USDHC_SYSCTL_SDCLKFS_DIV(prescaler) | USDHC_SYSCTL_DVS_DIV(divisor);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: imx9_clock
|
||||
@@ -1814,12 +1897,13 @@ static void imx9_clock(struct sdio_dev_s *dev, enum sdio_clock_e rate)
|
||||
{
|
||||
struct imx9_dev_s *priv = (struct imx9_dev_s *)dev;
|
||||
uint32_t regval;
|
||||
unsigned speed;
|
||||
|
||||
/* Clear the old prescaler and divisor values so that new ones can be
|
||||
* ORed in.
|
||||
*/
|
||||
|
||||
regval = getreg32(priv->addr + IMX9_USDHC_SYSCTL_OFFSET);
|
||||
regval = getreg32(priv->addr + IMX9_USDHC_SYSCTL_OFFSET);
|
||||
regval &= ~(USDHC_SYSCTL_SDCLKFS_MASK | USDHC_SYSCTL_DVS_MASK);
|
||||
|
||||
/* Select the new prescaler and divisor values based on the requested
|
||||
@@ -1830,13 +1914,12 @@ static void imx9_clock(struct sdio_dev_s *dev, enum sdio_clock_e rate)
|
||||
switch (rate)
|
||||
{
|
||||
default:
|
||||
case CLOCK_SDIO_DISABLED: /* Clock is disabled */
|
||||
case CLOCK_SDIO_DISABLED:
|
||||
{
|
||||
/* Clear the prescaler and divisor settings */
|
||||
/* Clock is disabled */
|
||||
|
||||
putreg32(regval, priv->addr + IMX9_USDHC_SYSCTL_OFFSET);
|
||||
mcinfo("DISABLED, SYSCTRL: %08" PRIx32 "\n",
|
||||
getreg32(priv->addr + IMX9_USDHC_SYSCTL_OFFSET)); return;
|
||||
mcinfo("DISABLED, SYSCTRL: %08" PRIx32 "\n", regval);
|
||||
speed = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1845,14 +1928,13 @@ static void imx9_clock(struct sdio_dev_s *dev, enum sdio_clock_e rate)
|
||||
/* Initial ID mode clocking (<400KHz) */
|
||||
|
||||
mcinfo("IDMODE\n");
|
||||
speed = BOARD_USDHC_IDMODE_SPEED;
|
||||
|
||||
/* Put out an additional 80 clocks in case this is a power-up
|
||||
* sequence.
|
||||
*/
|
||||
|
||||
regval |= (BOARD_USDHC_IDMODE_PRESCALER |
|
||||
BOARD_USDHC_IDMODE_DIVISOR |
|
||||
USDHC_SYSCTL_INITA);
|
||||
regval |= USDHC_SYSCTL_INITA;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1861,8 +1943,7 @@ static void imx9_clock(struct sdio_dev_s *dev, enum sdio_clock_e rate)
|
||||
/* MMC normal operation clocking */
|
||||
|
||||
mcinfo("MMCTRANSFER\n");
|
||||
regval |= (BOARD_USDHC_MMCMODE_PRESCALER |
|
||||
BOARD_USDHC_MMCMODE_DIVISOR);
|
||||
speed = BOARD_USDHC_MMCMODE_SPEED;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1871,8 +1952,7 @@ static void imx9_clock(struct sdio_dev_s *dev, enum sdio_clock_e rate)
|
||||
/* SD normal operation clocking (narrow 1-bit mode) */
|
||||
|
||||
mcinfo("1BITTRANSFER\n");
|
||||
regval |= (BOARD_USDHC_SD1MODE_PRESCALER |
|
||||
BOARD_USDHC_SD1MODE_DIVISOR);
|
||||
speed = BOARD_USDHC_SD1MODE_SPEED;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1880,13 +1960,34 @@ static void imx9_clock(struct sdio_dev_s *dev, enum sdio_clock_e rate)
|
||||
{
|
||||
/* SD normal operation clocking (wide 4-bit mode) */
|
||||
|
||||
mcinfo("4BITTRANSFER\n");
|
||||
regval |= (BOARD_USDHC_SD4MODE_PRESCALER |
|
||||
BOARD_USDHC_SD4MODE_DIVISOR);
|
||||
mcinfo("SDTRANSFER\n");
|
||||
speed = BOARD_USDHC_SDMODE_SPEED;
|
||||
|
||||
if (speed > 25000000)
|
||||
{
|
||||
/* Switch SD card to high-speed mode if configured for higher
|
||||
* than 25MHz
|
||||
*/
|
||||
|
||||
if (imx9_sdcard_hs_mode(dev, false))
|
||||
{
|
||||
if (!imx9_sdcard_hs_mode(dev, true))
|
||||
{
|
||||
/* HS mode setting failed, fall back to 25 MHz */
|
||||
|
||||
speed = 25000000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (speed > 0)
|
||||
{
|
||||
regval |= imx9_frequency(dev, speed);
|
||||
}
|
||||
|
||||
putreg32(regval, priv->addr + IMX9_USDHC_SYSCTL_OFFSET);
|
||||
|
||||
/* Wait for clock to become stable */
|
||||
@@ -3352,8 +3453,8 @@ struct sdio_dev_s *imx9_usdhc_initialize(int slotno)
|
||||
|
||||
/* Enable clocks */
|
||||
|
||||
imx9_ccm_configure_root_clock(CCM_CR_USDHC2, SYS_PLL1PFD1, 4);
|
||||
|
||||
imx9_ccm_configure_root_clock(CCM_CR_USDHC1, SYS_PLL1PFD1, 4);
|
||||
imx9_get_rootclock(CCM_CR_USDHC1, &priv->root_clock_freq);
|
||||
imx9_ccm_gate_on(CCM_LPCG_USDHC1, true);
|
||||
|
||||
break;
|
||||
@@ -3388,7 +3489,7 @@ struct sdio_dev_s *imx9_usdhc_initialize(int slotno)
|
||||
/* Enable clocks */
|
||||
|
||||
imx9_ccm_configure_root_clock(CCM_CR_USDHC2, SYS_PLL1PFD1, 4);
|
||||
|
||||
imx9_get_rootclock(CCM_CR_USDHC2, &priv->root_clock_freq);
|
||||
imx9_ccm_gate_on(CCM_LPCG_USDHC2, true);
|
||||
|
||||
mcinfo("Enabled clocks\n");
|
||||
|
||||
@@ -105,23 +105,21 @@
|
||||
#define PIN_USDHC2_CD_MUX IOMUX_CFG(IOMUXC_PAD_SD2_DATA3_USDHC2_DATA3, IOMUXC_PAD_DSE_X4 | IOMUXC_PAD_FSEL_FAST, 0)
|
||||
#define PIN_USDHC2_VSELECT_MUX IOMUX_CFG(IOMUXC_PAD_SD2_VSELECT_USDHC2_VSELECT, IOMUXC_PAD_DSE_X5 | IOMUXC_PAD_FSEL_SFAST | IOMUXC_PAD_PD_ON, 0)
|
||||
|
||||
/* 390 KHz for initial inquiry stuff */
|
||||
/* 400 KHz for initial inquiry stuff */
|
||||
|
||||
#define BOARD_USDHC_IDMODE_PRESCALER USDHC_SYSCTL_SDCLKFS_DIV256
|
||||
#define BOARD_USDHC_IDMODE_DIVISOR USDHC_SYSCTL_DVS_DIV(2)
|
||||
#define BOARD_USDHC_IDMODE_SPEED 400000
|
||||
|
||||
/* 25MHz for MMC mode */
|
||||
|
||||
#define BOARD_USDHC_MMCMODE_SPEED 25000000
|
||||
|
||||
/* 25MHz for 1-bit wide bus */
|
||||
|
||||
#define BOARD_USDHC_MMCMODE_PRESCALER USDHC_SYSCTL_SDCLKFS_DIV8
|
||||
#define BOARD_USDHC_MMCMODE_DIVISOR USDHC_SYSCTL_DVS_DIV(1)
|
||||
#define BOARD_USDHC_SD1MODE_SPEED 25000000
|
||||
|
||||
#define BOARD_USDHC_SD1MODE_PRESCALER USDHC_SYSCTL_SDCLKFS_DIV8
|
||||
#define BOARD_USDHC_SD1MODE_DIVISOR USDHC_SYSCTL_DVS_DIV(1)
|
||||
/* 50MHz for SD card mode */
|
||||
|
||||
/* 50MHz for 4-bit wide bus */
|
||||
|
||||
#define BOARD_USDHC_SD4MODE_PRESCALER USDHC_SYSCTL_SDCLKFS_DIV4
|
||||
#define BOARD_USDHC_SD4MODE_DIVISOR USDHC_SYSCTL_DVS_DIV(1)
|
||||
#define BOARD_USDHC_SDMODE_SPEED 50000000
|
||||
|
||||
/* Set the PLL clocks as follows:
|
||||
*
|
||||
|
||||
@@ -105,23 +105,21 @@
|
||||
#define PIN_USDHC2_CD_MUX IOMUX_CFG(IOMUXC_PAD_SD2_DATA3_USDHC2_DATA3, IOMUXC_PAD_DSE_X4 | IOMUXC_PAD_FSEL_FAST, 0)
|
||||
#define PIN_USDHC2_VSELECT_MUX IOMUX_CFG(IOMUXC_PAD_SD2_VSELECT_USDHC2_VSELECT, IOMUXC_PAD_DSE_X5 | IOMUXC_PAD_FSEL_SFAST | IOMUXC_PAD_PD_ON, 0)
|
||||
|
||||
/* 390 KHz for initial inquiry stuff */
|
||||
/* 400 KHz for initial inquiry stuff */
|
||||
|
||||
#define BOARD_USDHC_IDMODE_PRESCALER USDHC_SYSCTL_SDCLKFS_DIV256
|
||||
#define BOARD_USDHC_IDMODE_DIVISOR USDHC_SYSCTL_DVS_DIV(2)
|
||||
#define BOARD_USDHC_IDMODE_SPEED 400000
|
||||
|
||||
/* 25MHz for MMC mode */
|
||||
|
||||
#define BOARD_USDHC_MMCMODE_SPEED 25000000
|
||||
|
||||
/* 25MHz for 1-bit wide bus */
|
||||
|
||||
#define BOARD_USDHC_MMCMODE_PRESCALER USDHC_SYSCTL_SDCLKFS_DIV8
|
||||
#define BOARD_USDHC_MMCMODE_DIVISOR USDHC_SYSCTL_DVS_DIV(1)
|
||||
#define BOARD_USDHC_SD1MODE_SPEED 25000000
|
||||
|
||||
#define BOARD_USDHC_SD1MODE_PRESCALER USDHC_SYSCTL_SDCLKFS_DIV8
|
||||
#define BOARD_USDHC_SD1MODE_DIVISOR USDHC_SYSCTL_DVS_DIV(1)
|
||||
/* 50MHz for SD card mode */
|
||||
|
||||
/* 50MHz for 4-bit wide bus */
|
||||
|
||||
#define BOARD_USDHC_SD4MODE_PRESCALER USDHC_SYSCTL_SDCLKFS_DIV4
|
||||
#define BOARD_USDHC_SD4MODE_DIVISOR USDHC_SYSCTL_DVS_DIV(1)
|
||||
#define BOARD_USDHC_SDMODE_SPEED 50000000
|
||||
|
||||
/* Set the PLL clocks as follows:
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user