From 4d6bf464802fa0b7bba703a24cd47c8a6772b2d2 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 22 Dec 2017 11:59:45 -0600 Subject: [PATCH] lpc43xx and lpc54xx: No handling the wide bus MMC/SD interface correctly. --- arch/arm/src/lpc43xx/chip/lpc43_sdmmc.h | 1 + arch/arm/src/lpc43xx/lpc43_sdmmc.c | 83 +++++++++++++------------ arch/arm/src/lpc54xx/chip/lpc54_sdmmc.h | 1 + arch/arm/src/lpc54xx/lpc54_sdmmc.c | 83 +++++++++++++------------ 4 files changed, 86 insertions(+), 82 deletions(-) diff --git a/arch/arm/src/lpc43xx/chip/lpc43_sdmmc.h b/arch/arm/src/lpc43xx/chip/lpc43_sdmmc.h index 3ac448a92d..66ad82776b 100644 --- a/arch/arm/src/lpc43xx/chip/lpc43_sdmmc.h +++ b/arch/arm/src/lpc43xx/chip/lpc43_sdmmc.h @@ -196,6 +196,7 @@ /* Card type register CTYPE */ +#define SDMMC_CTYPE_WIDTH1 (0) /* 1-bit mode */ #define SDMMC_CTYPE_WIDTH4 (1 << 0) /* Bit 0: 4-bit mode */ /* Bits 1-15: Reserved */ #define SDMMC_CTYPE_WIDTH8 (1 << 16) /* Bit 16: 8-bit mode */ diff --git a/arch/arm/src/lpc43xx/lpc43_sdmmc.c b/arch/arm/src/lpc43xx/lpc43_sdmmc.c index ee528fb4c0..ca09fc23a5 100644 --- a/arch/arm/src/lpc43xx/lpc43_sdmmc.c +++ b/arch/arm/src/lpc43xx/lpc43_sdmmc.c @@ -242,7 +242,7 @@ struct lpc43_dev_s /* DMA data transfer support */ - bool widebus; /* Required for DMA support */ + bool widebus; /* Wide bus required for DMA support */ #ifdef CONFIG_LPC43_SDMMC_DMA bool dmamode; /* true: DMA mode transfer */ #endif @@ -267,7 +267,6 @@ static void lpc43_checksetup(void); static void lpc43_takesem(struct lpc43_dev_s *priv); #define lpc43_givesem(priv) (sem_post(&priv->waitsem)) static inline void lpc43_setclock(uint32_t clkdiv); -static inline void lpc43_settype(uint32_t ctype); static inline void lpc43_sdcard_clock(bool enable); static int lpc43_ciu_sendcmd(uint32_t cmd, uint32_t arg); static void lpc43_configwaitints(struct lpc43_dev_s *priv, uint32_t waitmask, @@ -571,25 +570,6 @@ static inline void lpc43_setclock(uint32_t clkdiv) lpc43_ciu_sendcmd(SDMMC_CMD_UPDCLOCK | SDMMC_CMD_WAITPREV, 0); } -/**************************************************************************** - * Name: lpc43_settype - * - * Description: Define the Bus Size of SDCard (1, 4 or 8-bit) - * - * Input Parameters: - * ctype - A new CTYPE (Card Type Register) value - * - * Returned Value: - * None - * - ****************************************************************************/ - -static inline void lpc43_settype(uint32_t ctype) -{ - mcinfo("cteype=%08lx\n", (unsigned long)ctype); - lpc43_putreg(ctype, LPC43_SDMMC_CTYPE); -} - /**************************************************************************** * Name: lpc43_sdcard_clock * @@ -1251,8 +1231,10 @@ static void lpc43_reset(FAR struct sdio_dev_s *dev) lpc43_putreg(SDMMC_CTRL_CNTLRRESET | SDMMC_CTRL_FIFORESET | SDMMC_CTRL_DMARESET, LPC43_SDMMC_CTRL); - while ((regval = lpc43_getreg(LPC43_SDMMC_CTRL)) & - (SDMMC_CTRL_CNTLRRESET | SDMMC_CTRL_FIFORESET | SDMMC_CTRL_DMARESET)); + while ((lpc43_getreg(LPC43_SDMMC_CTRL) & + (SDMMC_CTRL_CNTLRRESET | SDMMC_CTRL_FIFORESET | SDMMC_CTRL_DMARESET)) != 0) + { + } /* Reset data */ @@ -1273,21 +1255,20 @@ static void lpc43_reset(FAR struct sdio_dev_s *dev) /* DMA data transfer support */ - priv->widebus = true; /* Required for DMA support */ + priv->widebus = false; /* Wide bus required for DMA support */ priv->cdstatus = 0; /* Card status is unknown */ - regval = 0; - #ifdef CONFIG_LPC43_SDMMC_DMA priv->dmamode = false; /* true: DMA mode transfer */ - - /* Use the Internal DMA */ - - regval = SDMMC_CTRL_INTDMA; #endif + /* Select 1-bit wide bus */ + + lpc43_putreg(SDMMC_CTYPE_WIDTH1, LPC43_SDMMC_CTYPE); + /* Enable interrupts */ + regval = lpc43_getreg(LPC43_SDMMC_CTRL); regval |= SDMMC_CTRL_INTENABLE; lpc43_putreg(regval, LPC43_SDMMC_CTRL); @@ -1400,7 +1381,10 @@ static void lpc43_widebus(FAR struct sdio_dev_s *dev, bool wide) mcinfo("wide=%d\n", wide); - priv->widebus = wide; + /* Select 4-bit wide bus */ + + priv->widebus = true; + lpc43_putreg(SDMMC_CTYPE_WIDTH4, LPC43_SDMMC_CTYPE); } /**************************************************************************** @@ -1421,7 +1405,6 @@ static void lpc43_widebus(FAR struct sdio_dev_s *dev, bool wide) static void lpc43_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate) { uint8_t clkdiv; - uint8_t ctype; bool enabled = false; switch (rate) @@ -1431,7 +1414,6 @@ static void lpc43_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate) default: case CLOCK_SDIO_DISABLED: clkdiv = SDMMC_CLKDIV0(BOARD_CLKDIV_INIT); - ctype = SDCARD_BUS_D1; enabled = false; return; break; @@ -1440,7 +1422,6 @@ static void lpc43_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate) case CLOCK_IDMODE: clkdiv = SDMMC_CLKDIV0(BOARD_CLKDIV_INIT); - ctype = SDCARD_BUS_D1; enabled = true; break; @@ -1448,7 +1429,6 @@ static void lpc43_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate) case CLOCK_MMC_TRANSFER: clkdiv = SDMMC_CLKDIV0(BOARD_CLKDIV_MMCXFR); - ctype = SDCARD_BUS_D1; enabled = true; break; @@ -1457,7 +1437,6 @@ static void lpc43_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate) case CLOCK_SD_TRANSFER_4BIT: #ifndef CONFIG_SDIO_WIDTH_D1_ONLY clkdiv = SDMMC_CLKDIV0(BOARD_CLKDIV_SDWIDEXFR); - ctype = SDCARD_BUS_D4; enabled = true; break; #endif @@ -1466,15 +1445,10 @@ static void lpc43_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate) case CLOCK_SD_TRANSFER_1BIT: clkdiv = SDMMC_CLKDIV0(BOARD_CLKDIV_SDXFR); - ctype = SDCARD_BUS_D1; enabled = true; break; } - /* Setup the type of card bus wide */ - - lpc43_settype(ctype); - /* Set the new clock frequency division */ lpc43_setclock(clkdiv); @@ -1646,6 +1620,9 @@ static int lpc43_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer, struct lpc43_dev_s *priv = (struct lpc43_dev_s *)dev; uint32_t blocksize; uint32_t bytecnt; +#ifdef CONFIG_LPC43_SDMMC_DMA + uint32_t regval; +#endif mcinfo("nbytes=%ld\n", (long) nbytes); @@ -1684,10 +1661,16 @@ static int lpc43_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer, lpc43_putreg(SDMMC_FIFOTH_RXWMARK(1), LPC43_SDMMC_FIFOTH); +#ifdef CONFIG_LPC43_SDMMC_DMA /* Make sure that internal DMA is disabled */ lpc43_putreg(0, LPC43_SDMMC_BMOD); + regval = lpc43_getreg(LPC43_SDMMC_CTRL); + regval &= ~SDMMC_CTRL_INTDMA + lpc43_putreg(regval, LPC43_SDMMC_CTRL); +#endif + /* Configure the transfer interrupts */ lpc43_configxfrints(priv, SDCARD_RECV_MASK); @@ -1717,6 +1700,9 @@ static int lpc43_sendsetup(FAR struct sdio_dev_s *dev, FAR const uint8_t *buffer size_t nbytes) { struct lpc43_dev_s *priv = (struct lpc43_dev_s *)dev; +#ifdef CONFIG_LPC43_SDMMC_DMA + uint32_t regval; +#endif mcinfo("nbytes=%ld\n", (long)nbytes); @@ -1739,10 +1725,16 @@ static int lpc43_sendsetup(FAR struct sdio_dev_s *dev, FAR const uint8_t *buffer lpc43_putreg(SDMMC_FIFOTH_TXWMARK(LPC43_TXFIFO_DEPTH / 2), LPC43_SDMMC_FIFOTH); +#ifdef CONFIG_LPC43_SDMMC_DMA /* Make sure that internal DMA is disabled */ lpc43_putreg(0, LPC43_SDMMC_BMOD); + regval = lpc43_getreg(LPC43_SDMMC_CTRL); + regval &= ~SDMMC_CTRL_INTDMA + lpc43_putreg(regval, LPC43_SDMMC_CTRL); +#endif + /* Configure the transfer interrupts */ lpc43_configxfrints(priv, SDCARD_SEND_MASK); @@ -2463,6 +2455,10 @@ static int lpc43_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer, regval = SDMMC_BMOD_DE | SDMMC_BMOD_PBL_4XFRS | SDMMC_BMOD_DSL(4); lpc43_putreg(regval, LPC43_SDMMC_BMOD); + regval = lpc43_getreg(LPC43_SDMMC_CTRL); + regval |= SDMMC_CTRL_INTDMA + lpc43_putreg(regval, LPC43_SDMMC_CTRL); + /* Setup DMA error interrupts */ lpc43_configxfrints(priv, SDCARD_DMARECV_MASK); @@ -2531,6 +2527,7 @@ static int lpc43_dmasendsetup(FAR struct sdio_dev_s *dev, regval = lpc43_getreg(LPC43_SDMMC_CTRL); regval |= SDMMC_CTRL_FIFORESET | SDMMC_CTRL_DMARESET; lpc43_putreg(regval, LPC43_SDMMC_CTRL); + while (lpc43_getreg(LPC43_SDMMC_CTRL) & SDMMC_CTRL_DMARESET) { } @@ -2557,6 +2554,10 @@ static int lpc43_dmasendsetup(FAR struct sdio_dev_s *dev, regval = SDMMC_BMOD_DE | SDMMC_BMOD_PBL_4XFRS | SDMMC_BMOD_DSL(4); lpc43_putreg(regval, LPC43_SDMMC_BMOD); + regval = lpc43_getreg(LPC43_SDMMC_CTRL); + regval |= SDMMC_CTRL_INTDMA + lpc43_putreg(regval, LPC43_SDMMC_CTRL); + /* Setup DMA error interrupts */ lpc43_configxfrints(priv, SDCARD_DMASEND_MASK); diff --git a/arch/arm/src/lpc54xx/chip/lpc54_sdmmc.h b/arch/arm/src/lpc54xx/chip/lpc54_sdmmc.h index 12c8356854..8a2115adb6 100644 --- a/arch/arm/src/lpc54xx/chip/lpc54_sdmmc.h +++ b/arch/arm/src/lpc54xx/chip/lpc54_sdmmc.h @@ -186,6 +186,7 @@ /* Card type register CTYPE */ +#define SDMMC_CTYPE_WIDTH1 (0) /* 1-bit mode */ #define SDMMC_CTYPE_WIDTH4 (1 << 0) /* Bit 0: 4-bit mode */ /* Bits 1-15: Reserved */ #define SDMMC_CTYPE_WIDTH8 (1 << 16) /* Bit 16: 8-bit mode */ diff --git a/arch/arm/src/lpc54xx/lpc54_sdmmc.c b/arch/arm/src/lpc54xx/lpc54_sdmmc.c index 27f271e3c7..48134004a7 100644 --- a/arch/arm/src/lpc54xx/lpc54_sdmmc.c +++ b/arch/arm/src/lpc54xx/lpc54_sdmmc.c @@ -247,7 +247,7 @@ struct lpc54_dev_s /* DMA data transfer support */ - bool widebus; /* Required for DMA support */ + bool widebus; /* Wide bus required for DMA support */ #ifdef CONFIG_LPC54_SDMMC_DMA bool dmamode; /* true: DMA mode transfer */ #endif @@ -272,7 +272,6 @@ static void lpc54_checksetup(void); static void lpc54_takesem(struct lpc54_dev_s *priv); #define lpc54_givesem(priv) (sem_post(&priv->waitsem)) static inline void lpc54_setclock(uint32_t clkdiv); -static inline void lpc54_settype(uint32_t ctype); static inline void lpc54_sdcard_clock(bool enable); static int lpc54_ciu_sendcmd(uint32_t cmd, uint32_t arg); static void lpc54_configwaitints(struct lpc54_dev_s *priv, uint32_t waitmask, @@ -572,25 +571,6 @@ static inline void lpc54_setclock(uint32_t clkdiv) lpc54_ciu_sendcmd(SDMMC_CMD_UPDCLOCK | SDMMC_CMD_WAITPREV, 0); } -/**************************************************************************** - * Name: lpc54_settype - * - * Description: Define the Bus Size of SDCard (1, 4 or 8-bit) - * - * Input Parameters: - * ctype - A new CTYPE (Card Type Register) value - * - * Returned Value: - * None - * - ****************************************************************************/ - -static inline void lpc54_settype(uint32_t ctype) -{ - mcinfo("cteype=%08lx\n", (unsigned long)ctype); - lpc54_putreg(ctype, LPC54_SDMMC_CTYPE); -} - /**************************************************************************** * Name: lpc54_sdcard_clock * @@ -1252,8 +1232,10 @@ static void lpc54_reset(FAR struct sdio_dev_s *dev) lpc54_putreg(SDMMC_CTRL_CNTLRRESET | SDMMC_CTRL_FIFORESET | SDMMC_CTRL_DMARESET, LPC54_SDMMC_CTRL); - while ((regval = lpc54_getreg(LPC54_SDMMC_CTRL)) & - (SDMMC_CTRL_CNTLRRESET | SDMMC_CTRL_FIFORESET | SDMMC_CTRL_DMARESET)); + while ((lpc54_getreg(LPC54_SDMMC_CTRL) & + (SDMMC_CTRL_CNTLRRESET | SDMMC_CTRL_FIFORESET | SDMMC_CTRL_DMARESET)) != 0) + { + } /* Reset data */ @@ -1274,21 +1256,20 @@ static void lpc54_reset(FAR struct sdio_dev_s *dev) /* DMA data transfer support */ - priv->widebus = true; /* Required for DMA support */ + priv->widebus = false; /* Wide bus required for DMA support */ priv->cdstatus = 0; /* Card status is unknown */ - regval = 0; - #ifdef CONFIG_LPC54_SDMMC_DMA priv->dmamode = false; /* true: DMA mode transfer */ - - /* Use the Internal DMA */ - - regval = SDMMC_CTRL_INTDMA; #endif + /* Select 1-bit wide bus */ + + lpc54_putreg(SDMMC_CTYPE_WIDTH1, LPC54_SDMMC_CTYPE); + /* Enable interrupts */ + regval = lpc54_getreg(LPC54_SDMMC_CTRL); regval |= SDMMC_CTRL_INTENABLE; lpc54_putreg(regval, LPC54_SDMMC_CTRL); @@ -1401,7 +1382,10 @@ static void lpc54_widebus(FAR struct sdio_dev_s *dev, bool wide) mcinfo("wide=%d\n", wide); - priv->widebus = wide; + /* Select 4-bit wide bus */ + + priv->widebus = true; + lpc54_putreg(SDMMC_CTYPE_WIDTH4, LPC54_SDMMC_CTYPE); } /**************************************************************************** @@ -1422,7 +1406,6 @@ static void lpc54_widebus(FAR struct sdio_dev_s *dev, bool wide) static void lpc54_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate) { uint8_t clkdiv; - uint8_t ctype; bool enabled = false; switch (rate) @@ -1432,7 +1415,6 @@ static void lpc54_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate) default: case CLOCK_SDIO_DISABLED: clkdiv = SDMMC_CLKDIV0(BOARD_CLKDIV_INIT); - ctype = SDCARD_BUS_D1; enabled = false; return; break; @@ -1441,7 +1423,6 @@ static void lpc54_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate) case CLOCK_IDMODE: clkdiv = SDMMC_CLKDIV0(BOARD_CLKDIV_INIT); - ctype = SDCARD_BUS_D1; enabled = true; break; @@ -1449,7 +1430,6 @@ static void lpc54_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate) case CLOCK_MMC_TRANSFER: clkdiv = SDMMC_CLKDIV0(BOARD_CLKDIV_MMCXFR); - ctype = SDCARD_BUS_D1; enabled = true; break; @@ -1458,7 +1438,6 @@ static void lpc54_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate) case CLOCK_SD_TRANSFER_4BIT: #ifndef CONFIG_SDIO_WIDTH_D1_ONLY clkdiv = SDMMC_CLKDIV0(BOARD_CLKDIV_SDWIDEXFR); - ctype = SDCARD_BUS_D4; enabled = true; break; #endif @@ -1467,15 +1446,10 @@ static void lpc54_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate) case CLOCK_SD_TRANSFER_1BIT: clkdiv = SDMMC_CLKDIV0(BOARD_CLKDIV_SDXFR); - ctype = SDCARD_BUS_D1; enabled = true; break; } - /* Setup the type of card bus wide */ - - lpc54_settype(ctype); - /* Set the new clock frequency division */ lpc54_setclock(clkdiv); @@ -1647,6 +1621,9 @@ static int lpc54_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer, struct lpc54_dev_s *priv = (struct lpc54_dev_s *)dev; uint32_t blocksize; uint32_t bytecnt; +#ifdef CONFIG_LPC54_SDMMC_DMA + uint32_t regval; +#endif mcinfo("nbytes=%ld\n", (long) nbytes); @@ -1685,10 +1662,16 @@ static int lpc54_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer, lpc54_putreg(SDMMC_FIFOTH_RXWMARK(1), LPC54_SDMMC_FIFOTH); +#ifdef CONFIG_LPC54_SDMMC_DMA /* Make sure that internal DMA is disabled */ lpc54_putreg(0, LPC54_SDMMC_BMOD); + regval = lpc54_getreg(LPC54_SDMMC_CTRL); + regval &= ~SDMMC_CTRL_INTDMA + lpc54_putreg(regval, LPC54_SDMMC_CTRL); +#endif + /* Configure the transfer interrupts */ lpc54_configxfrints(priv, SDCARD_RECV_MASK); @@ -1718,6 +1701,9 @@ static int lpc54_sendsetup(FAR struct sdio_dev_s *dev, FAR const uint8_t *buffer size_t nbytes) { struct lpc54_dev_s *priv = (struct lpc54_dev_s *)dev; +#ifdef CONFIG_LPC54_SDMMC_DMA + uint32_t regval; +#endif mcinfo("nbytes=%ld\n", (long)nbytes); @@ -1740,10 +1726,16 @@ static int lpc54_sendsetup(FAR struct sdio_dev_s *dev, FAR const uint8_t *buffer lpc54_putreg(SDMMC_FIFOTH_TXWMARK(LPC54_TXFIFO_DEPTH / 2), LPC54_SDMMC_FIFOTH); +#ifdef CONFIG_LPC54_SDMMC_DMA /* Make sure that internal DMA is disabled */ lpc54_putreg(0, LPC54_SDMMC_BMOD); + regval = lpc54_getreg(LPC54_SDMMC_CTRL); + regval &= ~SDMMC_CTRL_INTDMA + lpc54_putreg(regval, LPC54_SDMMC_CTRL); +#endif + /* Configure the transfer interrupts */ lpc54_configxfrints(priv, SDCARD_SEND_MASK); @@ -2464,6 +2456,10 @@ static int lpc54_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer, regval = SDMMC_BMOD_DE | SDMMC_BMOD_PBL_4XFRS | SDMMC_BMOD_DSL(4); lpc54_putreg(regval, LPC54_SDMMC_BMOD); + regval = lpc54_getreg(LPC54_SDMMC_CTRL); + regval |= SDMMC_CTRL_INTDMA + lpc54_putreg(regval, LPC54_SDMMC_CTRL); + /* Setup DMA error interrupts */ lpc54_configxfrints(priv, SDCARD_DMARECV_MASK); @@ -2532,6 +2528,7 @@ static int lpc54_dmasendsetup(FAR struct sdio_dev_s *dev, regval = lpc54_getreg(LPC54_SDMMC_CTRL); regval |= SDMMC_CTRL_FIFORESET | SDMMC_CTRL_DMARESET; lpc54_putreg(regval, LPC54_SDMMC_CTRL); + while (lpc54_getreg(LPC54_SDMMC_CTRL) & SDMMC_CTRL_DMARESET) { } @@ -2558,6 +2555,10 @@ static int lpc54_dmasendsetup(FAR struct sdio_dev_s *dev, regval = SDMMC_BMOD_DE | SDMMC_BMOD_PBL_4XFRS | SDMMC_BMOD_DSL(4); lpc54_putreg(regval, LPC54_SDMMC_BMOD); + regval = lpc54_getreg(LPC54_SDMMC_CTRL); + regval |= SDMMC_CTRL_INTDMA + lpc54_putreg(regval, LPC54_SDMMC_CTRL); + /* Setup DMA error interrupts */ lpc54_configxfrints(priv, SDCARD_DMASEND_MASK);