arch/arm/src/lpc54xx and configs/lpcxpresso-lpc54628: Correct some SD/MMC clock divider logic.

This commit is contained in:
Gregory Nutt 2017-12-19 14:05:36 -06:00
parent 93b28017ab
commit 321a7a64af
3 changed files with 51 additions and 28 deletions

View File

@ -154,10 +154,16 @@
#define SDMMC_PWREN (1 << 0) /* Bit 0: Power on/off switch */
/* Bits 1-31: Reserved */
/* Clock divider register CLKDIV */
/* Clock divider register CLKDIV
*
* Clock division is 2*n. For example, value of 0 means divide by 2 * 0 = 0 (no division,
* bypass), value of 1 means divide by 2 * 1 = 2, value of 255 means divide by 2 * 255 = 510,
* and so on.
*/
#define SDMMC_CLKDIV0_SHIFT (0) /* Bits 0-7: Clock divider 0 value */
#define SDMMC_CLKDIV0_MASK (255 << SDMMC_CLKDIV0_SHIFT)
# define SDMMC_CLKDIV0_MASK(n) ((((n) + 1) >> 1) << SDMMC_CLKDIV0_SHIFT)
/* Bits 8-31: Reserved */
/* Clock enable register CLKENA */

View File

@ -115,13 +115,6 @@
# error "Callback support requires CONFIG_SCHED_WORKQUEUE"
#endif
/* Clock Division */
#define LPC54_CLKDIV_INIT 165 /* Divide by 165 = 400KHz */
#define SDCARD_CLOCK_MMCXFR 2 /* SDCARD_MMCXFR_CLKDIV */
#define SDCARD_CLOCK_SDWIDEXFR 2 /* SDCARD_SDXFR_CLKDIV */
#define SDCARD_CLOCK_SDXFR 2 /* SDCARD_SDXFR_CLKDIV */
/* Timing */
#define SDCARD_CMDTIMEOUT (10000)
@ -536,7 +529,7 @@ static inline void lpc54_setclock(uint32_t clkdiv)
/* Set Divider0 to desired value */
lpc54_putreg(clkdiv & SDMMC_CLKDIV0_MASK, LPC54_SDMMC_CLKDIV);
lpc54_putreg(clkdiv, LPC54_SDMMC_CLKDIV);
/* Inform CIU */
@ -1145,7 +1138,7 @@ static void lpc54_reset(FAR struct sdio_dev_s *dev)
regval = SDMMC_BMOD_DE;
regval |= SDMMC_BMOD_PBL_4XFRS;
regval |= ((4) << SDMMC_BMOD_DSL_SHIFT) & SDMMC_BMOD_DSL_MASK;
regval |= ((4) << SDMMC_BMOD_DSL_SHIFT);
lpc54_putreg(regval, LPC54_SDMMC_BMOD);
/* Disable clock to CIU (needs latch) */
@ -1260,7 +1253,7 @@ static void lpc54_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate)
default:
case CLOCK_SDIO_DISABLED:
clkdiv = LPC54_CLKDIV_INIT;
clkdiv = SDMMC_CLKDIV0(BOARD_CLKDIV_INIT);
ctype = SDCARD_BUS_D1;
enabled = false;
return;
@ -1269,7 +1262,7 @@ static void lpc54_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate)
/* Enable in initial ID mode clocking (<400KHz) */
case CLOCK_IDMODE:
clkdiv = LPC54_CLKDIV_INIT;
clkdiv = SDMMC_CLKDIV0(BOARD_CLKDIV_INIT);
ctype = SDCARD_BUS_D1;
enabled = true;
break;
@ -1277,7 +1270,7 @@ static void lpc54_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate)
/* Enable in MMC normal operation clocking */
case CLOCK_MMC_TRANSFER:
clkdiv = SDCARD_CLOCK_MMCXFR;
clkdiv = SDMMC_CLKDIV0(BOARD_CLKDIV_MMCXFR);
ctype = SDCARD_BUS_D1;
enabled = true;
break;
@ -1286,7 +1279,7 @@ static void lpc54_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate)
case CLOCK_SD_TRANSFER_4BIT:
#ifndef CONFIG_LPC54_SDMMC_WIDTH_D1_ONLY
clkdiv = SDCARD_CLOCK_SDWIDEXFR;
clkdiv = SDMMC_CLKDIV0(BOARD_CLKDIV_SDWIDEXFR);
ctype = SDCARD_BUS_D4;
enabled = true;
break;
@ -1295,7 +1288,7 @@ static void lpc54_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate)
/* SD normal operation clocking (narrow 1-bit mode) */
case CLOCK_SD_TRANSFER_1BIT:
clkdiv = SDCARD_CLOCK_SDXFR;
clkdiv = SDMMC_CLKDIV0(BOARD_CLKDIV_SDXFR);
ctype = SDCARD_BUS_D1;
enabled = true;
break;

View File

@ -193,10 +193,11 @@
#endif
#define BOARD_EMC_FREQUENCY (BOARD_CPU_FREQUENCY / BOARD_EMC_CLKDIV)
/* SD/MMC or SDIO interface
/* SD/MMC or SDIO interface/
/* SD/MMC function clock
*
* NOTE: The SDIO function clock to the interface can be up to 50 MHZ.
* Example: BOARD_MAIN_CLK=220MHz, CLKDIV=5, Fsdmmc=44MHz.
* Example: BOARD_MAIN_CLK=220MHz, CLKDIV=5, Finput=44MHz.
*/
#define BOARD_SDMMC_MAXFREQ 50000000
@ -206,6 +207,29 @@
#define BOARD_SDMMC_CLKDIV BOARD_SDMMC_CEIL(BOARD_MAIN_CLK, BOARD_SDMMC_MAXFREQ)
#define BOARD_SDMMC_FREQUENCY (BOARD_MAIN_CLK / BOARD_SDMMC_CLKDIV)
/* Mode-dependent function clock division
*
* Example: BOARD_SDMMC_FREQUENCY=44MHz
* BOARD_CLKDIV_INIT=110, Fsdmmc=400KHz (400KHz max)
* BOARD_CLKDIV_MMCXFR=4[3], Fsdmmc=11Mhz (20MHz max) See NOTE:
* BOARD_CLKDIV_SDWIDEXFR=2, Fsdmmc=22MHz (25MHz max)
* BOARD_CLKDIV_SDXFR=2, Fsdmmc=22MHz (25MHz max)
*
* NOTE: *lock division is 2*n. For example, value of 0 means divide by
* 2 * 0 = 0 (no division, bypass), value of 1 means divide by 2 * 1 = 2, value
* of 255 means divide by 2 * 255 = 510, and so on.
*
* SD/MMC logic will write the value ((clkdiv + 1) >> 1) as the divisor. So an
* odd value calculated below will be moved up to next higher divider value. So
* the value 3 will cause 2 to be written as the divider value and the effective
* divider will be 4.
*/
#define BOARD_CLKDIV_INIT BOARD_SDMMC_CEIL(BOARD_SDMMC_FREQUENCY, 400000)
#define BOARD_CLKDIV_MMCXFR BOARD_SDMMC_CEIL(BOARD_SDMMC_FREQUENCY, 20000000)
#define BOARD_CLKDIV_SDWIDEXFR BOARD_SDMMC_CEIL(BOARD_SDMMC_FREQUENCY, 25000000)
#define BOARD_CLKDIV_SDXFR BOARD_SDMMC_CEIL(BOARD_SDMMC_FREQUENCY, 25000000)
/* LED definitions *********************************************************/
/* The LPCXpress-LPC54628 has three user LEDs: D9, D11, and D12. These
* LEDs are for application use. They are illuminated when the driving