From 4b0327d845699e8e752a9204029562324d9bd588 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sun, 21 Oct 2018 17:55:51 -0600 Subject: [PATCH] arch/arm/src/lpc54/lpc54_sdmmc: Port Dave Marple's LPC43 USB DCD fix to the LPC54 with appropriate changed. --- arch/arm/src/lpc43xx/Kconfig | 1 + arch/arm/src/lpc43xx/lpc43_sdmmc.c | 9 +-- arch/arm/src/lpc54xx/Kconfig | 1 + arch/arm/src/lpc54xx/chip/lpc54_syscon.h | 3 + arch/arm/src/lpc54xx/lpc54_sdmmc.c | 74 +++++++++++++++++------- 5 files changed, 62 insertions(+), 26 deletions(-) diff --git a/arch/arm/src/lpc43xx/Kconfig b/arch/arm/src/lpc43xx/Kconfig index a6b62c3dde..a33e4154be 100644 --- a/arch/arm/src/lpc43xx/Kconfig +++ b/arch/arm/src/lpc43xx/Kconfig @@ -255,6 +255,7 @@ config LPC43_SDMMC bool "SD/MMC" default n select ARCH_HAVE_SDIO + select SDIO_BLOCKSETUP depends on EXPERIMENTAL config LPC43_SPI diff --git a/arch/arm/src/lpc43xx/lpc43_sdmmc.c b/arch/arm/src/lpc43xx/lpc43_sdmmc.c index c1bf86c46f..facaf0c304 100644 --- a/arch/arm/src/lpc43xx/lpc43_sdmmc.c +++ b/arch/arm/src/lpc43xx/lpc43_sdmmc.c @@ -1412,9 +1412,9 @@ static sdio_statset_t lpc43_status(FAR struct sdio_dev_s *dev) priv->cdstatus |= SDIO_STATUS_PRESENT; } else - { + { priv->cdstatus &= ~SDIO_STATUS_PRESENT; - } + } #endif mcinfo("cdstatus=%02x\n", priv->cdstatus); @@ -1690,8 +1690,6 @@ static int lpc43_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, static void lpc43_blocksetup(FAR struct sdio_dev_s *dev, unsigned int blocklen, unsigned int nblocks) { - struct stm32_dev_s *priv = (struct stm32_dev_s *)dev; - mcinfo("blocklen=%ld, total transfer=%ld (%ld blocks)\n", blocklen, blocklen*nblocks, nblocks); @@ -1727,11 +1725,10 @@ static int lpc43_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer, size_t nbytes) { 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); DEBUGASSERT(priv != NULL && buffer != NULL && nbytes > 0); diff --git a/arch/arm/src/lpc54xx/Kconfig b/arch/arm/src/lpc54xx/Kconfig index 947350c773..5b40181360 100644 --- a/arch/arm/src/lpc54xx/Kconfig +++ b/arch/arm/src/lpc54xx/Kconfig @@ -426,6 +426,7 @@ config LPC54_SDMMC bool "SD/MMC" default n select ARCH_HAVE_SDIO + select SDIO_BLOCKSETUP depends on EXPERIMENTAL config LPC54_WWDT diff --git a/arch/arm/src/lpc54xx/chip/lpc54_syscon.h b/arch/arm/src/lpc54xx/chip/lpc54_syscon.h index 2de9d22540..aba819a31b 100644 --- a/arch/arm/src/lpc54xx/chip/lpc54_syscon.h +++ b/arch/arm/src/lpc54xx/chip/lpc54_syscon.h @@ -737,8 +737,11 @@ #define SYSCON_SDIOCLKCTRL_CCLK_SMPDLYACTIVE (1 << 31) /* Bit 31: Enables sample delay */ /* FRO oscillator control */ + #define SYSCON_FROCTRL_ + /* System oscillator control */ + #define SYSCON_SYSOSCCTRL_ /* Watchdog oscillator control */ diff --git a/arch/arm/src/lpc54xx/lpc54_sdmmc.c b/arch/arm/src/lpc54xx/lpc54_sdmmc.c index d9dffcd134..7cf9fb300b 100644 --- a/arch/arm/src/lpc54xx/lpc54_sdmmc.c +++ b/arch/arm/src/lpc54xx/lpc54_sdmmc.c @@ -124,6 +124,10 @@ # error "Callback support requires CONFIG_SCHED_WORKQUEUE" #endif +#ifndef CONFIG_SDIO_BLOCKSETUP +# error "Driver requires CONFIG_SDIO_BLOCKSETUP to be set" +#endif + /* Timing */ #define SDCARD_CMDTIMEOUT (10000) @@ -312,6 +316,10 @@ static int lpc54_attach(FAR struct sdio_dev_s *dev); static int lpc54_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, uint32_t arg); +#ifdef CONFIG_SDIO_BLOCKSETUP +static void lpc54_blocksetup(FAR struct sdio_dev_s *dev, + unsigned int blocklen, unsigned int nblocks); +#endif static int lpc54_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer, size_t nbytes); static int lpc54_sendsetup(FAR struct sdio_dev_s *dev, @@ -367,6 +375,9 @@ struct lpc54_dev_s g_scard_dev = .clock = lpc54_clock, .attach = lpc54_attach, .sendcmd = lpc54_sendcmd, +#ifdef CONFIG_SDIO_BLOCKSETUP + .blocksetup = lpc54_blocksetup, +#endif .recvsetup = lpc54_recvsetup, .sendsetup = lpc54_sendsetup, .cancel = lpc54_cancel, @@ -1395,6 +1406,17 @@ static sdio_statset_t lpc54_status(FAR struct sdio_dev_s *dev) { struct lpc54_dev_s *priv = (struct lpc54_dev_s *)dev; +#ifdef CONFIG_MMCSD_HAVE_CARDDETECT + if ((lpc54_getreg(LPC54_SDMMC_CDETECT) & SDMMC_CDETECT_NOTPRESENT) == 0) + { + priv->cdstatus |= SDIO_STATUS_PRESENT; + } + else + { + priv->cdstatus &= ~SDIO_STATUS_PRESENT; + } +#endif + mcinfo("cdstatus=%02x\n", priv->cdstatus); return priv->cdstatus; @@ -1648,6 +1670,36 @@ static int lpc54_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd, return OK; } +/**************************************************************************** + * Name: lpc54_blocksetup + * + * Description: + * Configure block size and the number of blocks for next transfer + * + * Input Parameters: + * dev - An instance of the SDIO device interface + * blocklen - The selected block size. + * nblocklen - The number of blocks to transfer + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_SDIO_BLOCKSETUP +static void lpc54_blocksetup(FAR struct sdio_dev_s *dev, + unsigned int blocklen, unsigned int nblocks) +{ + mcinfo("blocklen=%ld, total transfer=%ld (%ld blocks)\n", + blocklen, blocklen*nblocks, nblocks); + + /* Configure block size for next transfer */ + + lpc54_putreg(blocklen, LPC54_SDMMC_BLKSIZ); + lpc54_putreg(blocklen * nblocks, LPC54_SDMMC_BYTCNT); +} +#endif + /**************************************************************************** * Name: lpc54_recvsetup * @@ -1673,8 +1725,6 @@ static int lpc54_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer, size_t nbytes) { 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 @@ -1693,23 +1743,6 @@ static int lpc54_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer, priv->dmamode = false; #endif - /* Then set up the SD card data path */ - - if (nbytes < 64) - { - blocksize = nbytes; - bytecnt = nbytes; - } - else - { - blocksize = 64; - bytecnt = nbytes; - DEBUGASSERT((nbytes & 0x3f) == 0); - } - - lpc54_putreg(blocksize, LPC54_SDMMC_BLKSIZ); - lpc54_putreg(bytecnt, LPC54_SDMMC_BYTCNT); - /* Configure the FIFO so that we will receive the RXDR interrupt whenever * there are more than 1 words (at least 8 bytes) in the RX FIFO. */ @@ -2739,8 +2772,9 @@ FAR struct sdio_dev_s *lpc54_sdmmc_initialize(int slotno) lpc54_sdmmc_enableclk(); - /* REVISIT: The delay values on the sample and drive inputs and outputs + /* The delay values on the sample and drive inputs and outputs * can be adjusted using the SDIOCLKCTRL register in the SYSCON block. + * Here we just leave these at the default settings. */ /* Initialize semaphores */