You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2021/09/18 15:18:13 UTC

[incubator-nuttx] branch master updated (3e92a4e -> f755356)

This is an automated email from the ASF dual-hosted git repository.

acassis pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git.


    from 3e92a4e  fs:procfs: add waiting_paging_fill state names
     new 772432e  mpfs: add emmcsd driver
     new 812f504  mpfs: emmcsd: add Kconfig/Makefile and board files
     new e022ea1  mpfs/icicle/configs/hwtest: enable SD card
     new 3a6d2ad  Documentation/mpfs: add SD to supported peripherals
     new f755356  drivers/mmcsd/mmcsd_spi: fix warning with finfo print

The 5 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 Documentation/platforms/risc-v/mpfs/index.rst      |    6 +-
 arch/risc-v/src/mpfs/Kconfig                       |    9 +
 arch/risc-v/src/mpfs/Make.defs                     |    6 +-
 arch/risc-v/src/mpfs/hardware/mpfs_emmcsd.h        |  746 +++++
 arch/risc-v/src/mpfs/mpfs_emmcsd.c                 | 2966 ++++++++++++++++++++
 .../src/mpfs/mpfs_emmcsd.h}                        |   10 +-
 boards/risc-v/mpfs/icicle/configs/hwtest/defconfig |    6 +
 boards/risc-v/mpfs/icicle/src/Makefile             |    4 +
 boards/risc-v/mpfs/icicle/src/mpfs_bringup.c       |    9 +
 .../mpfs/icicle/src/mpfs_emmcsd.c}                 |   57 +-
 boards/risc-v/mpfs/icicle/src/mpfsicicle.h         |    1 +
 drivers/mmcsd/mmcsd_spi.c                          |    2 +-
 12 files changed, 3781 insertions(+), 41 deletions(-)
 create mode 100755 arch/risc-v/src/mpfs/hardware/mpfs_emmcsd.h
 create mode 100755 arch/risc-v/src/mpfs/mpfs_emmcsd.c
 copy arch/{arm/src/stm32h7/stm32_sdmmc.h => risc-v/src/mpfs/mpfs_emmcsd.h} (94%)
 mode change 100644 => 100755
 copy boards/{arm/lpc31xx/olimex-lpc-h3131/src/lpc31_mmcsd.c => risc-v/mpfs/icicle/src/mpfs_emmcsd.c} (67%)

[incubator-nuttx] 04/05: Documentation/mpfs: add SD to supported peripherals

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 3a6d2adce83ebd5f7c8e80249a7f936601d79f7d
Author: Janne Rosberg <ja...@offcode.fi>
AuthorDate: Fri Sep 17 10:46:20 2021 +0300

    Documentation/mpfs: add SD to supported peripherals
---
 Documentation/platforms/risc-v/mpfs/index.rst | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/Documentation/platforms/risc-v/mpfs/index.rst b/Documentation/platforms/risc-v/mpfs/index.rst
index 3ab77a1..bb73321 100644
--- a/Documentation/platforms/risc-v/mpfs/index.rst
+++ b/Documentation/platforms/risc-v/mpfs/index.rst
@@ -59,13 +59,13 @@ GPIO           Yes
 MMUART         Yes      Uart mode only
 SPI            Yes      
 I2C            Yes      
-Timers         No       
+eMMC SD/SDIO   Yes      eMMC not fully tested
+Timers         No
 Watchdog       No       
 RTC            No       
 CAN            No       
 eNVM           No       
-USB            No       
-eMMC SD/SDIO   No       
+USB            No
 ============   =======  =====
 
 

[incubator-nuttx] 03/05: mpfs/icicle/configs/hwtest: enable SD card

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit e022ea1283f1e4151988833ec034e8a0c9dea178
Author: Janne Rosberg <ja...@offcode.fi>
AuthorDate: Fri Sep 17 09:52:27 2021 +0300

    mpfs/icicle/configs/hwtest: enable SD card
---
 boards/risc-v/mpfs/icicle/configs/hwtest/defconfig | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/boards/risc-v/mpfs/icicle/configs/hwtest/defconfig b/boards/risc-v/mpfs/icicle/configs/hwtest/defconfig
index 257e5f5..fddc3cb 100644
--- a/boards/risc-v/mpfs/icicle/configs/hwtest/defconfig
+++ b/boards/risc-v/mpfs/icicle/configs/hwtest/defconfig
@@ -7,6 +7,7 @@
 #
 # CONFIG_DISABLE_OS_API is not set
 # CONFIG_NSH_DISABLE_LOSMART is not set
+# CONFIG_SPI_CALLBACK is not set
 CONFIG_ALLOW_BSD_COMPONENTS=y
 CONFIG_ARCH="risc-v"
 CONFIG_ARCH_BOARD="icicle"
@@ -27,6 +28,7 @@ CONFIG_DEBUG_SYMBOLS=y
 CONFIG_DEBUG_WARN=y
 CONFIG_DEV_ZERO=y
 CONFIG_EXPERIMENTAL=y
+CONFIG_FS_FAT=y
 CONFIG_FS_PROCFS=y
 CONFIG_FS_ROMFS=y
 CONFIG_I2C=y
@@ -38,9 +40,12 @@ CONFIG_LIBC_PERROR_STDOUT=y
 CONFIG_LIBC_STRERROR=y
 CONFIG_MEMSET_64BIT=y
 CONFIG_MEMSET_OPTSPEED=y
+CONFIG_MMCSD=y
+CONFIG_MMCSD_SDIO=y
 CONFIG_MPFS_COREPWM0=y
 CONFIG_MPFS_COREPWM1=y
 CONFIG_MPFS_DMA=y
+CONFIG_MPFS_EMMCSD=y
 CONFIG_MPFS_ENABLE_DPFPU=y
 CONFIG_MPFS_HAVE_COREPWM=y
 CONFIG_MPFS_I2C0=y
@@ -62,6 +67,7 @@ CONFIG_NSH_DISABLE_UMOUNT=y
 CONFIG_NSH_LINELEN=160
 CONFIG_NSH_STRERROR=y
 CONFIG_PREALLOC_TIMERS=4
+CONFIG_PTABLE_PARTITION=y
 CONFIG_PWM=y
 CONFIG_PWM_NCHANNELS=16
 CONFIG_RAM_SIZE=1048576

[incubator-nuttx] 02/05: mpfs: emmcsd: add Kconfig/Makefile and board files

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 812f504c1661beed5d52e7d6eafaecca1cc5b199
Author: Eero Nurkkala <ee...@offcode.fi>
AuthorDate: Mon Aug 30 12:25:21 2021 +0300

    mpfs: emmcsd: add Kconfig/Makefile and board files
    
    Add necessary Kconfig, Make.defs, Makefile and board
    file changes.
    
    Signed-off-by: Eero Nurkkala <ee...@offcode.fi>
---
 arch/risc-v/src/mpfs/Kconfig                       |  9 +++
 arch/risc-v/src/mpfs/Make.defs                     |  6 +-
 boards/risc-v/mpfs/icicle/src/Makefile             |  4 ++
 boards/risc-v/mpfs/icicle/src/mpfs_bringup.c       |  9 +++
 .../icicle/src/{mpfs_bringup.c => mpfs_emmcsd.c}   | 80 ++++++++++------------
 boards/risc-v/mpfs/icicle/src/mpfsicicle.h         |  1 +
 6 files changed, 64 insertions(+), 45 deletions(-)

diff --git a/arch/risc-v/src/mpfs/Kconfig b/arch/risc-v/src/mpfs/Kconfig
index 287db4d..a74aaea 100755
--- a/arch/risc-v/src/mpfs/Kconfig
+++ b/arch/risc-v/src/mpfs/Kconfig
@@ -103,6 +103,15 @@ config MPFS_I2C1
         select ARCH_HAVE_I2CRESET
         default n
 
+config MPFS_EMMCSD
+        bool "EMMCSD"
+        select ARCH_HAVE_SDIO
+        select SDIO_BLOCKSETUP
+        select SDIO_DMA
+        default n
+        ---help---
+                Selects the MPFS eMMCSD driver.
+
 comment "CorePWM Options"
 
 config MPFS_HAVE_COREPWM
diff --git a/arch/risc-v/src/mpfs/Make.defs b/arch/risc-v/src/mpfs/Make.defs
index 69f5eff..22f017e 100755
--- a/arch/risc-v/src/mpfs/Make.defs
+++ b/arch/risc-v/src/mpfs/Make.defs
@@ -33,7 +33,7 @@ CMN_CSRCS  += riscv_interruptcontext.c riscv_modifyreg32.c riscv_puts.c
 CMN_CSRCS  += riscv_releasepending.c riscv_reprioritizertr.c
 CMN_CSRCS  += riscv_releasestack.c riscv_stackframe.c riscv_schedulesigaction.c
 CMN_CSRCS  += riscv_sigdeliver.c riscv_unblocktask.c riscv_usestack.c
-CMN_CSRCS  += riscv_mdelay.c riscv_copyfullstate.c
+CMN_CSRCS  += riscv_mdelay.c riscv_udelay.c riscv_copyfullstate.c
 
 ifeq ($(CONFIG_STACK_COLORATION),y)
 CMN_CSRCS += riscv_checkstack.c
@@ -74,6 +74,10 @@ ifeq ($(CONFIG_I2C),y)
 CHIP_CSRCS += mpfs_i2c.c
 endif
 
+ifeq ($(CONFIG_MPFS_EMMCSD),y)
+CHIP_CSRCS += mpfs_emmcsd.c
+endif
+
 ifeq (${CONFIG_MPFS_HAVE_COREPWM},y)
 CHIP_CSRCS += mpfs_corepwm.c
 endif
diff --git a/boards/risc-v/mpfs/icicle/src/Makefile b/boards/risc-v/mpfs/icicle/src/Makefile
index e493ec8..1f49e0a 100755
--- a/boards/risc-v/mpfs/icicle/src/Makefile
+++ b/boards/risc-v/mpfs/icicle/src/Makefile
@@ -46,4 +46,8 @@ ifeq ($(CONFIG_MPFS_HAVE_COREPWM),y)
 CSRCS += mpfs_pwm.c
 endif
 
+ifeq ($(CONFIG_MPFS_EMMCSD),y)
+CSRCS += mpfs_emmcsd.c
+endif
+
 include $(TOPDIR)/boards/Board.mk
diff --git a/boards/risc-v/mpfs/icicle/src/mpfs_bringup.c b/boards/risc-v/mpfs/icicle/src/mpfs_bringup.c
index f781afe..9018dd2 100755
--- a/boards/risc-v/mpfs/icicle/src/mpfs_bringup.c
+++ b/boards/risc-v/mpfs/icicle/src/mpfs_bringup.c
@@ -92,5 +92,14 @@ int mpfs_bringup(void)
     }
 #endif
 
+#ifdef CONFIG_MPFS_EMMCSD
+  ret = mpfs_board_emmcsd_init();
+
+  if (ret < 0)
+    {
+      syslog(LOG_ERR, "Failed to init eMMCSD driver: %d\n", ret);
+    }
+#endif
+
   return ret;
 }
diff --git a/boards/risc-v/mpfs/icicle/src/mpfs_bringup.c b/boards/risc-v/mpfs/icicle/src/mpfs_emmcsd.c
old mode 100755
new mode 100644
similarity index 55%
copy from boards/risc-v/mpfs/icicle/src/mpfs_bringup.c
copy to boards/risc-v/mpfs/icicle/src/mpfs_emmcsd.c
index f781afe..8b9d693
--- a/boards/risc-v/mpfs/icicle/src/mpfs_bringup.c
+++ b/boards/risc-v/mpfs/icicle/src/mpfs_emmcsd.c
@@ -1,5 +1,5 @@
 /****************************************************************************
- * boards/risc-v/mpfs/icicle/src/mpfs_bringup.c
+ * boards/risc-v/mpfs/icicle/src/mpfs_emmcsd.c
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -24,73 +24,65 @@
 
 #include <nuttx/config.h>
 
-#include <sys/mount.h>
-#include <stdbool.h>
-#include <stdio.h>
 #include <debug.h>
 #include <errno.h>
+#include <nuttx/mmcsd.h>
 
-#include <nuttx/board.h>
-#include <nuttx/drivers/ramdisk.h>
-
+#include "mpfs_emmcsd.h"
 #include "mpfsicicle.h"
-#include "mpfs_corepwm.h"
-#include "mpfs.h"
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static FAR struct sdio_dev_s *g_sdio_dev;
 
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
 
 /****************************************************************************
- * Name: mpfs_bringup
+ * Name: board_emmcsd_init
+ *
+ * Description:
+ *   Configure the eMMCSD driver.
+ *
+ * Returned Value:
+ *   Zero (OK) is returned on success; A negated errno value is returned
+ *   to indicate the nature of any failure.
+ *
  ****************************************************************************/
 
-int mpfs_bringup(void)
+int mpfs_board_emmcsd_init(void)
 {
-  int ret = OK;
+  int ret;
 
-#if defined(CONFIG_I2C_DRIVER)
-  /* Configure I2C peripheral interfaces */
+  /* Mount the SDIO-based MMC/SD block driver */
 
-  ret = mpfs_board_i2c_init();
+  /* First, get an instance of the SDIO interface */
 
-  if (ret < 0)
-    {
-      syslog(LOG_ERR, "Failed to initialize I2C driver: %d\n", ret);
-    }
-#endif
+  finfo("Initializing SDIO slot %d\n", CONFIG_NSH_MMCSDSLOTNO);
 
-#ifdef CONFIG_FS_PROCFS
-  /* Mount the procfs file system */
-
-  ret = mount(NULL, "/proc", "procfs", 0, NULL);
-  if (ret < 0)
+  g_sdio_dev = sdio_initialize(CONFIG_NSH_MMCSDSLOTNO);
+  if (!g_sdio_dev)
     {
-      serr("ERROR: Failed to mount procfs at %s: %d\n", "/proc", ret);
+      ferr("ERROR: Failed to initialize SDIO slot %d\n",
+           CONFIG_NSH_MMCSDSLOTNO);
+      return -ENODEV;
     }
-#endif
 
-#if defined(CONFIG_MPFS_SPI0) || defined(CONFIG_MPFS_SPI1)
-  /* Configure SPI peripheral interfaces */
+  /* Now bind the SDIO interface to the MMC/SD driver */
 
-  ret = mpfs_board_spi_init();
+  finfo("Bind SDIO to the MMC/SD driver, minor=%d\n", CONFIG_NSH_MMCSDMINOR);
 
-  if (ret < 0)
+  ret = mmcsd_slotinitialize(CONFIG_NSH_MMCSDMINOR, g_sdio_dev);
+  if (ret != OK)
     {
-      syslog(LOG_ERR, "Failed to initialize SPI driver: %d\n", ret);
+      ferr("ERROR: Failed to bind SDIO to the MMC/SD driver: %d\n", ret);
+      return ret;
     }
-#endif
-
-#ifdef CONFIG_MPFS_HAVE_COREPWM
-  /* Configure PWM peripheral interfaces */
 
-  ret = mpfs_pwm_setup();
-
-  if (ret < 0)
-    {
-      syslog(LOG_ERR, "Failed to initialize CorePWM driver: %d\n", ret);
-    }
-#endif
+  sdio_mediachange(g_sdio_dev, true);
 
-  return ret;
+  return OK;
 }
diff --git a/boards/risc-v/mpfs/icicle/src/mpfsicicle.h b/boards/risc-v/mpfs/icicle/src/mpfsicicle.h
index 600e7f9..d5f851f 100755
--- a/boards/risc-v/mpfs/icicle/src/mpfsicicle.h
+++ b/boards/risc-v/mpfs/icicle/src/mpfsicicle.h
@@ -44,6 +44,7 @@
 int mpfs_bringup(void);
 int mpfs_board_spi_init(void);
 int mpfs_board_i2c_init(void);
+int mpfs_board_emmcsd_init(void);
 int mpfs_pwm_setup(void);
 
 #endif /* __BOARDS_RISCV_ICICLE_MPFS_SRC_MPFSICICLE_H */

[incubator-nuttx] 01/05: mpfs: add emmcsd driver

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 772432e7c36eff619167e17d613ff2075968346e
Author: Eero Nurkkala <ee...@offcode.fi>
AuthorDate: Mon Aug 30 07:56:18 2021 +0300

    mpfs: add emmcsd driver
    
    This adds the emmcsd driver for the Polarfire Icicle kit.
    The driver has been tested with several SD-cards, such as:
    
     - Kingston 32 GB SDS2 Canvas Select Plus
     - Kingston MicroSD Canvas Select Plus
     - Sandisk Extreme PRO 32 GB
     - Transcend 8 GB MicroSD
    
    The internal eMMC hasn't been tested comprehensively.
    
    Signed-off-by: Eero Nurkkala <ee...@offcode.fi>
---
 arch/risc-v/src/mpfs/hardware/mpfs_emmcsd.h |  746 +++++++
 arch/risc-v/src/mpfs/mpfs_emmcsd.c          | 2966 +++++++++++++++++++++++++++
 arch/risc-v/src/mpfs/mpfs_emmcsd.h          |  113 +
 3 files changed, 3825 insertions(+)

diff --git a/arch/risc-v/src/mpfs/hardware/mpfs_emmcsd.h b/arch/risc-v/src/mpfs/hardware/mpfs_emmcsd.h
new file mode 100755
index 0000000..6cf6cdf
--- /dev/null
+++ b/arch/risc-v/src/mpfs/hardware/mpfs_emmcsd.h
@@ -0,0 +1,746 @@
+/****************************************************************************
+ * arch/risc-v/src/mpfs/hardware/mpfs_emmcsd.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_RISCV_SRC_MPFS_HARDWARE_MPFS_EMMCSD_H
+#define __ARCH_RISCV_SRC_MPFS_HARDWARE_MPFS_EMMCSD_H
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define MPFS_EMMCSD_HRS00_OFFSET      0x00
+#define MPFS_EMMCSD_HRS01_OFFSET      0x04
+#define MPFS_EMMCSD_HRS02_OFFSET      0x08
+#define MPFS_EMMCSD_HRS03_OFFSET      0x0c
+#define MPFS_EMMCSD_HRS04_OFFSET      0x10
+#define MPFS_EMMCSD_HRS06_OFFSET      0x18
+#define MPFS_EMMCSD_HRS07_OFFSET      0x1c
+#define MPFS_EMMCSD_HRS30_OFFSET      0x78
+#define MPFS_EMMCSD_HRS31_OFFSET      0x7c
+#define MPFS_EMMCSD_HRS32_OFFSET      0x80
+#define MPFS_EMMCSD_HRS33_OFFSET      0x84
+#define MPFS_EMMCSD_HRS34_OFFSET      0x88
+#define MPFS_EMMCSD_HRS35_OFFSET      0x8c
+#define MPFS_EMMCSD_HRS36_OFFSET      0x90
+#define MPFS_EMMCSD_HRS37_OFFSET      0x94
+#define MPFS_EMMCSD_HRS38_OFFSET      0x98
+
+#define MPFS_EMMCSD_CRS63_OFFSET      0xfc
+
+#define MPFS_EMMCSD_SRS00_OFFSET      0x200
+#define MPFS_EMMCSD_SRS01_OFFSET      0x204
+#define MPFS_EMMCSD_SRS02_OFFSET      0x208
+#define MPFS_EMMCSD_SRS03_OFFSET      0x20c
+#define MPFS_EMMCSD_SRS04_OFFSET      0x210
+#define MPFS_EMMCSD_SRS05_OFFSET      0x214
+#define MPFS_EMMCSD_SRS06_OFFSET      0x218
+#define MPFS_EMMCSD_SRS07_OFFSET      0x21c
+#define MPFS_EMMCSD_SRS08_OFFSET      0x220
+#define MPFS_EMMCSD_SRS09_OFFSET      0x224
+#define MPFS_EMMCSD_SRS10_OFFSET      0x228
+#define MPFS_EMMCSD_SRS11_OFFSET      0x22c
+#define MPFS_EMMCSD_SRS12_OFFSET      0x230
+#define MPFS_EMMCSD_SRS13_OFFSET      0x234
+#define MPFS_EMMCSD_SRS14_OFFSET      0x238
+#define MPFS_EMMCSD_SRS15_OFFSET      0x23c
+#define MPFS_EMMCSD_SRS16_OFFSET      0x240
+#define MPFS_EMMCSD_SRS17_OFFSET      0x244
+#define MPFS_EMMCSD_SRS18_OFFSET      0x248
+#define MPFS_EMMCSD_SRS19_OFFSET      0x24c
+#define MPFS_EMMCSD_SRS20_OFFSET      0x250
+#define MPFS_EMMCSD_SRS21_OFFSET      0x254
+#define MPFS_EMMCSD_SRS22_OFFSET      0x258
+#define MPFS_EMMCSD_SRS23_OFFSET      0x25c
+
+#define MPFS_EMMCSD_SRS24_OFFSET      0x260
+#define MPFS_EMMCSD_SRS25_OFFSET      0x264
+#define MPFS_EMMCSD_SRS26_OFFSET      0x268
+#define MPFS_EMMCSD_SRS27_OFFSET      0x26c
+#define MPFS_EMMCSD_SRS29_OFFSET      0x274
+
+#define MPFS_EMMCSD_CQRS00_OFFSET     0x400
+#define MPFS_EMMCSD_CQRS01_OFFSET     0x404
+#define MPFS_EMMCSD_CQRS02_OFFSET     0x408
+#define MPFS_EMMCSD_CQRS03_OFFSET     0x40c
+#define MPFS_EMMCSD_CQRS04_OFFSET     0x410
+#define MPFS_EMMCSD_CQRS05_OFFSET     0x414
+#define MPFS_EMMCSD_CQRS06_OFFSET     0x418
+#define MPFS_EMMCSD_CQRS07_OFFSET     0x41c
+#define MPFS_EMMCSD_CQRS08_OFFSET     0x420
+#define MPFS_EMMCSD_CQRS09_OFFSET     0x424
+#define MPFS_EMMCSD_CQRS10_OFFSET     0x428
+#define MPFS_EMMCSD_CQRS11_OFFSET     0x42c
+#define MPFS_EMMCSD_CQRS12_OFFSET     0x430
+#define MPFS_EMMCSD_CQRS13_OFFSET     0x434
+#define MPFS_EMMCSD_CQRS14_OFFSET     0x438
+#define MPFS_EMMCSD_CQRS16_OFFSET     0x440
+#define MPFS_EMMCSD_CQRS17_OFFSET     0x444
+#define MPFS_EMMCSD_CQRS18_OFFSET     0x448
+#define MPFS_EMMCSD_CQRS20_OFFSET     0x450
+#define MPFS_EMMCSD_CQRS21_OFFSET     0x454
+#define MPFS_EMMCSD_CQRS22_OFFSET     0x458
+#define MPFS_EMMCSD_CQRS23_OFFSET     0x45c
+
+/* HRS00 register */
+
+#define MPFS_EMMCSD_HRS00_HWINIT1       (0xff << 24)
+#define MPFS_EMMCSD_HRS00_SAV           (0xff << 16)
+#define MPFS_EMMCSD_HRS00_HWINIT0       (0x7fff << 1)
+#define MPFS_EMMCSD_HRS00_SWR           (1 << 0)
+
+/* HRS01 register */
+
+#define MPFS_EMMCSD_HRS01_HWINIT0       (0xff << 24)
+#define MPFS_EMMCSD_HRS01_DP            (0xffffff << 0)
+
+/* HRS02 register */
+
+#define MPFS_EMMCSD_HRS02_HWINIT1       (0x3fff << 18)
+#define MPFS_EMMCSD_FRS02_OTN           (0x3 << 16)
+#define MPFS_EMMCSD_HRS02_HWINIT0       (0xfff << 4)
+#define MPFS_EMMCSD_HRS02_PBL           (0xf << 0)
+
+/* HRS03 register */
+
+#define MPFS_EMMCSD_HRS03_AER_IEBS      (1 << 19)
+#define MPFS_EMMCSD_HRS03_AER_IEBD      (1 << 18)
+#define MPFS_EMMCSD_HRS03_AER_IERS      (1 << 17)
+#define MPFS_EMMCSD_HRS03_AER_IERD      (1 << 16)
+#define MPFS_EMMCSD_HRS03_AER_SENBS     (1 << 11)
+#define MPFS_EMMCSD_HRS03_AER_SENBD     (1 << 10)
+#define MPFS_EMMCSD_HRS03_AER_SENRS     (1 << 9)
+#define MPFS_EMMCSD_HRS03_AER_SENRD     (1 << 8)
+#define MPFS_EMMCSD_HRS03_AER_BS        (1 << 3)
+#define MPFS_EMMCSD_HRS03_AER_BD        (1 << 2)
+#define MPFS_EMMCSD_HRS03_AER_RS        (1 << 1)
+#define MPFS_EMMCSD_HRS03_AER_RD        (1 << 0)
+
+/* HRS04 register */
+
+#define MPFS_EMMCSD_HRS04_UIS_ACK       (1 << 26)
+#define MPFS_EMMCSD_HRS04_UIS_RD        (1 << 25)
+#define MPFS_EMMCSD_HRS04_UIS_WR        (1 << 24)
+#define MPFS_EMMCSD_HRS04_UIS_RDATA     (0xff << 16)
+#define MPFS_EMMCSD_HRS04_UIS_WDATA     (0xff << 8)
+#define MPFS_EMMCSD_HRS04_UIS_ADDR      (0x3f << 0)
+
+/* HRS06 register */
+
+#define MPFS_EMMCSD_HRS06_ETR           (1 << 15)
+#define MPFS_EMMCSD_HRS06_ETV           (0x3f << 8)
+#define MPFS_EMMCSD_HRS06_EMM           (0x3 << 0)
+
+/* HRS07 register */
+
+#define MPFS_EMMCSD_HRS07_ODELAY_VAL    (0x1f << 16)
+#define MPFS_EMMCSD_HRS07_IDELAY_VAL    (0x1f << 0)
+
+/* HRS30 register */
+
+#define MPFS_EMMCSD_HRS30_HS400ESSUP    (1 << 1)
+#define MPFS_EMMCSD_HRS30_CQSUP         (1 << 0)
+
+/* HRS31 register */
+
+#define MPFS_EMMCSD_HRS31_HOSTCTRLVER   (0xfff << 16)
+#define MPFS_EMMCSD_HRS31_HOSTFIXVER    (0xff << 0)
+
+/* HRS32 register */
+
+#define MPFS_EMMCSD_HRS32_LOAD          (1 << 31)
+#define MPFS_EMMCSD_HRS32_ADDR          (0x7fff << 16)
+#define MPFS_EMMCSD_HRS32_DATA          (0xffff << 0)
+
+/* HRS33 register */
+
+/* #define MPFS_EMMCSD_HRS33_STAT0 */
+
+/* HRS34 register */
+
+#define MPFS_EMMCSD_HRS33_STAT1         (0xff << 0)
+
+/* HRS35 register */
+
+#define MPFS_EMMCSD_HRS35_TFR           (1 << 31)
+#define MPFS_EMMCSD_HRS35_TFV           (0x3f << 16)
+#define MPFS_EMMCSD_HRS35_TVAL          (0x3f << 0)
+
+/* HRS36 register */
+
+#define MPFS_EMMCSD_HRS36_BOOT_EDE      (1 << 5)
+#define MPFS_EMMCSD_HRS36_BOOT_EDC      (1 << 4)
+#define MPFS_EMMCSD_HRS36_BOOT_EDT      (1 << 3)
+#define MPFS_EMMCSD_HRS36_BOOT_EAI      (1 << 2)
+#define MPFS_EMMCSD_HRS36_BOOT_EAT      (1 << 1)
+#define MPFS_EMMCSD_HRS36_BOOT_ACT      (1 << 0)
+
+/* HRS37 register */
+
+#define MPFS_EMMCSD_HRS37_RGB_COEFF_IFM (0x3f << 0)
+
+/* HRS38 register */
+
+#define MPFS_EMMCSD_HRS38_RGB_COEFF     (0x0f << 0)
+
+/* CRS63 register */
+
+#define MPFS_EMMCSD_CRS63_HWINIT1       (0xff << 24)
+#define MPFS_EMMCSD_CRS63_SVN           (0xff << 16)
+#define MPFS_EMMCSD_CRS63_HWINIT0       (0xff << 8)
+#define MPFS_EMMCSD_CRS63_ISES          (0xff << 0)
+
+/* SRS01 register */
+
+#define MPFS_EMMCSD_SRS01_BCCT          (0xff << 16)
+#define MPFS_EMMCSD_SRS01_SDMABB        (0x7 << 12)
+#define MPFS_EMMCSD_SRS01_TBS           (0xfff << 0)
+
+#define MPFS_EMMCSD_SRS01_DMA_SZ_512KB  0x00007000
+
+/* SRS03 register */
+
+#define MPFS_EMMCSD_SRS03_CIDX          (0x3f << 24)
+#define MPFS_EMMCSD_SRS03_CT            (0x03 << 22)
+#define MPFS_EMMCSD_SRS03_DPS           (1 << 21)
+#define MPFS_EMMCSD_SRS03_CICE          (1 << 20)
+#define MPFS_EMMCSD_SRS03_CRCCE         (1 << 19)
+#define MPFS_EMMCSD_SRS03_RTS           (0x3 << 16)
+#define MPFS_EMMCSD_SRS03_RID           (1 << 8)
+#define MPFS_EMMCSD_SRS03_RECE          (1 << 7)
+#define MPFS_EMMCSD_SRS03_RECT          (1 << 6)
+#define MPFS_EMMCSD_SRS03_MSBS          (1 << 5)
+#define MPFS_EMMCSD_SRS03_DTDS          (1 << 4)
+#define MPFS_EMMCSD_SRS03_ACE           (0x3 << 2)
+#define MPFS_EMMCSD_SRS03_BCE           (1 << 1)
+#define MPFS_EMMCSD_SRS03_DMAE          (1 << 0)
+
+#define MPFS_EMMCSD_SRS03_NO_RESPONSE   (0 << 16)
+#define MPFS_EMMCSD_SRS03_RESP_L136     (0x1 << 16)
+#define MPFS_EMMCSD_SRS03_RESP_L48      (0x2 << 16)
+#define MPFS_EMMCSD_SRS03_RESP_L48B     (0x3 << 16)
+
+/* SRS09 register */
+
+#define MPFS_EMMCSD_SRS09_CMDSL         (1 << 24)
+#define MPFS_EMMCSD_SRS09_DATSL1        (0xf << 20)
+#define MPFS_EMMCSD_SRS09_WPSL          (1 << 19)
+#define MPFS_EMMCSD_SRS09_CDSL          (1 << 18)
+#define MPFS_EMMCSD_SRS09_CSS           (1 << 17)
+#define MPFS_EMMCSD_SRS09_CI            (1 << 16)
+#define MPFS_EMMCSD_SRS09_BRE           (1 << 11)
+#define MPFS_EMMCSD_SRS09_BWE           (1 << 10)
+#define MPFS_EMMCSD_SRS09_RTA           (1 << 9)
+#define MPFS_EMMCSD_SRS09_WTA           (1 << 8)
+#define MPFS_EMMCSD_SRS09_DATSL2        (0xf << 4)
+#define MPFS_EMMCSD_SRS09_DLA           (1 << 2)
+#define MPFS_EMMCSD_SRS09_CIDAT         (1 << 1)
+#define MPFS_EMMCSD_SRS09_CICMD         (1 << 0)
+
+/* SRS10 register */
+
+#define MPFS_EMMCSD_SRS10_WORM          (1 << 26)
+#define MPFS_EMMCSD_SRS10_WOIS          (1 << 25)
+#define MPFS_EMMCSD_SRS10_WOIQ          (1 << 24)
+#define MPFS_EMMCSD_SRS10_IBG           (1 << 19)
+#define MPFS_EMMCSD_SRS10_RWC           (1 << 18)
+#define MPFS_EMMCSD_SRS10_CREQ          (1 << 17)
+#define MPFS_EMMCSD_SRS10_SBGR          (1 << 16)
+#define MPFS_EMMCSD_SRS10_BVS2          (0x7 << 13)
+#define MPFS_EMMCSD_SRS10_BP2           (1 << 12)
+#define MPFS_EMMCSD_SRS10_BVS           (0x7 << 9)
+#define MPFS_EMMCSD_SRS10_BP            (1 << 8)
+#define MPFS_EMMCSD_SRS10_CDSS          (1 << 7)
+#define MPFS_EMMCSD_SRS10_CDTL          (1 << 6)
+#define MPFS_EMMCSD_SRS10_EDTW          (1 << 5)
+#define MPFS_EMMCSD_SRS10_DMASEL        (0x3 << 3)
+#define MPFS_EMMCSD_SRS10_HSE           (1 << 2)
+#define MPFS_EMMCSD_SRS10_DTW           (1 << 1)
+#define MPFS_EMMCSD_SRS10_LEDC          (1 << 0)
+
+/* SRS11 register */
+
+#define MPFS_EMMCSD_SRS11_SRDAT         (1 << 26)
+#define MPFS_EMMCSD_SRS11_SRCMD         (1 << 25)
+#define MPFS_EMMCSD_SRS11_SRFA          (1 << 24)
+#define MPFS_EMMCSD_SRS11_DTCV          (0xf << 16)
+#define MPFS_EMMCSD_SRS11_SDCFSL        (0xff << 8)
+#define MPFS_EMMCSD_SRS11_SDCFSH        (0x3 << 6)
+#define MPFS_EMMCSD_SRS11_CLKGENSEL     (1 << 5) /* Not documented! */
+#define MPFS_EMMCSD_SRS11_SDCE          (1 << 2)
+#define MPFS_EMMCSD_SRS11_ICS           (1 << 1)
+#define MPFS_EMMCSD_SRS11_ICE           (1 << 0)
+
+/* SRS12 register */
+
+#define MPFS_EMMCSD_SRS12_ERSP          (1 << 27)
+#define MPFS_EMMCSD_SRS12_EADMA         (1 << 25)
+#define MPFS_EMMCSD_SRS12_EAC           (1 << 24)
+#define MPFS_EMMCSD_SRS12_ECL           (1 << 23)
+#define MPFS_EMMCSD_SRS12_EDEB          (1 << 22)
+#define MPFS_EMMCSD_SRS12_EDCRC         (1 << 21)
+#define MPFS_EMMCSD_SRS12_EDT           (1 << 20)
+#define MPFS_EMMCSD_SRS12_ECI           (1 << 19)
+#define MPFS_EMMCSD_SRS12_ECEB          (1 << 18)
+#define MPFS_EMMCSD_SRS12_ECCRC         (1 << 17)
+#define MPFS_EMMCSD_SRS12_ECT           (1 << 16)
+#define MPFS_EMMCSD_SRS12_EINT          (1 << 15)
+#define MPFS_EMMCSD_SRS12_CQINT         (1 << 14)
+#define MPFS_EMMCSD_SRS12_CINT          (1 << 8)
+#define MPFS_EMMCSD_SRS12_CR            (1 << 7)
+#define MPFS_EMMCSD_SRS12_CIN           (1 << 6)
+#define MPFS_EMMCSD_SRS12_BRR           (1 << 5)
+#define MPFS_EMMCSD_SRS12_BWR           (1 << 4)
+#define MPFS_EMMCSD_SRS12_DMAINT        (1 << 3)
+#define MPFS_EMMCSD_SRS12_BGE           (1 << 2)
+#define MPFS_EMMCSD_SRS12_TC            (1 << 1)
+#define MPFS_EMMCSD_SRS12_CC            (1 << 0)
+
+#define MPFS_EMMCSD_SRS12_ESTAT_MASK    (0xFFFF8000u)
+#define MPFS_EMMCSD_SRS12_STAT_CLEAR    0xFFFFFFFFu
+
+/* SRS13 register */
+
+#define MPFS_EMMCSD_SRS13_ERSP_SE       (1 << 27)
+#define MPFS_EMMCSD_SRS13_TUNING_ERR_SE (1 << 26)
+#define MPFS_EMMCSD_SRS13_EADMA_SE      (1 << 25)
+#define MPFS_EMMCSD_SRS13_EAC_SE        (1 << 24)
+#define MPFS_EMMCSD_SRS13_ECL_SE        (1 << 23)
+#define MPFS_EMMCSD_SRS13_EDEB_SE       (1 << 22)
+#define MPFS_EMMCSD_SRS13_EDCRC_SE      (1 << 21)
+#define MPFS_EMMCSD_SRS13_EDT_SE        (1 << 20)
+#define MPFS_EMMCSD_SRS13_ECI_SE        (1 << 19)
+#define MPFS_EMMCSD_SRS13_ECEB_SE       (1 << 18)
+#define MPFS_EMMCSD_SRS13_ECCRC_SE      (1 << 17)
+#define MPFS_EMMCSD_SRS13_ECT_SE        (1 << 16)
+#define MPFS_EMMCSD_SRS13_CQINT_SE      (1 << 14)
+#define MPFS_EMMCSD_SRS13_RT_SE         (1 << 12) /* Undocumented */
+#define MPFS_EMMCSD_SRS13_INT_ON_C_SE   (1 << 11) /* Undocumented */
+#define MPFS_EMMCSD_SRS13_INT_ON_B_SE   (1 << 10) /* Undocumented */
+#define MPFS_EMMCSD_SRS13_INT_ON_A_SE   (1 << 9)  /* Undocumented */
+#define MPFS_EMMCSD_SRS13_CINT_SE       (1 << 8)
+#define MPFS_EMMCSD_SRS13_CR_SE         (1 << 7)
+#define MPFS_EMMCSD_SRS13_CIN_SE        (1 << 6)
+#define MPFS_EMMCSD_SRS13_BRR_SE        (1 << 5)
+#define MPFS_EMMCSD_SRS13_BWR_SE        (1 << 4)
+#define MPFS_EMMCSD_SRS13_DMAINT_SE     (1 << 3)
+#define MPFS_EMMCSD_SRS13_BGE_SE        (1 << 2)
+#define MPFS_EMMCSD_SRS13_TC_SE         (1 << 1)
+#define MPFS_EMMCSD_SRS13_CC_SE         (1 << 0)
+
+#define MPFS_EMMCSD_SRS13_STATUS_EN (MPFS_EMMCSD_SRS13_ERSP_SE |       \
+                                     MPFS_EMMCSD_SRS13_TUNING_ERR_SE | \
+                                     MPFS_EMMCSD_SRS13_EADMA_SE |      \
+                                     MPFS_EMMCSD_SRS13_EAC_SE |        \
+                                     MPFS_EMMCSD_SRS13_ECL_SE |        \
+                                     MPFS_EMMCSD_SRS13_EDEB_SE |       \
+                                     MPFS_EMMCSD_SRS13_EDCRC_SE |      \
+                                     MPFS_EMMCSD_SRS13_EDT_SE |        \
+                                     MPFS_EMMCSD_SRS13_ECI_SE |        \
+                                     MPFS_EMMCSD_SRS13_ECEB_SE |       \
+                                     MPFS_EMMCSD_SRS13_ECCRC_SE |      \
+                                     MPFS_EMMCSD_SRS13_ECT_SE |        \
+                                     MPFS_EMMCSD_SRS13_CQINT_SE |      \
+                                     MPFS_EMMCSD_SRS13_RT_SE |         \
+                                     MPFS_EMMCSD_SRS13_INT_ON_C_SE |   \
+                                     MPFS_EMMCSD_SRS13_INT_ON_B_SE |   \
+                                     MPFS_EMMCSD_SRS13_INT_ON_A_SE |   \
+                                     MPFS_EMMCSD_SRS13_CR_SE |         \
+                                     MPFS_EMMCSD_SRS13_CIN_SE |        \
+                                     MPFS_EMMCSD_SRS13_BRR_SE |        \
+                                     MPFS_EMMCSD_SRS13_BWR_SE |        \
+                                     MPFS_EMMCSD_SRS13_DMAINT_SE |     \
+                                     MPFS_EMMCSD_SRS13_BGE_SE |        \
+                                     MPFS_EMMCSD_SRS13_TC_SE |         \
+                                     MPFS_EMMCSD_SRS13_CC_SE)
+
+/* SRS14 register */
+
+#define MPFS_EMMCSD_SRS14_ERSP_IE       (1 << 27)
+#define MPFS_EMMCSD_SRS14_EADMA_IE      (1 << 25)
+#define MPFS_EMMCSD_SRS14_EAC_IE        (1 << 24)
+#define MPFS_EMMCSD_SRS14_ECL_IE        (1 << 23)
+#define MPFS_EMMCSD_SRS14_EDEB_IE       (1 << 22)
+#define MPFS_EMMCSD_SRS14_EDCRC_IE      (1 << 21)
+#define MPFS_EMMCSD_SRS14_EDT_IE        (1 << 20)
+#define MPFS_EMMCSD_SRS14_ECI_IE        (1 << 19)
+#define MPFS_EMMCSD_SRS14_ECEB_IE       (1 << 18)
+#define MPFS_EMMCSD_SRS14_ECCRC_IE      (1 << 17)
+#define MPFS_EMMCSD_SRS14_ECT_IE        (1 << 16)
+#define MPFS_EMMCSD_SRS14_CQINT_IE      (1 << 14)
+#define MPFS_EMMCSD_SRS14_CINT_IE       (1 << 8)
+#define MPFS_EMMCSD_SRS14_CR_IE         (1 << 7)
+#define MPFS_EMMCSD_SRS14_CIN_IE        (1 << 6)
+#define MPFS_EMMCSD_SRS14_BRR_IE        (1 << 5)
+#define MPFS_EMMCSD_SRS14_BWR_IE        (1 << 4)
+#define MPFS_EMMCSD_SRS14_DMAINT_IE     (1 << 3)
+#define MPFS_EMMCSD_SRS14_BGE_IE        (1 << 2)
+#define MPFS_EMMCSD_SRS14_TC_IE         (1 << 1)
+#define MPFS_EMMCSD_SRS14_CC_IE         (1 << 0)
+
+/* SRS15 register */
+
+#define MPFS_EMMCSD_SRS15_PVE           (1 << 31)
+#define MPFS_EMMCSD_SRS15_A64B          (1 << 29)
+#define MPFS_EMMCSD_SRS15_HV4E          (1 << 28)
+#define MPFS_EMMCSD_SRS15_SCS           (1 << 23)
+#define MPFS_EMMCSD_SRS15_EXTNG         (1 << 22)
+#define MPFS_EMMCSD_SRS15_DSS           (0x3 << 20)
+#define MPFS_EMMCSD_SRS15_V18SE         (1 << 19)
+#define MPFS_EMMCSD_SRS15_UMS           (0x7 << 16)
+#define MPFS_EMMCSD_SRS15_CNIACE        (1 << 7)
+#define MPFS_EMMCSD_SRS15_ACRE          (1 << 5)
+#define MPFS_EMMCSD_SRS15_ACIE          (1 << 4)
+#define MPFS_EMMCSD_SRS15_ACEBE         (1 << 3)
+#define MPFS_EMMCSD_SRS15_ACCE          (1 << 2)
+#define MPFS_EMMCSD_SRS15_ACTE          (1 << 1)
+#define MPFS_EMMCSD_SRS15_ACNE          (1 << 0)
+
+/* SRS16 register */
+
+#define MPFS_EMMCSD_SRS16_SLT           (0x3 << 30)
+#define MPFS_EMMCSD_SRS16_AIS           (1 << 29)
+#define MPFS_EMMCSD_SRS16_A64S          (1 << 28)
+#define MPFS_EMMCSD_SRS16_HWINIT1       (1 << 27)
+#define MPFS_EMMCSD_SRS16_VS18          (1 << 26)
+#define MPFS_EMMCSD_SRS16_VS30          (1 << 25)
+#define MPFS_EMMCSD_SRS16_VS33          (1 << 24)
+#define MPFS_EMMCSD_SRS16_SRS           (1 << 23)
+#define MPFS_EMMCSD_SRS16_DMAS          (1 << 22)
+#define MPFS_EMMCSD_SRS16_HSS           (1 << 21)
+#define MPFS_EMMCSD_SRS16_ADMA1S        (1 << 20)
+#define MPFS_EMMCSD_SRS16_ADMA2S        (1 << 19)
+#define MPFS_EMMCSD_SRS16_EDS8          (1 << 18)
+#define MPFS_EMMCSD_SRS16_MBL           (0x3 << 16)
+#define MPFS_EMMCSD_SRS16_BCSDCLK       (0xff << 8)
+#define MPFS_EMMCSD_SRS16_TCU           (1 << 7)
+#define MPFS_EMMCSD_SRS16_HWINIT0       (1 << 6)
+#define MPFS_EMMCSD_SRS16_TCF           (0x3f << 0)
+
+/* SRS17 register */
+
+#define MPFS_EMMCSD_SRS17_HWINIT3       (0x7 << 29)
+#define MPFS_EMMCSD_SRS17_VDD2S         (1 << 28)
+#define MPFS_EMMCSD_SRS17_HWINIT2       (0xf << 24)
+#define MPFS_EMMCSD_SRS17_CLKMPR        (0xff << 16)
+#define MPFS_EMMCSD_SRS17_RTNGM         (0x3 << 14)
+#define MPFS_EMMCSD_SRS17_UTSM50        (1 << 13)
+#define MPFS_EMMCSD_SRS17_HWINIT1       (1 << 12)
+#define MPFS_EMMCSD_SRS17_RTNGCNT       (0xf << 8)
+#define MPFS_EMMCSD_SRS17_HWINIT0       (1 << 7)
+#define MPFS_EMMCSD_SRS17_DRVD          (1 << 6)
+#define MPFS_EMMCSD_SRS17_DRVC          (1 << 5)
+#define MPFS_EMMCSD_SRS17_DRVA          (1 << 4)
+#define MPFS_EMMCSD_SRS17_UHSII         (1 << 3)
+#define MPFS_EMMCSD_SRS17_DDR50         (1 << 2)
+#define MPFS_EMMCSD_SRS17_SDR104        (1 << 1)
+#define MPFS_EMMCSD_SRS17_SDR50         (1 << 0)
+
+/* SRS18 register */
+
+#define MPFS_EMMCSD_SRS18_HWINIT0       (0xff << 24)
+#define MPFS_EMMCSD_SRS18_MC18          (0xff << 16)
+#define MPFS_EMMCSD_SRS18_MC30          (0xff << 8)
+#define MPFS_EMMCSD_SRS18_MC33          (0xff << 0)
+
+/* SRS19 register */
+
+#define MPFS_EMMCSD_SRS19_HWINIT0       (0xffffff << 8)
+#define MPFS_EMMCSD_SRS19_MC18V2        (0xff << 0)
+
+/* SRS20 register */
+
+#define MPFS_EMMCSD_SRS20_ERESP_FE      (1 << 27)
+#define MPFS_EMMCSD_SRS20_ETUNE_FE      (1 << 26)
+#define MPFS_EMMCSD_SRS20_EADMA_FE      (1 << 25)
+#define MPFS_EMMCSD_SRS20_EAC_FE        (1 << 24)
+#define MPFS_EMMCSD_SRS20_ECL_FE        (1 << 23)
+#define MPFS_EMMCSD_SRS20_EDEB_FE       (1 << 22)
+#define MPFS_EMMCSD_SRS20_EDCRC_FE      (1 << 21)
+#define MPFS_EMMCSD_SRS20_EDT_FE        (1 << 20)
+#define MPFS_EMMCSD_SRS20_ECI_FE        (1 << 19)
+#define MPFS_EMMCSD_SRS20_ECEB_FE       (1 << 18)
+#define MPFS_EMMCSD_SRS20_ECCRC_FE      (1 << 17)
+#define MPFS_EMMCSD_SRS20_ECT_FE        (1 << 16)
+#define MPFS_EMMCSD_SRS20_CNIACE_FE     (1 << 7)
+#define MPFS_EMMCSD_SRS20_ACIE_FE       (1 << 4)
+#define MPFS_EMMCSD_SRS20_ACEBE_FE      (1 << 3)
+#define MPFS_EMMCSD_SRS20_ACCE_FE       (1 << 2)
+#define MPFS_EMMCSD_SRS20_ACTE_FE       (1 << 1)
+#define MPFS_EMMCSD_SRS20_ACNE_FE       (1 << 0)
+
+/* SRS21 register */
+
+#define MPFS_EMMCSD_SRS21_EADMAL        (1 << 2)
+#define MPFS_EMMCSD_SRS21_EADMAS        (0x3 << 0)
+
+/* SRS24 register */
+
+#define MPFS_EMMCSD_SRS24_DSSPV_31_30   (0x3 << 30)
+#define MPFS_EMMCSD_SRS24_HWINIT1       (0xf << 26)
+#define MPFS_EMMCSD_SRS24_SDCFSPV_25_16 (0x3ff << 16)
+#define MPFS_EMMCSD_SRS24_HWINIT0       (0xffff << 0)
+
+/* SRS25 register */
+
+#define MPFS_EMMCSD_SRS25_DSSPV_31_30   (0x3 << 30)
+#define MPFS_EMMCSD_SRS25_HWINIT1       (0xf << 26)
+#define MPFS_EMMCSD_SRS25_SDCFSPV_25_16 (0x3ff << 16)
+#define MPFS_EMMCSD_SRS25_DSSPV_15_14   (0x3 << 14)
+#define MPFS_EMMCSD_SRS25_HWINIT0       (0xf << 10)
+#define MPFS_EMMCSD_SRS25_SDCFSPV_09_00 (0x3ff << 0)
+
+/* SRS26 register */
+
+#define MPFS_EMMCSD_SRS26_DSSPV_31_30   (0x3 << 30)
+#define MPFS_EMMCSD_SRS26_HWINIT1       (0xf << 26)
+#define MPFS_EMMCSD_SRS26_SDCFSPV_25_16 (0x3ff << 16)
+#define MPFS_EMMCSD_SRS26_DSSPV_15_14   (0x3 << 14)
+#define MPFS_EMMCSD_SRS26_HWINIT0       (0x7 << 11)
+#define MPFS_EMMCSD_SRS26_CGSPV_10      (1 << 10)
+#define MPFS_EMMCSD_SRS26_SDCFSPV_09_00 (0x3ff << 0)
+
+/* SRS27 register */
+
+#define MPFS_EMMCSD_SRS27_DSSPV_31_30   (0x3 << 30)
+#define MPFS_EMMCSD_SRS27_HWINIT1       (0xf << 26)
+#define MPFS_EMMCSD_SRS27_SDCFSPV_25_16 (0x3ff << 16)
+#define MPFS_EMMCSD_SRS27_DSSPV_15_14   (0x3 << 14)
+#define MPFS_EMMCSD_SRS27_HWINIT0       (0xf << 10)
+#define MPFS_EMMCSD_SRS27_SDCFSPV_09_00 (0x3ff << 0)
+
+/* SRS29 register */
+
+#define MPFS_EMMCSD_SRS29_HWINIT1       (0xffff << 16)
+#define MPFS_EMMCSD_SRS29_DSSPV_15_14   (0x3 << 14)
+#define MPFS_EMMCSD_SRS29_HWINIT0       (0xf << 10)
+#define MPFS_EMMCSD_SRS29_SDCFSPV_09_00 (0x3ff << 0)
+
+/* CQRS00 register */
+
+#define MPFS_EMMCSD_CQRS00_CQVN1        (0xf << 8)
+#define MPFS_EMMCSD_CQRS00_CQVN2        (0xf << 4)
+#define MPFS_EMMCSD_CQRS00_CQVN3        (0xf << 0)
+
+/* CQRS01 register */
+
+#define MPFS_EMMCSD_CQRS01_ITCFMUL      (0xf << 12)
+#define MPFS_EMMCSD_CQRS01_ITCFVAL      (0x3ff << 0)
+
+/* CQRS02 register */
+
+#define MPFS_EMMCSD_CQRS02_CQDCE        (1 << 12)
+#define MPFS_EMMCSD_CQRS02_CQTDS        (1 << 8)
+#define MPFS_EMMCSD_CQRS02_CQE          (1 << 0)
+
+/* CQRS03 register */
+
+#define MPFS_EMMCSD_CQRS03_CQCAT        (1 << 8)
+#define MPFS_EMMCSD_CQRS03_CQHLT        (1 << 0)
+
+/* CQRS04 register */
+
+#define MPFS_EMMCSD_CQRS04_CQTCL        (1 << 3)
+#define MPFS_EMMCSD_CQRS04_CQREDI       (1 << 2)
+#define MPFS_EMMCSD_CQRS04_CQTCC        (1 << 1)
+#define MPFS_EMMCSD_CQRS04_CQHAC        (1 << 0)
+
+/* CQRS05 register */
+
+#define MPFS_EMMCSD_CQRS05_CQTCLST      (1 << 3)
+#define MPFS_EMMCSD_CQRS05_CQREDST      (1 << 2)
+#define MPFS_EMMCSD_CQRS05_CQTCCST      (1 << 1)
+#define MPFS_EMMCSD_CQRS05_CQHACST      (1 << 0)
+
+/* CQRS06 register */
+
+#define MPFS_EMMCSD_CQRS06_CQTCLSI      (1 << 3)
+#define MPFS_EMMCSD_CQRS06_CQREDSI      (1 << 2)
+#define MPFS_EMMCSD_CQRS06_CQTCCSI      (1 << 1)
+#define MPFS_EMMCSD_CQRS06_CQHACSI      (1 << 0)
+
+/* CQRS07 register */
+
+#define MPFS_EMMCSD_CQRS07_CQICED       (1 << 31)
+#define MPFS_EMMCSD_CQRS07_CQICSB       (1 << 20)
+#define MPFS_EMMCSD_CQRS07_CQICCTR      (1 << 16)
+#define MPFS_EMMCSD_CQRS07_CQICCTHWEN   (1 << 15)
+#define MPFS_EMMCSD_CQRS07_CQICCTH      (0x1f << 8)
+#define MPFS_EMMCSD_CQRS07_CQICTOVALEN  (1 << 7)
+#define MPFS_EMMCSD_CQRS07_CQICTOVAL    (0x7f << 0)
+
+/* CQRS10 register */
+
+#define MPFS_EMMCSD_CQRS10_CQTD31       (1 << 31)
+#define MPFS_EMMCSD_CQRS10_CQTD30       (1 << 30)
+#define MPFS_EMMCSD_CQRS10_CQTD29       (1 << 29)
+#define MPFS_EMMCSD_CQRS10_CQTD28       (1 << 28)
+#define MPFS_EMMCSD_CQRS10_CQTD27       (1 << 27)
+#define MPFS_EMMCSD_CQRS10_CQTD26       (1 << 26)
+#define MPFS_EMMCSD_CQRS10_CQTD25       (1 << 25)
+#define MPFS_EMMCSD_CQRS10_CQTD24       (1 << 24)
+#define MPFS_EMMCSD_CQRS10_CQTD23       (1 << 23)
+#define MPFS_EMMCSD_CQRS10_CQTD22       (1 << 22)
+#define MPFS_EMMCSD_CQRS10_CQTD21       (1 << 21)
+#define MPFS_EMMCSD_CQRS10_CQTD20       (1 << 20)
+#define MPFS_EMMCSD_CQRS10_CQTD19       (1 << 19)
+#define MPFS_EMMCSD_CQRS10_CQTD18       (1 << 18)
+#define MPFS_EMMCSD_CQRS10_CQTD17       (1 << 17)
+#define MPFS_EMMCSD_CQRS10_CQTD16       (1 << 16)
+#define MPFS_EMMCSD_CQRS10_CQTD15       (1 << 15)
+#define MPFS_EMMCSD_CQRS10_CQTD14       (1 << 14)
+#define MPFS_EMMCSD_CQRS10_CQTD13       (1 << 13)
+#define MPFS_EMMCSD_CQRS10_CQTD12       (1 << 12)
+#define MPFS_EMMCSD_CQRS10_CQTD11       (1 << 11)
+#define MPFS_EMMCSD_CQRS10_CQTD10       (1 << 10)
+#define MPFS_EMMCSD_CQRS10_CQTD09       (1 << 9)
+#define MPFS_EMMCSD_CQRS10_CQTD08       (1 << 8)
+#define MPFS_EMMCSD_CQRS10_CQTD07       (1 << 7)
+#define MPFS_EMMCSD_CQRS10_CQTD06       (1 << 6)
+#define MPFS_EMMCSD_CQRS10_CQTD05       (1 << 5)
+#define MPFS_EMMCSD_CQRS10_CQTD04       (1 << 4)
+#define MPFS_EMMCSD_CQRS10_CQTD03       (1 << 3)
+#define MPFS_EMMCSD_CQRS10_CQTD02       (1 << 2)
+#define MPFS_EMMCSD_CQRS10_CQTD01       (1 << 1)
+#define MPFS_EMMCSD_CQRS10_CQTD00       (1 << 0)
+
+/* CQRS11 register */
+
+#define MPFS_EMMCSD_CQRS11_CQTCN31      (1 << 31)
+#define MPFS_EMMCSD_CQRS11_CQTCN30      (1 << 30)
+#define MPFS_EMMCSD_CQRS11_CQTCN29      (1 << 29)
+#define MPFS_EMMCSD_CQRS11_CQTCN28      (1 << 28)
+#define MPFS_EMMCSD_CQRS11_CQTCN27      (1 << 27)
+#define MPFS_EMMCSD_CQRS11_CQTCN26      (1 << 26)
+#define MPFS_EMMCSD_CQRS11_CQTCN25      (1 << 25)
+#define MPFS_EMMCSD_CQRS11_CQTCN24      (1 << 24)
+#define MPFS_EMMCSD_CQRS11_CQTCN23      (1 << 23)
+#define MPFS_EMMCSD_CQRS11_CQTCN22      (1 << 22)
+#define MPFS_EMMCSD_CQRS11_CQTCN21      (1 << 21)
+#define MPFS_EMMCSD_CQRS11_CQTCN20      (1 << 20)
+#define MPFS_EMMCSD_CQRS11_CQTCN19      (1 << 19)
+#define MPFS_EMMCSD_CQRS11_CQTCN18      (1 << 18)
+#define MPFS_EMMCSD_CQRS11_CQTCN17      (1 << 17)
+#define MPFS_EMMCSD_CQRS11_CQTCN16      (1 << 16)
+#define MPFS_EMMCSD_CQRS11_CQTCN15      (1 << 15)
+#define MPFS_EMMCSD_CQRS11_CQTCN14      (1 << 14)
+#define MPFS_EMMCSD_CQRS11_CQTCN13      (1 << 13)
+#define MPFS_EMMCSD_CQRS11_CQTCN12      (1 << 12)
+#define MPFS_EMMCSD_CQRS11_CQTCN11      (1 << 11)
+#define MPFS_EMMCSD_CQRS11_CQTCN10      (1 << 10)
+#define MPFS_EMMCSD_CQRS11_CQTCN09      (1 << 9)
+#define MPFS_EMMCSD_CQRS11_CQTCN08      (1 << 8)
+#define MPFS_EMMCSD_CQRS11_CQTCN07      (1 << 7)
+#define MPFS_EMMCSD_CQRS11_CQTCN06      (1 << 6)
+#define MPFS_EMMCSD_CQRS11_CQTCN05      (1 << 5)
+#define MPFS_EMMCSD_CQRS11_CQTCN04      (1 << 4)
+#define MPFS_EMMCSD_CQRS11_CQTCN03      (1 << 3)
+#define MPFS_EMMCSD_CQRS11_CQTCN02      (1 << 2)
+#define MPFS_EMMCSD_CQRS11_CQTCN01      (1 << 1)
+#define MPFS_EMMCSD_CQRS11_CQTCN00      (1 << 0)
+
+/* CQRS13 register */
+
+#define MPFS_EMMCSD_CQRS13_CQDPT31      (1 << 31)
+#define MPFS_EMMCSD_CQRS13_CQDPT30      (1 << 30)
+#define MPFS_EMMCSD_CQRS13_CQDPT29      (1 << 29)
+#define MPFS_EMMCSD_CQRS13_CQDPT28      (1 << 28)
+#define MPFS_EMMCSD_CQRS13_CQDPT27      (1 << 27)
+#define MPFS_EMMCSD_CQRS13_CQDPT26      (1 << 26)
+#define MPFS_EMMCSD_CQRS13_CQDPT25      (1 << 25)
+#define MPFS_EMMCSD_CQRS13_CQDPT24      (1 << 24)
+#define MPFS_EMMCSD_CQRS13_CQDPT23      (1 << 23)
+#define MPFS_EMMCSD_CQRS13_CQDPT22      (1 << 22)
+#define MPFS_EMMCSD_CQRS13_CQDPT21      (1 << 21)
+#define MPFS_EMMCSD_CQRS13_CQDPT20      (1 << 20)
+#define MPFS_EMMCSD_CQRS13_CQDPT19      (1 << 19)
+#define MPFS_EMMCSD_CQRS13_CQDPT18      (1 << 18)
+#define MPFS_EMMCSD_CQRS13_CQDPT17      (1 << 17)
+#define MPFS_EMMCSD_CQRS13_CQDPT16      (1 << 16)
+#define MPFS_EMMCSD_CQRS13_CQDPT15      (1 << 15)
+#define MPFS_EMMCSD_CQRS13_CQDPT14      (1 << 14)
+#define MPFS_EMMCSD_CQRS13_CQDPT13      (1 << 13)
+#define MPFS_EMMCSD_CQRS13_CQDPT12      (1 << 12)
+#define MPFS_EMMCSD_CQRS13_CQDPT11      (1 << 11)
+#define MPFS_EMMCSD_CQRS13_CQDPT10      (1 << 10)
+#define MPFS_EMMCSD_CQRS13_CQDPT09      (1 << 9)
+#define MPFS_EMMCSD_CQRS13_CQDPT08      (1 << 8)
+#define MPFS_EMMCSD_CQRS13_CQDPT07      (1 << 7)
+#define MPFS_EMMCSD_CQRS13_CQDPT06      (1 << 6)
+#define MPFS_EMMCSD_CQRS13_CQDPT05      (1 << 5)
+#define MPFS_EMMCSD_CQRS13_CQDPT04      (1 << 4)
+#define MPFS_EMMCSD_CQRS13_CQDPT03      (1 << 3)
+#define MPFS_EMMCSD_CQRS13_CQDPT02      (1 << 2)
+#define MPFS_EMMCSD_CQRS13_CQDPT01      (1 << 1)
+#define MPFS_EMMCSD_CQRS13_CQDPT00      (1 << 0)
+
+/* CQRS14 register */
+
+#define MPFS_EMMCSD_CQRS14_CQTC31      (1 << 31)
+#define MPFS_EMMCSD_CQRS14_CQTC30      (1 << 30)
+#define MPFS_EMMCSD_CQRS14_CQTC29      (1 << 29)
+#define MPFS_EMMCSD_CQRS14_CQTC28      (1 << 28)
+#define MPFS_EMMCSD_CQRS14_CQTC27      (1 << 27)
+#define MPFS_EMMCSD_CQRS14_CQTC26      (1 << 26)
+#define MPFS_EMMCSD_CQRS14_CQTC25      (1 << 25)
+#define MPFS_EMMCSD_CQRS14_CQTC24      (1 << 24)
+#define MPFS_EMMCSD_CQRS14_CQTC23      (1 << 23)
+#define MPFS_EMMCSD_CQRS14_CQTC22      (1 << 22)
+#define MPFS_EMMCSD_CQRS14_CQTC21      (1 << 21)
+#define MPFS_EMMCSD_CQRS14_CQTC20      (1 << 20)
+#define MPFS_EMMCSD_CQRS14_CQTC19      (1 << 19)
+#define MPFS_EMMCSD_CQRS14_CQTC18      (1 << 18)
+#define MPFS_EMMCSD_CQRS14_CQTC17      (1 << 17)
+#define MPFS_EMMCSD_CQRS14_CQTC16      (1 << 16)
+#define MPFS_EMMCSD_CQRS14_CQTC15      (1 << 15)
+#define MPFS_EMMCSD_CQRS14_CQTC14      (1 << 14)
+#define MPFS_EMMCSD_CQRS14_CQTC13      (1 << 13)
+#define MPFS_EMMCSD_CQRS14_CQTC12      (1 << 12)
+#define MPFS_EMMCSD_CQRS14_CQTC11      (1 << 11)
+#define MPFS_EMMCSD_CQRS14_CQTC10      (1 << 10)
+#define MPFS_EMMCSD_CQRS14_CQTC09      (1 << 9)
+#define MPFS_EMMCSD_CQRS14_CQTC08      (1 << 8)
+#define MPFS_EMMCSD_CQRS14_CQTC07      (1 << 7)
+#define MPFS_EMMCSD_CQRS14_CQTC06      (1 << 6)
+#define MPFS_EMMCSD_CQRS14_CQTC05      (1 << 5)
+#define MPFS_EMMCSD_CQRS14_CQTC04      (1 << 4)
+#define MPFS_EMMCSD_CQRS14_CQTC03      (1 << 3)
+#define MPFS_EMMCSD_CQRS14_CQTC02      (1 << 2)
+#define MPFS_EMMCSD_CQRS14_CQTC01      (1 << 1)
+#define MPFS_EMMCSD_CQRS14_CQTC00      (1 << 0)
+
+/* CQRS16 register */
+
+#define MPFS_EMMCSD_CQRS16_CQSSCBC     (0xf << 16)
+#define MPFS_EMMCSD_CQRS16_CQSSCIT     (0xffff << 0)
+
+/* CQRS21 register */
+
+#define MPFS_EMMCSD_CQRS21_CQDTEFV     (1 << 31)
+#define MPFS_EMMCSD_CQRS21_CQDTETID    (0x1f << 24)
+#define MPFS_EMMCSD_CQRS21_CQDTECI     (0x3f << 16)
+#define MPFS_EMMCSD_CQRS21_CQRMEFV     (1 << 15)
+#define MPFS_EMMCSD_CQRS21_CQRMETID    (0x1f << 8)
+#define MPFS_EMMCSD_CQRS21_CQRMECI     (0x3f << 0)
+
+/* CQRS22 register */
+
+#define MPFS_EMMCSD_CQRS22_CQLCRI      (0x3f << 0)
+
+#endif /* __ARCH_RISCV_SRC_MPFS_HARDWARE_MPFS_EMMCSD_H */
diff --git a/arch/risc-v/src/mpfs/mpfs_emmcsd.c b/arch/risc-v/src/mpfs/mpfs_emmcsd.c
new file mode 100755
index 0000000..82a182a
--- /dev/null
+++ b/arch/risc-v/src/mpfs/mpfs_emmcsd.c
@@ -0,0 +1,2966 @@
+/****************************************************************************
+ * arch/risc-v/src/mpfs/mpfs_emmcsd.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <assert.h>
+#include <debug.h>
+#include <errno.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/wdog.h>
+#include <nuttx/clock.h>
+#include <nuttx/sdio.h>
+#include <nuttx/wqueue.h>
+#include <nuttx/semaphore.h>
+#include <nuttx/signal.h>
+#include <nuttx/mmcsd.h>
+#include <nuttx/irq.h>
+#include <nuttx/cache.h>
+
+#include <arch/board/board.h>
+
+#include "mpfs_emmcsd.h"
+#include "riscv_arch.h"
+#include "hardware/mpfs_emmcsd.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define MPFS_EMMCSD_HRS00      (priv->hw_base + MPFS_EMMCSD_HRS00_OFFSET)
+#define MPFS_EMMCSD_HRS01      (priv->hw_base + MPFS_EMMCSD_HRS01_OFFSET)
+#define MPFS_EMMCSD_HRS04      (priv->hw_base + MPFS_EMMCSD_HRS04_OFFSET)
+#define MPFS_EMMCSD_HRS06      (priv->hw_base + MPFS_EMMCSD_HRS06_OFFSET)
+
+#define MPFS_EMMCSD_SRS01      (priv->hw_base + MPFS_EMMCSD_SRS01_OFFSET)
+#define MPFS_EMMCSD_SRS02      (priv->hw_base + MPFS_EMMCSD_SRS02_OFFSET)
+#define MPFS_EMMCSD_SRS03      (priv->hw_base + MPFS_EMMCSD_SRS03_OFFSET)
+#define MPFS_EMMCSD_SRS04      (priv->hw_base + MPFS_EMMCSD_SRS04_OFFSET)
+#define MPFS_EMMCSD_SRS05      (priv->hw_base + MPFS_EMMCSD_SRS05_OFFSET)
+#define MPFS_EMMCSD_SRS06      (priv->hw_base + MPFS_EMMCSD_SRS06_OFFSET)
+#define MPFS_EMMCSD_SRS07      (priv->hw_base + MPFS_EMMCSD_SRS07_OFFSET)
+#define MPFS_EMMCSD_SRS08      (priv->hw_base + MPFS_EMMCSD_SRS08_OFFSET)
+#define MPFS_EMMCSD_SRS09      (priv->hw_base + MPFS_EMMCSD_SRS09_OFFSET)
+#define MPFS_EMMCSD_SRS10      (priv->hw_base + MPFS_EMMCSD_SRS10_OFFSET)
+#define MPFS_EMMCSD_SRS11      (priv->hw_base + MPFS_EMMCSD_SRS11_OFFSET)
+#define MPFS_EMMCSD_SRS12      (priv->hw_base + MPFS_EMMCSD_SRS12_OFFSET)
+#define MPFS_EMMCSD_SRS13      (priv->hw_base + MPFS_EMMCSD_SRS13_OFFSET)
+#define MPFS_EMMCSD_SRS14      (priv->hw_base + MPFS_EMMCSD_SRS14_OFFSET)
+#define MPFS_EMMCSD_SRS15      (priv->hw_base + MPFS_EMMCSD_SRS15_OFFSET)
+#define MPFS_EMMCSD_SRS16      (priv->hw_base + MPFS_EMMCSD_SRS16_OFFSET)
+#define MPFS_EMMCSD_SRS21      (priv->hw_base + MPFS_EMMCSD_SRS21_OFFSET)
+#define MPFS_EMMCSD_SRS22      (priv->hw_base + MPFS_EMMCSD_SRS22_OFFSET)
+#define MPFS_EMMCSD_SRS23      (priv->hw_base + MPFS_EMMCSD_SRS23_OFFSET)
+
+#define MPFS_SYSREG_SOFT_RESET_CR     (MPFS_SYSREG_BASE + \
+                                       MPFS_SYSREG_SOFT_RESET_CR_OFFSET)
+#define MPFS_SYSREG_SUBBLK_CLOCK_CR   (MPFS_SYSREG_BASE + \
+                                       MPFS_SYSREG_SUBBLK_CLOCK_CR_OFFSET)
+
+#define MPFS_PMPCFG_MMC_0             (MPFS_MPUCFG_BASE + 0x700)
+#define MPFS_PMPCFG_MMC_1             (MPFS_MPUCFG_BASE + 0x708)
+#define MPFS_PMPCFG_MMC_2             (MPFS_MPUCFG_BASE + 0x710)
+#define MPFS_PMPCFG_MMC_3             (MPFS_MPUCFG_BASE + 0x718)
+
+#define MPFS_MMC_CLOCK_400KHZ              400u
+#define MPFS_MMC_CLOCK_12_5MHZ             12500u
+#define MPFS_MMC_CLOCK_25MHZ               25000u
+#define MPFS_MMC_CLOCK_26MHZ               26000u
+#define MPFS_MMC_CLOCK_50MHZ               50000u
+#define MPFS_MMC_CLOCK_100MHZ              100000u
+#define MPFS_MMC_CLOCK_200MHZ              200000u
+
+#define MPFS_EMMCSD_DEBOUNCE_TIME          0x300000u
+#define MPFS_EMMCSD_MODE_LEGACY            0x7u
+
+#define MPFS_EMMCSD_DATA_TIMEOUT           500000
+
+#define MPFS_EMMCSD_SRS10_3_3V_BUS_VOLTAGE (0x7 << 9)
+#define MPFS_EMMCSD_SRS10_3_0V_BUS_VOLTAGE (0x6 << 9)
+#define MPFS_EMMCSD_SRS10_1_8V_BUS_VOLTAGE (0x5 << 9)
+
+#define MPFS_EMMCSD_1_8V_BUS_VOLTAGE       18
+#define MPFS_EMMCSD_3_3V_BUS_VOLTAGE       33
+
+#define MPFS_EMMCSD_INITIALIZED            0x00
+#define MPFS_EMMCSD_NOT_INITIALIZED        0x01
+
+#ifndef CONFIG_SCHED_WORKQUEUE
+#  error "Callback support requires CONFIG_SCHED_WORKQUEUE"
+#endif
+
+/* High-speed single data rate supports clock frequency up to 52 MHz and data
+ * bus width of 1 bit, 4 bits, and 8 bits.
+ */
+
+#define MPFS_EMMCSD_MODE_SDR               0x2u
+
+/* High speed double data rate supports clock frequency up to 52 MHz and data
+ * bus width of 4 bits and 8 bits.
+ */
+
+#define MPFS_EMMCSD_MODE_DDR               0x3u
+
+/* SDR data sampling supports clock frequency up to 200 MHz and data bus
+ * width of 4 bits and 8 bits.
+ */
+
+#define MPFS_EMMCSD_MODE_HS200             0x4u
+
+/* DDR data sampling supports clock frequency up to 200 MHz and data bus
+ * width of 8 bits.
+ */
+
+#define MPFS_EMMCSD_MODE_HS400             0x5u
+
+/* HS400 mode with Enhanced Strobe */
+
+#define MPFS_EMMCSD_MODE_HS400_ES          0x6u
+
+/* Define the Hardware FIFO size */
+
+#define FIFO_SIZE_IN_BYTES                 64
+
+/* Timing */
+
+#define EMMCSD_CMDTIMEOUT                  (100000)
+#define EMMCSD_LONGTIMEOUT                 (100000000)
+
+/* Event waiting interrupt mask bits */
+
+#define MPFS_EMMCSD_CARD_INTS     (MPFS_EMMCSD_SRS14_CINT_IE   | \
+                                   MPFS_EMMCSD_SRS14_CIN_IE    | \
+                                   MPFS_EMMCSD_SRS14_CR_IE)
+
+#define MPFS_EMMCSD_CMDDONE_STA   (MPFS_EMMCSD_SRS12_CC)
+
+#define MPFS_EMMCSD_RESPDONE_STA  (MPFS_EMMCSD_SRS12_ECT       | \
+                                   MPFS_EMMCSD_SRS12_ECCRC)
+
+#define MPFS_EMMCSD_XFRDONE_STA   (MPFS_EMMCSD_SRS12_TC)
+
+#define MPFS_EMMCSD_CMDDONE_MASK  (MPFS_EMMCSD_CARD_INTS       | \
+                                   MPFS_EMMCSD_SRS14_CC_IE)
+
+#define MPFS_EMMCSD_RESPDONE_MASK (MPFS_EMMCSD_CARD_INTS       | \
+                                   MPFS_EMMCSD_SRS14_ECCRC_IE  | \
+                                   MPFS_EMMCSD_SRS14_ECT_IE)
+
+#define MPFS_EMMCSD_XFRDONE_MASK  (MPFS_EMMCSD_CARD_INTS       | \
+                                   MPFS_EMMCSD_SRS14_TC_IE)
+
+#define MPFS_EMMCSD_CMDDONE_ICR   (MPFS_EMMCSD_SRS12_CC)
+
+#define MPFS_EMMCSD_RESPDONE_ICR  (MPFS_EMMCSD_SRS12_ECT       | \
+                                   MPFS_EMMCSD_SRS12_ECCRC)
+
+#define MPFS_EMMCSD_XFRDONE_ICR   (MPFS_EMMCSD_SRS12_EDCRC     | \
+                                   MPFS_EMMCSD_SRS12_EDT       | \
+                                   MPFS_EMMCSD_SRS12_TC)
+
+#define MPFS_EMMCSD_WAITALL_ICR   (MPFS_EMMCSD_CMDDONE_ICR     | \
+                                   MPFS_EMMCSD_RESPDONE_ICR    | \
+                                   MPFS_EMMCSD_XFRDONE_ICR)
+
+#define MPFS_EMMCSD_RECV_MASKDMA  (MPFS_EMMCSD_CARD_INTS       | \
+                                   MPFS_EMMCSD_SRS14_EADMA_IE  | \
+                                   MPFS_EMMCSD_SRS14_DMAINT_IE | \
+                                   MPFS_EMMCSD_SRS14_EDT_IE    | \
+                                   MPFS_EMMCSD_SRS14_ECT_IE    | \
+                                   MPFS_EMMCSD_SRS14_BRR_IE    | \
+                                   MPFS_EMMCSD_SRS14_TC_IE)
+
+#define MPFS_EMMCSD_RECV_MASK     (MPFS_EMMCSD_CARD_INTS       | \
+                                   MPFS_EMMCSD_SRS14_EDT_IE    | \
+                                   MPFS_EMMCSD_SRS14_ECT_IE    | \
+                                   MPFS_EMMCSD_SRS14_BRR_IE    | \
+                                   MPFS_EMMCSD_SRS14_TC_IE)
+
+#define MPFS_EMMCSD_SEND_MASKDMA  (MPFS_EMMCSD_CARD_INTS       | \
+                                   MPFS_EMMCSD_SRS14_EADMA_IE  | \
+                                   MPFS_EMMCSD_SRS14_DMAINT_IE | \
+                                   MPFS_EMMCSD_SRS14_EDT_IE    | \
+                                   MPFS_EMMCSD_SRS14_ECT_IE    | \
+                                   MPFS_EMMCSD_SRS14_BWR_IE    | \
+                                   MPFS_EMMCSD_SRS14_TC_IE)
+
+#define MPFS_EMMCSD_SEND_MASK     (MPFS_EMMCSD_CARD_INTS       | \
+                                   MPFS_EMMCSD_SRS14_EDT_IE    | \
+                                   MPFS_EMMCSD_SRS14_ECT_IE    | \
+                                   MPFS_EMMCSD_SRS14_BWR_IE    | \
+                                   MPFS_EMMCSD_SRS14_TC_IE)
+
+/* SD-Card IOMUX */
+
+#define LIBERO_SETTING_IOMUX1_CR_SD                     0x00000000UL
+#define LIBERO_SETTING_IOMUX2_CR_SD                     0x00000000UL
+#define LIBERO_SETTING_IOMUX6_CR_SD                     0x0000001DUL
+#define LIBERO_SETTING_MSSIO_BANK4_CFG_CR_SD            0x00080907UL
+#define LIBERO_SETTING_MSSIO_BANK4_IO_CFG_0_1_CR_SD     0x08290829UL
+#define LIBERO_SETTING_MSSIO_BANK4_IO_CFG_2_3_CR_SD     0x08290829UL
+#define LIBERO_SETTING_MSSIO_BANK4_IO_CFG_4_5_CR_SD     0x08290829UL
+#define LIBERO_SETTING_MSSIO_BANK4_IO_CFG_6_7_CR_SD     0x08290829UL
+#define LIBERO_SETTING_MSSIO_BANK4_IO_CFG_8_9_CR_SD     0x08290829UL
+#define LIBERO_SETTING_MSSIO_BANK4_IO_CFG_10_11_CR_SD   0x08290829UL
+#define LIBERO_SETTING_MSSIO_BANK4_IO_CFG_12_13_CR_SD   0x08290829UL
+
+/* eMMC / SD switch address */
+
+#define SDIO_REGISTER_ADDRESS                           0x4f000000
+
+#define MPFS_SYSREG_IOMUX1   (MPFS_SYSREG_BASE + \
+                              MPFS_SYSREG_IOMUX1_CR_OFFSET)
+#define MPFS_SYSREG_IOMUX2   (MPFS_SYSREG_BASE + \
+                              MPFS_SYSREG_IOMUX2_CR_OFFSET)
+#define MPFS_SYSREG_IOMUX6   (MPFS_SYSREG_BASE + \
+                              MPFS_SYSREG_IOMUX6_CR_OFFSET)
+#define MPFS_SYSREG_B4_CFG   (MPFS_SYSREG_BASE + \
+                              MPFS_SYSREG_MSSIO_BANK4_CFG_CR)
+#define MPFS_SYSREG_B4_0_1   (MPFS_SYSREG_BASE + \
+                              MPFS_SYSREG_MSSIO_BANK4_IO_CFG_0_1_CR_OFFSET)
+#define MPFS_SYSREG_B4_2_3   (MPFS_SYSREG_BASE + \
+                              MPFS_SYSREG_MSSIO_BANK4_IO_CFG_2_3_CR_OFFSET)
+#define MPFS_SYSREG_B4_4_5   (MPFS_SYSREG_BASE + \
+                              MPFS_SYSREG_MSSIO_BANK4_IO_CFG_4_5_CR_OFFSET)
+#define MPFS_SYSREG_B4_6_7   (MPFS_SYSREG_BASE + \
+                              MPFS_SYSREG_MSSIO_BANK4_IO_CFG_6_7_CR_OFFSET)
+#define MPFS_SYSREG_B4_8_9   (MPFS_SYSREG_BASE + \
+                              MPFS_SYSREG_MSSIO_BANK4_IO_CFG_8_9_CR_OFFSET)
+#define MPFS_SYSREG_B4_10_11 (MPFS_SYSREG_BASE + \
+                              MPFS_SYSREG_MSSIO_BANK4_IO_CFG_10_11_CR_OFFSET)
+#define MPFS_SYSREG_4_12_13  (MPFS_SYSREG_BASE + \
+                              MPFS_SYSREG_MSSIO_BANK4_IO_CFG_12_13_CR_OFFSET)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* This structure defines the state of the MPFS eMMCSD interface */
+
+struct mpfs_dev_s
+{
+  struct sdio_dev_s  dev;             /* Standard, base SDIO interface */
+
+  uintptr_t          hw_base;         /* Base address */
+  int                plic_irq;        /* PLIC interrupt */
+  bool               clk_enabled;     /* Clk state */
+
+  /* eMMC / SD and HW parameters */
+
+  bool               emmc;            /* eMMC or SD */
+  int                bus_voltage;     /* Bus voltage */
+  int                bus_speed;       /* Bus speed */
+  bool               jumpers_3v3;     /* Jumper settings: 1v8 or 3v3 */
+
+  /* Event support */
+
+  sem_t              waitsem;         /* Implements event waiting */
+  sdio_eventset_t    waitevents;      /* Set of events to be waited for */
+  uint32_t           waitmask;        /* Interrupt enables for event waiting */
+  volatile sdio_eventset_t wkupevent; /* The event that caused the wakeup */
+  struct wdog_s      waitwdog;        /* Watchdog that handles event timeouts */
+
+  /* Callback support */
+
+  sdio_statset_t     cdstatus;        /* Card status */
+  sdio_eventset_t    cbevents;        /* Set of events to be cause callbacks */
+  worker_t           callback;        /* Registered callback function */
+  void              *cbarg;           /* Registered callback argument */
+  struct work_s      cbwork;          /* Callback work queue structure */
+
+  /* Interrupt mode data transfer support */
+
+  uint32_t          *buffer;          /* Address of current R/W buffer */
+  size_t             remaining;       /* Number of bytes remaining in the transfer */
+  size_t             receivecnt;      /* Real count to receive */
+  uint32_t           xfrmask;         /* Interrupt enables for data transfer */
+
+  bool               widebus;         /* Required for DMA support */
+  bool               onebit;          /* true: Only 1-bit transfers are supported */
+
+  /* DMA data transfer support */
+
+  bool               polltransfer;    /* Indicate a poll transfer, no DMA */
+
+  /* Misc */
+
+  uint32_t           blocksize;       /* Current block size */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* Low-level helper  ********************************************************/
+
+#define     mpfs_givesem(priv) (nxsem_post(&priv->waitsem))
+
+/* Mutual exclusion */
+
+#if defined(CONFIG_SDIO_MUXBUS)
+static int  mpfs_lock(FAR struct sdio_dev_s *dev, bool lock);
+#endif
+
+/* Initialization/setup */
+
+static void mpfs_reset(FAR struct sdio_dev_s *dev);
+static sdio_capset_t mpfs_capabilities(FAR struct sdio_dev_s *dev);
+static sdio_statset_t mpfs_status(FAR struct sdio_dev_s *dev);
+static void mpfs_widebus(FAR struct sdio_dev_s *dev, bool enable);
+static void mpfs_clock(FAR struct sdio_dev_s *dev,
+                       enum sdio_clock_e rate);
+static int  mpfs_attach(FAR struct sdio_dev_s *dev);
+
+/* Command / Status / Data Transfer */
+
+static int  mpfs_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd,
+                         uint32_t arg);
+#ifdef CONFIG_SDIO_BLOCKSETUP
+static void mpfs_blocksetup(FAR struct sdio_dev_s *dev,
+              unsigned int blocksize, unsigned int nblocks);
+#endif
+static int  mpfs_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
+                           size_t nbytes);
+static int  mpfs_sendsetup(FAR struct sdio_dev_s *dev,
+                           FAR const uint8_t *buffer, size_t nbytes);
+static int  mpfs_cancel(FAR struct sdio_dev_s *dev);
+
+static int  mpfs_waitresponse(FAR struct sdio_dev_s *dev, uint32_t cmd);
+static int  mpfs_recvshortcrc(FAR struct sdio_dev_s *dev, uint32_t cmd,
+                              uint32_t *rshort);
+static int  mpfs_recvlong(FAR struct sdio_dev_s *dev, uint32_t cmd,
+                          uint32_t rlong[4]);
+static int  mpfs_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd,
+                           uint32_t *rshort);
+
+/* Event handler */
+
+static void mpfs_waitenable(FAR struct sdio_dev_s *dev,
+                            sdio_eventset_t eventset, uint32_t timeout);
+static sdio_eventset_t mpfs_eventwait(FAR struct sdio_dev_s *dev);
+static void mpfs_callbackenable(FAR struct sdio_dev_s *dev,
+                                sdio_eventset_t eventset);
+static int  mpfs_registercallback(FAR struct sdio_dev_s *dev,
+                                  worker_t callback, void *arg);
+
+/* DMA */
+
+#if defined(CONFIG_SDIO_DMA)
+static int  mpfs_dmarecvsetup(FAR struct sdio_dev_s *dev,
+                              FAR uint8_t *buffer, size_t buflen);
+static int  mpfs_dmasendsetup(FAR struct sdio_dev_s *dev,
+                              FAR const uint8_t *buffer, size_t buflen);
+#endif
+
+/* Initialization/uninitialization/reset ************************************/
+
+static void mpfs_callback(void *arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+struct mpfs_dev_s g_emmcsd_dev =
+{
+  .dev =
+  {
+#if defined(CONFIG_SDIO_MUXBUS)
+    .lock             = mpfs_lock,
+#endif
+    .reset            = mpfs_reset,
+    .capabilities     = mpfs_capabilities,
+    .status           = mpfs_status,
+    .widebus          = mpfs_widebus,
+    .clock            = mpfs_clock,
+    .attach           = mpfs_attach,
+    .sendcmd          = mpfs_sendcmd,
+#ifdef CONFIG_SDIO_BLOCKSETUP
+    .blocksetup       = mpfs_blocksetup,
+#endif
+    .recvsetup        = mpfs_recvsetup,
+    .sendsetup        = mpfs_sendsetup,
+    .cancel           = mpfs_cancel,
+    .waitresponse     = mpfs_waitresponse,
+    .recv_r1          = mpfs_recvshortcrc,
+    .recv_r2          = mpfs_recvlong,
+    .recv_r3          = mpfs_recvshort,
+    .recv_r4          = mpfs_recvshort,
+    .recv_r5          = mpfs_recvshortcrc,
+    .recv_r6          = mpfs_recvshortcrc,
+    .recv_r7          = mpfs_recvshort,
+    .waitenable       = mpfs_waitenable,
+    .eventwait        = mpfs_eventwait,
+    .callbackenable   = mpfs_callbackenable,
+    .registercallback = mpfs_registercallback,
+#if defined(CONFIG_SDIO_DMA)
+    .dmarecvsetup     = mpfs_dmarecvsetup,
+    .dmasendsetup     = mpfs_dmasendsetup,
+#endif
+  },
+  .hw_base           = MPFS_EMMC_SD_BASE,
+  .plic_irq          = MPFS_IRQ_MMC_MAIN,
+  .emmc              = false,
+  .bus_voltage       = MPFS_EMMCSD_3_3V_BUS_VOLTAGE,
+  .bus_speed         = MPFS_EMMCSD_MODE_SDR,
+  .jumpers_3v3       = true,
+  .blocksize         = 512,
+  .onebit            = false,
+  .polltransfer      = true,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: mpfs_takesem
+ *
+ * Description:
+ *   Take the wait semaphore (handling false alarm wakeups due to the receipt
+ *   of signals).
+ *
+ * Input Parameters:
+ *   priv  - Instance of the EMMCSD private state structure.
+ *
+ * Returned Value:
+ *   Normally OK, but may return -ECANCELED in the rare event that the task
+ *   has been canceled.
+ *
+ ****************************************************************************/
+
+static int mpfs_takesem(struct mpfs_dev_s *priv)
+{
+  return nxsem_wait_uninterruptible(&priv->waitsem);
+}
+
+/****************************************************************************
+ * Name: mpfs_reset_lines
+ *
+ * Description:
+ *   Resets the DAT and CMD lines and waits until they are cleared.
+ *
+ * Input Parameters:
+ *   priv  - Instance of the EMMCSD private state structure.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void mpfs_reset_lines(struct mpfs_dev_s *priv)
+{
+  uint32_t retries = EMMCSD_CMDTIMEOUT;
+  uint32_t status;
+
+  /* Software Reset For DAT Line and CMD Line */
+
+  modifyreg32(MPFS_EMMCSD_SRS11, 0, MPFS_EMMCSD_SRS11_SRDAT |
+              MPFS_EMMCSD_SRS11_SRCMD);
+
+  do
+    {
+      status = getreg32(MPFS_EMMCSD_SRS11);
+    }
+  while ((status & (MPFS_EMMCSD_SRS11_SRDAT | MPFS_EMMCSD_SRS11_SRCMD)) &&
+         --retries);
+
+  if (retries == 0)
+    {
+      mcerr("Timeout waiting line resets!\n");
+    }
+}
+
+/****************************************************************************
+ * Name: mpfs_check_lines_busy
+ *
+ * Description:
+ *   Verifies the DAT and CMD lines are available, not busy.
+ *
+ * Input Parameters:
+ *   priv  - Instance of the EMMCSD private state structure.
+ *
+ * Returned Value:
+ *   true if busy, false if available
+ *
+ ****************************************************************************/
+
+static bool mpfs_check_lines_busy(struct mpfs_dev_s *priv)
+{
+  uint32_t retries = EMMCSD_LONGTIMEOUT;
+  uint32_t srs9;
+
+  do
+    {
+      srs9 = getreg32(MPFS_EMMCSD_SRS09);
+    }
+  while (srs9 & (MPFS_EMMCSD_SRS09_CICMD | MPFS_EMMCSD_SRS09_CIDAT) &&
+         --retries);
+
+  if (retries == 0)
+    {
+      mcerr("Lines are still busy!\n");
+      return true;
+    }
+
+  return false;
+}
+
+/****************************************************************************
+ * Name: mpfs_setclkrate
+ *
+ * Description:
+ *   Set the clock rate. Disables the SD clock for the time changing the
+ *   settings, if already enabled.
+ *
+ * Input Parameters:
+ *   priv  - Instance of the EMMCSD private state structure.
+ *   clkcr - New clock rate.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void mpfs_setclkrate(struct mpfs_dev_s *priv, uint32_t clkrate)
+{
+  uint32_t baseclk;
+  uint32_t settings;
+  uint32_t divider;
+  uint32_t clkstable;
+  uint32_t retries = EMMCSD_CMDTIMEOUT;
+  int i;
+
+  mcinfo("clkrate: %08" PRIx32 "\n", clkrate);
+
+  if (clkrate == 0)
+    {
+      modifyreg32(MPFS_EMMCSD_SRS11, MPFS_EMMCSD_SRS11_SDCE, 0);
+      priv->clk_enabled = false;
+      return;
+    }
+
+  baseclk = (getreg32(MPFS_EMMCSD_SRS16) & 0xff00) >> 8;
+  baseclk *= 1000;
+
+  DEBUGASSERT(baseclk != 0);
+
+  /* 10-bit divider, search for match (N*2) */
+
+  for (i = 1; i < 2046; i++)
+    {
+      if (((baseclk / i) < clkrate) || (((baseclk / i) == clkrate) &&
+          ((baseclk % i) == 0u)))
+        {
+          break;
+        }
+    }
+
+  divider = ((i / 2) << 8);
+
+  /* Set SDCLK Frequency Select and Internal Clock Enable */
+
+  settings = (divider & 0xff00u) | ((divider & 0x30000u) >> 10) |
+              MPFS_EMMCSD_SRS11_ICE;
+
+  /* Disable SD clock if enabled */
+
+  if (priv->clk_enabled)
+    {
+      modifyreg32(MPFS_EMMCSD_SRS11, MPFS_EMMCSD_SRS11_SDCE, 0);
+    }
+
+  /* Apply new settings */
+
+  modifyreg32(MPFS_EMMCSD_SRS11, MPFS_EMMCSD_SRS11_SDCFSL |
+              MPFS_EMMCSD_SRS11_SDCFSH | MPFS_EMMCSD_SRS11_ICE,
+              settings);
+
+  /* Wait for stable clock */
+
+  clkstable = getreg32(MPFS_EMMCSD_SRS11);
+  while (!(clkstable & MPFS_EMMCSD_SRS11_ICS) && --retries)
+    {
+      clkstable = getreg32(MPFS_EMMCSD_SRS11);
+    }
+
+  if (retries == 0)
+    {
+      mcwarn("Clock didn't get stable!\n");
+      DEBUGPANIC();
+    }
+
+  /* HSE bit enabled if clk greater than 25 Mhz */
+
+  if (clkrate > MPFS_MMC_CLOCK_25MHZ)
+    {
+      modifyreg32(MPFS_EMMCSD_SRS10, 0, MPFS_EMMCSD_SRS10_HSE);
+    }
+
+  priv->clk_enabled = true;
+  modifyreg32(MPFS_EMMCSD_SRS11, 0, MPFS_EMMCSD_SRS11_SDCE);
+
+  mcinfo("SRS11 now: %08" PRIx32 "\n", getreg32(MPFS_EMMCSD_SRS11));
+}
+
+/****************************************************************************
+ * Name: mpfs_configwaitints
+ *
+ * Description:
+ *   Enable/disable SDIO interrupts needed to support the wait function
+ *
+ * Input Parameters:
+ *   priv       - Instance of the EMMCSD private state structure.
+ *   waitmask   - The set of bits in the SDIO MASK register to set
+ *   waitevents - Waited for events
+ *   wkupevent  - Wake-up events
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void mpfs_configwaitints(struct mpfs_dev_s *priv, uint32_t waitmask,
+                                 sdio_eventset_t waitevents,
+                                 sdio_eventset_t wkupevent)
+{
+  irqstate_t flags;
+
+  /* Save all of the data and set the new interrupt mask in one, atomic
+   * operation.
+   */
+
+  flags = enter_critical_section();
+
+  priv->waitevents = waitevents;
+  priv->wkupevent  = wkupevent;
+  priv->waitmask   = waitmask;
+
+  leave_critical_section(flags);
+}
+
+/****************************************************************************
+ * Name: mpfs_configxfrints
+ *
+ * Description:
+ *   Enable SDIO interrupts needed to support the data transfer event
+ *
+ * Input Parameters:
+ *   priv    - Instance of the EMMCSD private state structure.
+ *   xfrmask - The set of bits in the SDIO MASK register to set
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void mpfs_configxfrints(struct mpfs_dev_s *priv, uint32_t xfrmask)
+{
+  irqstate_t flags;
+
+  flags = enter_critical_section();
+  priv->xfrmask = xfrmask;
+
+  mcinfo("Mask: %08" PRIx32 "\n", priv->xfrmask | priv->waitmask);
+
+  putreg32(priv->xfrmask | priv->waitmask, MPFS_EMMCSD_SRS14);
+
+  leave_critical_section(flags);
+}
+
+/****************************************************************************
+ * Name: mpfs_sendfifo
+ *
+ * Description:
+ *   Send SDIO data in interrupt mode
+ *
+ * Input Parameters:
+ *   priv  - Instance of the EMMCSD private state structure.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void mpfs_sendfifo(struct mpfs_dev_s *priv)
+{
+  union
+  {
+    uint32_t w;
+    uint8_t  b[4];
+  } data;
+
+  /* Disable Buffer Write Ready interrupt */
+
+  modifyreg32(MPFS_EMMCSD_SRS14, MPFS_EMMCSD_SRS14_BWR_IE, 0);
+
+  putreg32(MPFS_EMMCSD_SRS12_TC, MPFS_EMMCSD_SRS12);
+
+  /* We might get extra interrupts */
+
+  if (priv->remaining == 0)
+    {
+      return;
+    }
+
+  /* Loop while there is more data to be sent and the TX FIFO is not full */
+
+  while (priv->remaining > 0)
+    {
+      /* Is there a full word remaining in the user buffer? */
+
+      if (priv->remaining >= sizeof(uint32_t))
+        {
+          /* Yes, transfer the word to the TX FIFO */
+
+          data.w           = *priv->buffer++;
+          priv->remaining -= sizeof(uint32_t);
+        }
+      else
+        {
+          /* No.. transfer just the bytes remaining in the user buffer,
+           * padding with zero as necessary to extend to a full word.
+           */
+
+          uint8_t *ptr = (uint8_t *)priv->remaining;
+          int i;
+
+          data.w = 0;
+          for (i = 0; i < (int)priv->remaining; i++)
+            {
+              data.b[i] = *ptr++;
+            }
+
+          /* Now the transfer is finished */
+
+          priv->remaining = 0;
+        }
+
+      /* Put the word in the FIFO */
+
+      putreg32(data.w, MPFS_EMMCSD_SRS08);
+
+      /* Multi-block writes may hit the wall - stop for now,
+       * continue later. Enable BWR interrupt, clear status and
+       * come back when we're good to write again.
+       */
+
+      if (priv->remaining && (!(getreg32(MPFS_EMMCSD_SRS09) &
+          MPFS_EMMCSD_SRS09_BWE)))
+        {
+          modifyreg32(MPFS_EMMCSD_SRS14, 0, MPFS_EMMCSD_SRS14_BWR_IE);
+          putreg32(MPFS_EMMCSD_SRS12_BWR, MPFS_EMMCSD_SRS12);
+          return;
+        }
+    }
+
+  mcinfo("Wrote all\n");
+}
+
+/****************************************************************************
+ * Name: mpfs_recvfifo
+ *
+ * Description:
+ *   Receive SDIO data in interrupt mode
+ *
+ * Input Parameters:
+ *   priv  - Instance of the EMMCSD private state structure.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void mpfs_recvfifo(struct mpfs_dev_s *priv)
+{
+  union
+  {
+    uint32_t w;
+    uint8_t  b[4];
+  } data;
+
+  mcinfo("Reading: %lu bytes\n", priv->remaining);
+
+  /* Disable Buffer Read Ready interrupt */
+
+  modifyreg32(MPFS_EMMCSD_SRS14, MPFS_EMMCSD_SRS14_BRR_IE, 0);
+
+  if (!priv->remaining)
+    {
+      return;
+    }
+
+  /* Loop while there is space to store the data and there is more
+   * data available in the RX FIFO.
+   */
+
+  while (priv->remaining > 0)
+    {
+      /* Multi-block reads may hit the wall - stop for now,
+       * continue later. Enable BRR interrupt, clear status and
+       * come back when we're good to read more.
+       */
+
+      if (!(getreg32(MPFS_EMMCSD_SRS09) & MPFS_EMMCSD_SRS09_BRE))
+        {
+          modifyreg32(MPFS_EMMCSD_SRS14, 0, MPFS_EMMCSD_SRS14_BRR_IE);
+          putreg32(MPFS_EMMCSD_SRS12_BRR, MPFS_EMMCSD_SRS12);
+          return;
+        }
+
+      /* Read the next word from the RX FIFO */
+
+      data.w = getreg32(MPFS_EMMCSD_SRS08);
+      if (priv->remaining >= sizeof(uint32_t))
+        {
+          /* Transfer the whole word to the user buffer */
+
+          *priv->buffer++  = data.w;
+          priv->remaining -= sizeof(uint32_t);
+        }
+      else
+        {
+          /* Transfer any trailing fractional word */
+
+          uint8_t *ptr = (uint8_t *)priv->buffer;
+          int i;
+
+          for (i = 0; i < (int)priv->remaining; i++)
+            {
+              *ptr++ = data.b[i];
+            }
+
+          /* Now the transfer is finished */
+
+          priv->remaining = 0;
+        }
+    }
+
+    mcinfo("Read all\n");
+}
+
+/****************************************************************************
+ * Name: mpfs_endwait
+ *
+ * Description:
+ *   Wake up a waiting thread if the waited-for event has occurred.
+ *
+ * Input Parameters:
+ *   priv  - Instance of the EMMCSD private state structure.
+ *   wkupevent - The event that caused the wait to end
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   Always called from the interrupt level with interrupts disabled.
+ *
+ ****************************************************************************/
+
+static void mpfs_endwait(struct mpfs_dev_s *priv,
+                          sdio_eventset_t wkupevent)
+{
+  mcinfo("wkupevent: %u\n", wkupevent);
+
+  /* Cancel the watchdog timeout */
+
+  wd_cancel(&priv->waitwdog);
+
+  /* Disable event-related interrupts */
+
+  mpfs_configwaitints(priv, 0, 0, wkupevent);
+
+  /* Wake up the waiting thread */
+
+  mpfs_givesem(priv);
+}
+
+/****************************************************************************
+ * Name: mpfs_eventtimeout
+ *
+ * Description:
+ *   The watchdog timeout setup when the event wait start has expired without
+ *   any other waited-for event occurring.
+ *
+ * Input Parameters:
+ *   arg    - The argument
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   Always called from the interrupt level with interrupts disabled.
+ *
+ ****************************************************************************/
+
+static void mpfs_eventtimeout(wdparm_t arg)
+{
+  struct mpfs_dev_s *priv = (struct mpfs_dev_s *)arg;
+
+  /* There is always race conditions with timer expirations. */
+
+  DEBUGASSERT((priv->waitevents & SDIOWAIT_TIMEOUT) != 0 ||
+              priv->wkupevent != 0);
+
+  mcinfo("sta: %08" PRIx32 " enabled irq: %08" PRIx32 "\n",
+         getreg32(MPFS_EMMCSD_SRS12),
+         getreg32(MPFS_EMMCSD_SRS13));
+
+  /* Is a data transfer complete event expected? */
+
+  if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
+    {
+      /* Yes.. wake up any waiting threads */
+
+      mpfs_endwait(priv, SDIOWAIT_TIMEOUT);
+      mcerr("Timeout: remaining: %lu\n", priv->remaining);
+    }
+}
+
+/****************************************************************************
+ * Name: mpfs_endtransfer
+ *
+ * Description:
+ *   Terminate a transfer with the provided status.  This function is called
+ *   only from the SDIO interrupt handler when end-of-transfer conditions
+ *   are detected.
+ *
+ * Input Parameters:
+ *   priv  - Instance of the EMMCSD private state structure.
+ *   wkupevent - The event that caused the transfer to end
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   Always called from the interrupt level with interrupts disabled.
+ *
+ ****************************************************************************/
+
+static void mpfs_endtransfer(struct mpfs_dev_s *priv,
+                              sdio_eventset_t wkupevent)
+{
+  /* Disable all transfer related interrupts */
+
+  mpfs_configxfrints(priv, 0);
+
+  /* If there were errors, reset lines */
+
+  if ((wkupevent & (~SDIOWAIT_TRANSFERDONE)) != 0)
+    {
+      mpfs_reset_lines(priv);
+    }
+
+  /* Clear Buffer Read Ready (BRR), BWR and DMA statuses */
+
+  putreg32(MPFS_EMMCSD_SRS12, MPFS_EMMCSD_SRS12_BRR |
+           MPFS_EMMCSD_SRS12_BWR | MPFS_EMMCSD_SRS12_DMAINT);
+
+  /* Mark the transfer finished */
+
+  priv->remaining = 0;
+
+  /* Is a thread wait for these data transfer complete events? */
+
+  if ((priv->waitevents & wkupevent) != 0)
+    {
+      /* Yes.. wake up any waiting threads */
+
+      mpfs_endwait(priv, wkupevent);
+    }
+}
+
+/****************************************************************************
+ * Name: mpfs_emmcsd_interrupt
+ *
+ * Description:
+ *   eMMCSD interrupt handler
+ *
+ * Input Parameters:
+ *   priv  - Instance of the eMMCSD private state structure.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static int mpfs_emmcsd_interrupt(int irq, void *context, void *arg)
+{
+  struct mpfs_dev_s *priv = (struct mpfs_dev_s *)arg;
+  uint32_t status;
+
+  DEBUGASSERT(priv != NULL);
+
+  status = getreg32(MPFS_EMMCSD_SRS12);
+
+  mcinfo("status: %08" PRIx32 "\n", status);
+
+  if (status & MPFS_EMMCSD_SRS12_EINT)
+    {
+      if (status & MPFS_EMMCSD_SRS12_EDCRC)
+        {
+          /* Handle data block send/receive CRC failure */
+
+          mcerr("ERROR: Data block CRC failure, remaining: %lu\n",
+                priv->remaining);
+
+          mpfs_endtransfer(priv, SDIOWAIT_TRANSFERDONE |
+                                 SDIOWAIT_ERROR);
+        }
+      else if (status & MPFS_EMMCSD_SRS12_EDT)
+        {
+          /* Handle data timeout error */
+
+          mcerr("ERROR: Data timeout: %08" PRIx32 " remaining: %lu\n",
+                status, priv->remaining);
+
+          mpfs_endtransfer(priv, SDIOWAIT_TRANSFERDONE |
+                                 SDIOWAIT_TIMEOUT);
+        }
+      else if (status & MPFS_EMMCSD_SRS12_EADMA)
+        {
+          /* Handle DMA error */
+
+          mcerr("ERROR: DMA error: %08" PRIx32 " SRS21: %08" PRIx32 "\n",
+                status, getreg32(MPFS_EMMCSD_SRS21));
+
+          mpfs_endtransfer(priv, SDIOWAIT_TRANSFERDONE |
+                                 SDIOWAIT_ERROR);
+        }
+      else
+        {
+          /* Generic error, not specified above */
+
+          mcerr("ERROR: %08" PRIx32 "\n", status);
+          mpfs_endtransfer(priv, SDIOWAIT_TRANSFERDONE |
+                                 SDIOWAIT_ERROR);
+        }
+    }
+  else
+    {
+      /* Handle wait events */
+
+      if (status & MPFS_EMMCSD_SRS12_DMAINT)
+        {
+          /* Very large transfers may end up here.
+           * They are not tested at all.
+           */
+
+          mcerr("DMAINT not expected, TC instead!\n");
+
+          mpfs_endtransfer(priv, SDIOWAIT_TRANSFERDONE);
+        }
+      else if (status & MPFS_EMMCSD_SRS12_BRR)
+        {
+          if (priv->polltransfer)
+            {
+              mpfs_recvfifo(priv);
+              if (!priv->remaining)
+                {
+                  if (status & MPFS_EMMCSD_SRS12_TC)
+                    {
+                      mpfs_endtransfer(priv, SDIOWAIT_TRANSFERDONE);
+                    }
+                }
+            }
+          else
+            {
+              mpfs_endtransfer(priv, SDIOWAIT_TRANSFERDONE);
+            }
+        }
+      else if (status & MPFS_EMMCSD_SRS12_BWR)
+        {
+          if (priv->polltransfer)
+            {
+              mpfs_sendfifo(priv);
+              if (status & MPFS_EMMCSD_SRS12_TC)
+                {
+                  mpfs_endtransfer(priv, SDIOWAIT_TRANSFERDONE);
+                }
+            }
+        }
+      else if (status & MPFS_EMMCSD_SRS12_TC)
+        {
+          putreg32(MPFS_EMMCSD_SRS12_TC, MPFS_EMMCSD_SRS12);
+          if (priv->polltransfer && priv->receivecnt)
+            {
+              mcerr("Unexpected Transfer Complete!\n");
+            }
+          else
+            {
+              mpfs_endtransfer(priv, SDIOWAIT_TRANSFERDONE);
+            }
+        }
+      else if (status & MPFS_EMMCSD_SRS12_CC)
+        {
+          /* We don't handle Command Completes here! */
+
+          DEBUGPANIC();
+        }
+      else if (status & MPFS_EMMCSD_SRS12_CIN)
+        {
+          mcinfo("Card inserted!\n");
+
+          sdio_mediachange((struct sdio_dev_s *)priv, true);
+          putreg32(MPFS_EMMCSD_SRS12_CIN, MPFS_EMMCSD_SRS12);
+        }
+      else if (status & MPFS_EMMCSD_SRS12_CR)
+        {
+          mcinfo("Card removed!\n");
+
+          sdio_mediachange((struct sdio_dev_s *)priv, false);
+          putreg32(MPFS_EMMCSD_SRS12_CR, MPFS_EMMCSD_SRS12);
+        }
+      else
+        {
+          mcerr("Status not handled: %08" PRIx32 "\n", status);
+        }
+    }
+
+  mcinfo("done\n");
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: mpfs_lock
+ *
+ * Description:
+ *   Locks the bus. Function calls low-level multiplexed bus routines to
+ *   resolve bus requests and acknowledgment issues.
+ *
+ * Input Parameters:
+ *   dev    - An instance of the SDIO device interface
+ *   lock   - TRUE to lock, FALSE to unlock.
+ *
+ * Returned Value:
+ *   OK on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_SDIO_MUXBUS)
+static int mpfs_lock(FAR struct sdio_dev_s *dev, bool lock)
+{
+  /* The multiplex bus is part of board support package. */
+
+  mpfs_muxbus_sdio_lock(dev, lock);
+
+  return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: mpfs_set_data_timeout
+ *
+ * Description:
+ *   Sets the cycles for determining the data line timeout.
+ *
+ * Input Parameters:
+ *   priv        - Instance of the eMMCSD private state structure.
+ *   timeout_us  - Requested timeout in microseconds
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void mpfs_set_data_timeout(struct mpfs_dev_s *priv,
+                                  uint32_t timeout_us)
+{
+  uint32_t timeout_interval;
+  uint32_t sdmclk_khz;
+  uint32_t sdmclk_mhz;
+  uint32_t sdmclk;
+  uint32_t timeout;
+  uint32_t temp;
+  uint8_t j;
+
+  temp = getreg32(MPFS_EMMCSD_SRS16);
+
+  /* 0x4u; - 0x4 is dummy -> 50Mhz * 4 = 200Mhz */
+
+  sdmclk_khz = (temp & 0x0000003fu);
+
+  DEBUGASSERT(sdmclk_khz);
+
+  if (!(temp & MPFS_EMMCSD_SRS16_TCU))
+    {
+      DEBUGASSERT(timeout_us >= 1000);
+    }
+  else
+    {
+      sdmclk_khz *= 1000;
+    }
+
+  sdmclk_mhz = sdmclk_khz / 1000;
+
+  if (sdmclk_mhz == 0)
+    {
+      sdmclk = sdmclk_khz;
+      timeout = timeout_us / 1000u;
+    }
+  else
+    {
+      sdmclk = sdmclk_mhz;
+      timeout = timeout_us;
+    }
+
+  /* calculate data timeout counter value */
+
+  timeout_interval = 8192; /* 2^13 */
+  for (j = 0; j < 15; j++)
+    {
+      if (timeout < (timeout_interval / sdmclk))
+        {
+          break;
+        }
+
+        timeout_interval *= 2;
+    }
+
+  timeout_interval = (uint32_t)j << 16;
+
+  mcinfo("Data timeout: %08" PRIx32 "\n", timeout_interval);
+
+  modifyreg32(MPFS_EMMCSD_SRS11, MPFS_EMMCSD_SRS11_DTCV, timeout_interval);
+}
+
+/****************************************************************************
+ * Name: mpfs_set_sdhost_power
+ *
+ * Description:
+ *   Sets the requested SD bus voltage.
+ *
+ * Input Parameters:
+ *   priv     - Instance of the eMMCSD private state structure.
+ *   voltage  - Requested voltage: 0v, 3v3, 3v0 or 1v8
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void mpfs_set_sdhost_power(struct mpfs_dev_s *priv, uint32_t voltage)
+{
+  uint32_t srs16;
+
+  /* Disable SD bus power */
+
+  modifyreg32(MPFS_EMMCSD_SRS10, MPFS_EMMCSD_SRS10_BP, 0);
+
+  /* Clear current voltage settings */
+
+  modifyreg32(MPFS_EMMCSD_SRS10, MPFS_EMMCSD_SRS10_BVS, 0);
+
+  if (!voltage)
+    {
+      return;
+    }
+
+  srs16 = getreg32(MPFS_EMMCSD_SRS16);
+
+  switch (voltage)
+    {
+      case MPFS_EMMCSD_SRS10_3_3V_BUS_VOLTAGE:
+        DEBUGASSERT(srs16 & MPFS_EMMCSD_SRS16_VS33);
+        modifyreg32(MPFS_EMMCSD_SRS10,
+                    MPFS_EMMCSD_SRS10_BVS,
+                    MPFS_EMMCSD_SRS10_3_3V_BUS_VOLTAGE |
+                    MPFS_EMMCSD_SRS10_BP);
+        break;
+      case MPFS_EMMCSD_SRS10_3_0V_BUS_VOLTAGE:
+        DEBUGASSERT(srs16 & MPFS_EMMCSD_SRS16_VS30);
+        modifyreg32(MPFS_EMMCSD_SRS10,
+                    MPFS_EMMCSD_SRS10_BVS,
+                    MPFS_EMMCSD_SRS10_3_0V_BUS_VOLTAGE |
+                    MPFS_EMMCSD_SRS10_BP);
+        break;
+      case MPFS_EMMCSD_SRS10_1_8V_BUS_VOLTAGE:
+        DEBUGASSERT(srs16 & MPFS_EMMCSD_SRS16_VS18);
+        modifyreg32(MPFS_EMMCSD_SRS10,
+                    MPFS_EMMCSD_SRS10_BVS,
+                    MPFS_EMMCSD_SRS10_1_8V_BUS_VOLTAGE |
+                    MPFS_EMMCSD_SRS10_BP);
+        break;
+      default:
+        DEBUGPANIC();
+    }
+
+  nxsig_usleep(1000);
+}
+
+/****************************************************************************
+ * Name: mpfs_sdcard_init
+ *
+ * Description:
+ *   Switches to use to SD-card instead of eMMC. Call only if the SD-card
+ *   is used, not eMMC. SDIO_REGISTER_ADDRESS is the switch itself: 0
+ *   means eMMC and 1 is for SD. Also the IOMUX settings are applied
+ *   properly.
+ *
+ * Input Parameters:
+ *   priv     - Instance of the eMMCSD private state structure.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void mpfs_sdcard_init(struct mpfs_dev_s *priv)
+{
+  mcinfo("Init SD-card. Old FPGA will crash here!\n");
+
+  putreg32(LIBERO_SETTING_IOMUX1_CR_SD, MPFS_SYSREG_IOMUX1);
+  putreg32(LIBERO_SETTING_IOMUX2_CR_SD, MPFS_SYSREG_IOMUX2);
+  putreg32(LIBERO_SETTING_IOMUX6_CR_SD, MPFS_SYSREG_IOMUX6);
+
+  /* With 3.3v we exit from here */
+
+  if (priv->jumpers_3v3)
+    {
+      putreg32(1, SDIO_REGISTER_ADDRESS);
+      return;
+    }
+
+  putreg32(LIBERO_SETTING_MSSIO_BANK4_CFG_CR_SD, MPFS_SYSREG_B4_CFG);
+  putreg32(LIBERO_SETTING_MSSIO_BANK4_IO_CFG_0_1_CR_SD, MPFS_SYSREG_B4_0_1);
+  putreg32(LIBERO_SETTING_MSSIO_BANK4_IO_CFG_2_3_CR_SD, MPFS_SYSREG_B4_2_3);
+  putreg32(LIBERO_SETTING_MSSIO_BANK4_IO_CFG_4_5_CR_SD, MPFS_SYSREG_B4_4_5);
+  putreg32(LIBERO_SETTING_MSSIO_BANK4_IO_CFG_6_7_CR_SD, MPFS_SYSREG_B4_6_7);
+  putreg32(LIBERO_SETTING_MSSIO_BANK4_IO_CFG_8_9_CR_SD, MPFS_SYSREG_B4_8_9);
+  putreg32(LIBERO_SETTING_MSSIO_BANK4_IO_CFG_10_11_CR_SD,
+           MPFS_SYSREG_B4_10_11);
+  putreg32(LIBERO_SETTING_MSSIO_BANK4_IO_CFG_12_13_CR_SD,
+          MPFS_SYSREG_4_12_13);
+
+  putreg32(1, SDIO_REGISTER_ADDRESS);
+}
+
+/****************************************************************************
+ * Name: mpfs_device_reset
+ *
+ * Description:
+ *   Reset the SDIO controller. Undo all setup and initialization.
+ *
+ * Input Parameters:
+ *   dev    - An instance of the SDIO device interface
+ *
+ * Returned Value:
+ *   true on success, false otherwise
+ *
+ ****************************************************************************/
+
+static bool mpfs_device_reset(FAR struct sdio_dev_s *dev)
+{
+  FAR struct mpfs_dev_s *priv = (FAR struct mpfs_dev_s *)dev;
+  irqstate_t flags;
+  uint32_t regval;
+  uint32_t cap;
+  uint32_t srs09;
+  bool retval = true;
+  int status = MPFS_EMMCSD_INITIALIZED;
+
+  flags = enter_critical_section();
+
+  up_disable_irq(priv->plic_irq);
+
+  if (!priv->emmc)
+    {
+      /* SD card needs FPGA out of reset and FIC3 clks for the eMMC / SD
+       * switch. It's OK if these are already out of reset or clk applied.
+       */
+
+      modifyreg32(MPFS_SYSREG_SOFT_RESET_CR,
+                  SYSREG_SOFT_RESET_CR_FPGA |
+                  SYSREG_SOFT_RESET_CR_FIC3, 0);
+
+      modifyreg32(MPFS_SYSREG_SUBBLK_CLOCK_CR, 0,
+                  SYSREG_SUBBLK_CLOCK_CR_FIC3);
+
+      mpfs_sdcard_init(priv);
+    }
+
+  /* Perform system-level reset */
+
+  modifyreg32(MPFS_SYSREG_SUBBLK_CLOCK_CR, 0,
+              SYSREG_SUBBLK_CLOCK_CR_MMC);
+
+  modifyreg32(MPFS_SYSREG_SOFT_RESET_CR, 0,
+              SYSREG_SOFT_RESET_CR_MMC);
+
+  modifyreg32(MPFS_SYSREG_SOFT_RESET_CR,
+              SYSREG_SOFT_RESET_CR_MMC, 0);
+
+  nxsig_sleep(1);
+
+  /* Perform module-level reset */
+
+  modifyreg32(MPFS_EMMCSD_HRS00, 0, MPFS_EMMCSD_HRS00_SWR);
+
+  nxsig_usleep(1000);
+
+  do
+    {
+      regval = getreg32(MPFS_EMMCSD_HRS00);
+    }
+  while (regval & MPFS_EMMCSD_HRS00_SWR);
+
+  putreg32(MPFS_EMMCSD_DEBOUNCE_TIME, MPFS_EMMCSD_HRS01);
+
+  modifyreg32(MPFS_EMMCSD_HRS06, MPFS_EMMCSD_HRS06_EMM, 0);
+
+  /* eMMC, not SD */
+
+  if (priv->emmc)
+    {
+      modifyreg32(MPFS_EMMCSD_HRS06, 0, MPFS_EMMCSD_MODE_LEGACY);
+    }
+
+  putreg32(MPFS_EMMCSD_SRS12_STAT_CLEAR, MPFS_EMMCSD_SRS12);
+
+  cap = getreg32(MPFS_EMMCSD_SRS16);
+
+  /* DMA 64 bit support? */
+
+  if (cap & MPFS_EMMCSD_SRS16_A64S)
+    {
+      modifyreg32(MPFS_EMMCSD_SRS15, 0, MPFS_EMMCSD_SRS15_A64B |
+                  MPFS_EMMCSD_SRS15_HV4E);
+    }
+
+#ifdef CONFIG_SDIO_DMA
+  /* Check if SDMA is supported */
+
+  if (!(cap & MPFS_EMMCSD_SRS16_DMAS))
+    {
+      mcerr("DMA not supported!\n");
+      DEBUGPANIC();
+    }
+
+  uint64_t pmpcfg_mmc_x;
+
+  /* DMA will not work with the power-on default PMPCFG values.
+   * Check that the HSS or envm bootloader has applied the
+   * following values below, provide info if not.
+   */
+
+  pmpcfg_mmc_x = getreg64(MPFS_PMPCFG_MMC_0);
+  if ((pmpcfg_mmc_x & 0x1ffffff000000000) != 0x1f00000000000000)
+    {
+      mcinfo("Please check PMPCFG_MMC0 register.\n");
+    }
+
+  pmpcfg_mmc_x = getreg64(MPFS_PMPCFG_MMC_1);
+  if ((pmpcfg_mmc_x & 0x1ffffff000000000) != 0x1f00000000000000)
+    {
+      mcinfo("Please check PMPCFG_MMC1 register.\n");
+    }
+
+  pmpcfg_mmc_x = getreg64(MPFS_PMPCFG_MMC_2);
+  if ((pmpcfg_mmc_x & 0x1ffffff000000000) != 0x1f00000000000000)
+    {
+      mcinfo("Please check PMPCFG_MMC2 register.\n");
+    }
+
+  pmpcfg_mmc_x = getreg64(MPFS_PMPCFG_MMC_3);
+  if ((pmpcfg_mmc_x & 0x1ffffff000000000) != 0x1f00000000000000)
+    {
+      mcinfo("Please check PMPCFG_MMC3 register.\n");
+    }
+
+#endif
+
+  /* Clear interrupt status and disable interrupts */
+
+  putreg32(MPFS_EMMCSD_SRS13_STATUS_EN, MPFS_EMMCSD_SRS13);
+  putreg32(0, MPFS_EMMCSD_SRS14);
+
+  mpfs_set_data_timeout(priv, MPFS_EMMCSD_DATA_TIMEOUT);
+
+  /* Turn off host controller power */
+
+  mpfs_set_sdhost_power(priv, 0);
+
+  /* Card state stable */
+
+  srs09 = getreg32(MPFS_EMMCSD_SRS09);
+  DEBUGASSERT(srs09 & MPFS_EMMCSD_SRS09_CSS);
+
+  if (!priv->emmc)
+    {
+      if (!(srs09 & MPFS_EMMCSD_SRS09_CI))
+        {
+          mcerr("Please insert the SD card!\n");
+
+          /* No card detected, cannot communicate with it */
+
+          retval = false;
+        }
+    }
+
+  /* Set 1-bit bus mode */
+
+  modifyreg32(MPFS_EMMCSD_SRS10,
+              MPFS_EMMCSD_SRS10_DTW | MPFS_EMMCSD_SRS10_EDTW,
+              0);
+
+  if (priv->emmc)
+    {
+      switch (priv->bus_voltage)
+        {
+          case MPFS_EMMCSD_1_8V_BUS_VOLTAGE:
+            mpfs_set_sdhost_power(priv, MPFS_EMMCSD_SRS10_1_8V_BUS_VOLTAGE);
+            break;
+
+          case MPFS_EMMCSD_3_3V_BUS_VOLTAGE:
+            if ((priv->bus_speed != MPFS_EMMCSD_MODE_HS200) &&
+                (priv->bus_speed != MPFS_EMMCSD_MODE_HS400_ES) &&
+                (priv->bus_speed != MPFS_EMMCSD_MODE_HS400))
+              {
+                mpfs_set_sdhost_power(priv,
+                                      MPFS_EMMCSD_SRS10_3_3V_BUS_VOLTAGE);
+              }
+              else
+              {
+                status = MPFS_EMMCSD_NOT_INITIALIZED;
+                mcerr("Voltage / mode combination not supported!\n");
+              }
+            break;
+
+          default:
+            DEBUGPANIC();
+        }
+    }
+  else
+    {
+      /* SD-card support currently only 3.3v */
+
+       mpfs_set_sdhost_power(priv, MPFS_EMMCSD_SRS10_3_3V_BUS_VOLTAGE);
+    }
+
+  if (status == MPFS_EMMCSD_INITIALIZED)
+    {
+      mpfs_setclkrate(priv, MPFS_MMC_CLOCK_400KHZ);
+    }
+
+  nxsig_usleep(1000);
+
+  /* Reset data */
+
+  priv->waitevents = 0;      /* Set of events to be waited for */
+  priv->waitmask   = 0;      /* Interrupt enables for event waiting */
+  priv->wkupevent  = 0;      /* The event that caused the wakeup */
+
+  wd_cancel(&priv->waitwdog); /* Cancel any timeouts */
+
+  /* Interrupt mode data transfer support */
+
+  priv->buffer     = 0;      /* Address of current R/W buffer */
+  priv->remaining  = 0;      /* Number of bytes remaining in the transfer */
+  priv->xfrmask    = 0;      /* Interrupt enables for data transfer */
+
+  priv->widebus    = false;
+
+  mpfs_reset_lines(priv);
+
+  leave_critical_section(flags);
+
+  return retval;
+}
+
+/****************************************************************************
+ * Name: mpfs_reset
+ *
+ * Description:
+ *   Reset the SDIO controller via mpfs_device_reset. This is a wrapper
+ *   function only.
+ *
+ * Input Parameters:
+ *   dev    - An instance of the SDIO device interface
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void mpfs_reset(FAR struct sdio_dev_s *dev)
+{
+  mpfs_device_reset(dev);
+}
+
+/****************************************************************************
+ * Name: mpfs_capabilities
+ *
+ * Description:
+ *   Get capabilities (and limitations) of the SDIO driver (optional)
+ *
+ * Input Parameters:
+ *   dev   - Device-specific state data
+ *
+ * Returned Value:
+ *   Returns a bitset of status values (see SDIO_CAPS_* defines)
+ *
+ ****************************************************************************/
+
+static sdio_capset_t mpfs_capabilities(FAR struct sdio_dev_s *dev)
+{
+  struct mpfs_dev_s *priv = (struct mpfs_dev_s *)dev;
+  sdio_capset_t caps = 0;
+
+  if (priv->onebit)
+    {
+      caps |= SDIO_CAPS_1BIT_ONLY;
+    }
+
+  /* This reverses the logic for mmcsd_writesingle(): setup first, then
+   * the command is sent. Normally the command is sent first and the setup
+   * via SDIO_SENDSETUP().
+   */
+
+  caps |= SDIO_CAPS_DMABEFOREWRITE;
+
+#ifdef CONFIG_SDIO_DMA
+  caps |= SDIO_CAPS_DMASUPPORTED;
+#endif
+
+  return caps;
+}
+
+/****************************************************************************
+ * Name: mpfs_status
+ *
+ * Description:
+ *   Get SDIO status.
+ *
+ * Input Parameters:
+ *   dev   - Device-specific state data
+ *
+ * Returned Value:
+ *   Returns a bitset of status values (see mpfs_status_* defines)
+ *
+ ****************************************************************************/
+
+static sdio_statset_t mpfs_status(FAR struct sdio_dev_s *dev)
+{
+  struct mpfs_dev_s *priv = (struct mpfs_dev_s *)dev;
+  return priv->cdstatus;
+}
+
+/****************************************************************************
+ * Name: mpfs_widebus
+ *
+ * Description:
+ *   Called after change in Bus width has been selected (via ACMD6).  Most
+ *   controllers will need to perform some special operations to work
+ *   correctly in the new bus mode.
+ *
+ * Input Parameters:
+ *   dev  - An instance of the SDIO device interface
+ *   wide - true: wide bus (4-bit) bus mode enabled
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void mpfs_widebus(FAR struct sdio_dev_s *dev, bool wide)
+{
+  struct mpfs_dev_s *priv = (struct mpfs_dev_s *)dev;
+  priv->widebus = wide;
+
+  mcinfo("wide: %d\n", wide);
+
+  if (wide)
+    {
+      modifyreg32(MPFS_EMMCSD_SRS10, 0, MPFS_EMMCSD_SRS10_DTW);
+    }
+  else
+    {
+      modifyreg32(MPFS_EMMCSD_SRS10, MPFS_EMMCSD_SRS10_DTW, 0);
+    }
+}
+
+/****************************************************************************
+ * Name: mpfs_clock
+ *
+ * Description:
+ *   Enable/disable SDIO clocking. Only up to 25 Mhz is supported now. 50 Mhz
+ *   may work with some cards.
+ *
+ * Input Parameters:
+ *   dev  - An instance of the SDIO device interface
+ *   rate - Specifies the clocking to use (see enum sdio_clock_e)
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void mpfs_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate)
+{
+  struct mpfs_dev_s *priv = (struct mpfs_dev_s *)dev;
+  uint32_t clckr;
+
+  switch (rate)
+  {
+    /* Disable clock */
+
+    default:
+    case CLOCK_SDIO_DISABLED:
+      clckr = 0;
+      break;
+
+    /* Enable in initial ID mode clocking (400KHz) */
+
+    case CLOCK_IDMODE:
+      clckr = MPFS_MMC_CLOCK_400KHZ;
+      break;
+
+    /* Enable normal MMC operation clocking */
+
+    case CLOCK_MMC_TRANSFER:
+      clckr = MPFS_MMC_CLOCK_25MHZ;
+      break;
+
+    /* SD normal operation clocking (wide 4-bit mode) */
+
+    case CLOCK_SD_TRANSFER_4BIT:
+      clckr = MPFS_MMC_CLOCK_25MHZ;
+      break;
+
+    /* SD normal operation clocking (narrow 1-bit mode) */
+
+    case CLOCK_SD_TRANSFER_1BIT:
+      clckr = MPFS_MMC_CLOCK_25MHZ;
+      break;
+  }
+
+  /* Set the new clock frequency */
+
+  mpfs_setclkrate(priv, clckr);
+}
+
+/****************************************************************************
+ * Name: mpfs_attach
+ *
+ * Description:
+ *   Attach and prepare interrupts
+ *
+ * Input Parameters:
+ *   dev - An instance of the SDIO device interface
+ *
+ * Returned Value:
+ *   OK on success; A negated errno on failure.
+ *
+ ****************************************************************************/
+
+static int mpfs_attach(FAR struct sdio_dev_s *dev)
+{
+  struct mpfs_dev_s *priv = (struct mpfs_dev_s *)dev;
+  int ret;
+
+  /* Attach the SDIO interrupt handler */
+
+  ret = irq_attach(priv->plic_irq, mpfs_emmcsd_interrupt, priv);
+  if (ret == OK)
+    {
+      /* Disable all interrupts at the SDIO controller and clear
+       * interrupt flags, except current limit error, card interrupt,
+       * card removal and card insertion
+       */
+
+      modifyreg32(MPFS_EMMCSD_SRS12, MPFS_EMMCSD_SRS12_ECL |
+                                     MPFS_EMMCSD_SRS12_CINT |
+                                     MPFS_EMMCSD_SRS12_CR |
+                                     MPFS_EMMCSD_SRS12_CIN,
+                                     0);
+
+      /* Enable SDIO interrupts. They can now be enabled at the
+       * SDIO controller as needed.
+       */
+
+      up_enable_irq(priv->plic_irq);
+
+      /* Enable card insertion and removal interrupts */
+
+      putreg32(MPFS_EMMCSD_CARD_INTS, MPFS_EMMCSD_SRS14);
+    }
+
+  mcinfo("attach: %d\n", ret);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: mpfs_sendcmd
+ *
+ * Description:
+ *   Send the SDIO command
+ *
+ * Input Parameters:
+ *   dev  - An instance of the SDIO device interface
+ *   cmd  - The command to send (32-bits, encoded)
+ *   arg  - 32-bit argument required with some commands
+ *
+ * Returned Value:
+ *   OK if no errors, an error otherwise
+ *
+ ****************************************************************************/
+
+static int mpfs_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd,
+                         uint32_t arg)
+{
+  struct mpfs_dev_s *priv = (struct mpfs_dev_s *)dev;
+  uint32_t command_information;
+  uint32_t cmdidx;
+
+  /* Check if command / data lines are busy */
+
+  if (mpfs_check_lines_busy(priv))
+    {
+      mcerr("Busy!\n");
+      return -EBUSY;
+    }
+
+  /* Clear all status interrupts */
+
+  putreg32(MPFS_EMMCSD_SRS12_STAT_CLEAR, MPFS_EMMCSD_SRS12);
+
+  /* Check response type */
+
+  switch (cmd & MMCSD_RESPONSE_MASK)
+    {
+      case MMCSD_R2_RESPONSE:
+        command_information = MPFS_EMMCSD_SRS03_RESP_L136 |
+                              MPFS_EMMCSD_SRS03_CRCCE;
+        break;
+      case MMCSD_R3_RESPONSE:
+      case MMCSD_R4_RESPONSE:
+        command_information = MPFS_EMMCSD_SRS03_RESP_L48;
+        break;
+      case MMCSD_R1_RESPONSE:
+      case MMCSD_R5_RESPONSE:
+      case MMCSD_R6_RESPONSE:
+      case MMCSD_R7_RESPONSE:
+        command_information = MPFS_EMMCSD_SRS03_RESP_L48 |
+                              MPFS_EMMCSD_SRS03_CRCCE |
+                              MPFS_EMMCSD_SRS03_CICE;
+        break;
+      case MMCSD_R1B_RESPONSE:
+        command_information = MPFS_EMMCSD_SRS03_RESP_L48B |
+                              MPFS_EMMCSD_SRS03_CRCCE |
+                              MPFS_EMMCSD_SRS03_CICE;
+        break;
+      case MMCSD_NO_RESPONSE:
+        command_information = MPFS_EMMCSD_SRS03_NO_RESPONSE;
+        break;
+      default:
+        return -EINVAL;
+    }
+
+  putreg32(arg, MPFS_EMMCSD_SRS02);
+
+  cmdidx = (cmd & MMCSD_CMDIDX_MASK) >> MMCSD_CMDIDX_SHIFT;
+
+  if (cmd & MMCSD_DATAXFR_MASK)
+    {
+      command_information |= MPFS_EMMCSD_SRS03_DPS |
+                             MPFS_EMMCSD_SRS03_BCE |
+                             MPFS_EMMCSD_SRS03_RECE;
+
+#ifdef CONFIG_SDIO_DMA
+      if (!priv->polltransfer)
+        {
+          command_information |= MPFS_EMMCSD_SRS03_DMAE;
+        }
+#endif
+
+      if ((cmd & MMCSD_DATAXFR_MASK) == MMCSD_RDDATAXFR)
+        {
+          command_information |= MPFS_EMMCSD_SRS03_DTDS;
+          mcinfo("cmd & MMCSD_RDDATAXFR\n");
+        }
+
+      if (cmd & MMCSD_MULTIBLOCK)
+        {
+          command_information |= MPFS_EMMCSD_SRS03_MSBS;
+        }
+
+      mcinfo("cmd & MMCSD_DATAXFR_MASK\n");
+    }
+
+  putreg32((((cmdidx << 24) & MPFS_EMMCSD_SRS03_CIDX) | command_information),
+           MPFS_EMMCSD_SRS03);
+
+  mcinfo("sendcmd: %08" PRIx32 " cmd: %08" PRIx32 " arg: %08" PRIx32
+         " cmdidx: %08" PRIx32 "\n",
+         command_information, cmd, arg, cmdidx);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: mpfs_blocksetup
+ *
+ * Description:
+ *   Configure block size and the number of blocks for next transfer.
+ *
+ * Input Parameters:
+ *   dev       - An instance of the SDIO device interface.
+ *   blocksize - The selected block size.
+ *   nblocks   - The number of blocks to transfer.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SDIO_BLOCKSETUP
+static void mpfs_blocksetup(FAR struct sdio_dev_s *dev,
+                             unsigned int blocksize, unsigned int nblocks)
+{
+  struct mpfs_dev_s *priv = (struct mpfs_dev_s *)dev;
+
+  priv->blocksize = blocksize;
+
+  putreg32(priv->blocksize | (nblocks << 16) |
+           MPFS_EMMCSD_SRS01_DMA_SZ_512KB, MPFS_EMMCSD_SRS01);
+}
+#endif
+
+/****************************************************************************
+ * Name: mpfs_recvsetup
+ *
+ * Description:
+ *   Setup hardware in preparation for data transfer from the card in non-DMA
+ *   (interrupt driven mode).  This method will do whatever controller setup
+ *   is necessary.  This would be called for SD memory just BEFORE sending
+ *   CMD13 (SEND_STATUS), CMD17 (READ_SINGLE_BLOCK), CMD18
+ *   (READ_MULTIPLE_BLOCKS), ACMD51 (SEND_SCR), etc. Normally,
+ *   EMMCSD_WAITEVENT will be called to receive the indication that the
+ *   transfer is complete.
+ *
+ * Input Parameters:
+ *   dev    - An instance of the SDIO device interface
+ *   buffer - Address of the buffer in which to receive the data
+ *   nbytes - The number of bytes in the transfer
+ *
+ * Returned Value:
+ *   Number of bytes sent on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+static int mpfs_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
+                           size_t nbytes)
+{
+  struct mpfs_dev_s *priv = (struct mpfs_dev_s *)dev;
+
+  mcinfo("Receive: %zu bytes\n", nbytes);
+
+  DEBUGASSERT(priv != NULL && buffer != NULL && nbytes > 0);
+  DEBUGASSERT(((uintptr_t)buffer & 3) == 0);
+
+  priv->buffer       = (uint32_t *)buffer;
+  priv->remaining    = nbytes;
+  priv->receivecnt   = nbytes;
+  priv->polltransfer = true;
+
+  mpfs_check_lines_busy(priv);
+
+  /* Set up the SDIO data path, reset DAT and CMD lines */
+
+  mpfs_reset_lines(priv);
+
+#ifndef CONFIG_SDIO_BLOCKSETUP
+  uint32_t blockcount = ((nbytes - 1) / priv->blocksize) + 1;
+  putreg32(priv->blocksize | (blockcount << 16), MPFS_EMMCSD_SRS01);
+#endif
+
+  putreg32(MPFS_EMMCSD_SRS13_STATUS_EN, MPFS_EMMCSD_SRS13);
+  putreg32(MPFS_EMMCSD_SRS12_STAT_CLEAR, MPFS_EMMCSD_SRS12);
+
+  /* Enable interrupts */
+
+  mpfs_configxfrints(priv, MPFS_EMMCSD_RECV_MASK);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: mpfs_sendsetup
+ *
+ * Description:
+ *   Setup hardware in preparation for data transfer from the card.  This
+ *   method will do whatever controller setup is necessary. This would be
+ *   called for SD memory just BEFORE sending CMD24 (WRITE_BLOCK), CMD25
+ *   (WRITE_MULTIPLE_BLOCK).
+ *
+ * Input Parameters:
+ *   dev    - An instance of the SDIO device interface
+ *   buffer - Address of the buffer containing the data to send
+ *   nbytes - The number of bytes in the transfer
+ *
+ * Returned Value:
+ *   Number of bytes sent on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+static int mpfs_sendsetup(FAR struct sdio_dev_s *dev, FAR const
+                           uint8_t *buffer, size_t nbytes)
+{
+  struct mpfs_dev_s *priv = (struct mpfs_dev_s *)dev;
+
+  mcinfo("Send: %zu bytes\n", nbytes);
+
+  DEBUGASSERT(priv != NULL && buffer != NULL && nbytes > 0);
+  DEBUGASSERT(((uintptr_t)buffer & 3) == 0);
+
+  mpfs_check_lines_busy(priv);
+
+  /* Save the source buffer information for use by the interrupt handler */
+
+  priv->buffer       = (uint32_t *)buffer;
+  priv->remaining    = nbytes;
+  priv->receivecnt   = 0;
+  priv->polltransfer = true;
+
+#ifndef CONFIG_SDIO_BLOCKSETUP
+  uint32_t blockcount = ((nbytes - 1) / priv->blocksize) + 1;
+  putreg32(priv->blocksize | (blockcount << 16), MPFS_EMMCSD_SRS01);
+#endif
+
+  putreg32(MPFS_EMMCSD_SRS13_STATUS_EN, MPFS_EMMCSD_SRS13);
+  putreg32(~(MPFS_EMMCSD_SRS12_BWR), MPFS_EMMCSD_SRS12);
+
+  /* Enable interrupts */
+
+  mpfs_configxfrints(priv, MPFS_EMMCSD_SEND_MASK);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: mpfs_dmarecvsetup
+ *
+ * Description:
+ *   Setup to perform a read DMA.  If the processor supports a data cache,
+ *   then this method will also make sure that the contents of the DMA memory
+ *   and the data cache are coherent. For read transfers this may mean
+ *   invalidating the data cache. No cache support is currently implemented.
+ *
+ * Input Parameters:
+ *   dev    - An instance of the SDIO device interface
+ *   buffer - The memory to DMA from
+ *   buflen - The size of the DMA transfer in bytes
+ *
+ * Returned Value:
+ *   OK on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SDIO_DMA
+static int mpfs_dmarecvsetup(FAR struct sdio_dev_s *dev,
+                              FAR uint8_t *buffer, size_t buflen)
+{
+  struct mpfs_dev_s *priv = (struct mpfs_dev_s *)dev;
+#ifndef CONFIG_SDIO_BLOCKSETUP
+  uint32_t blockcount;
+#endif
+
+  mcinfo("Receive: %zu bytes\n", buflen);
+
+  DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0);
+  DEBUGASSERT(((uintptr_t)buffer & 3) == 0);
+
+  priv->buffer       = (uint32_t *)buffer;
+  priv->remaining    = buflen;
+  priv->receivecnt   = buflen;
+  priv->polltransfer = false;
+
+  /* Set up the SDIO data path, reset DAT and CMD lines */
+
+  mpfs_reset_lines(priv);
+
+  modifyreg32(MPFS_EMMCSD_SRS10, MPFS_EMMCSD_SRS10_DMASEL, 0);
+
+  putreg32((uintptr_t)buffer, MPFS_EMMCSD_SRS22);
+  putreg32((uintptr_t)((uint64_t)buffer >> 32), MPFS_EMMCSD_SRS23);
+#ifndef CONFIG_SDIO_BLOCKSETUP
+  blockcount = ((buflen - 1) / priv->blocksize) + 1;
+
+  putreg32((priv->blocksize | (blockcount << 16) |
+           MPFS_EMMCSD_SRS01_DMA_SZ_512KB), MPFS_EMMCSD_SRS01);
+#endif
+
+  /* Clear interrupt status */
+
+  putreg32(MPFS_EMMCSD_SRS12_STAT_CLEAR, MPFS_EMMCSD_SRS12);
+
+  mpfs_configxfrints(priv, MPFS_EMMCSD_RECV_MASKDMA);
+
+  return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: mpfs_dmasendsetup
+ *
+ * Description:
+ *   Setup to perform a write DMA. No cache support is currently implemented.
+ *
+ * Input Parameters:
+ *   dev    - An instance of the SDIO device interface
+ *   buffer - The memory to DMA into
+ *   buflen - The size of the DMA transfer in bytes
+ *
+ * Returned Value:
+ *   OK on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SDIO_DMA
+static int mpfs_dmasendsetup(FAR struct sdio_dev_s *dev,
+                              FAR const uint8_t *buffer, size_t buflen)
+{
+  struct mpfs_dev_s *priv = (struct mpfs_dev_s *)dev;
+#ifndef CONFIG_SDIO_BLOCKSETUP
+  uint32_t blockcount;
+#endif
+
+  mcinfo("Send: %zu bytes\n", buflen);
+
+  DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0);
+  DEBUGASSERT(((uintptr_t)buffer & 3) == 0);
+
+  /* DMA send doesn't work in 0x08xxxxxxx address range. Default to IRQ mode
+   * in this special case.
+   */
+
+  if (((uintptr_t)buffer & 0xff000000) == 0x08000000)
+    {
+      return mpfs_sendsetup(dev, buffer, buflen);
+    }
+
+  /* Save the source buffer information for use by the interrupt handler */
+
+  priv->buffer       = (uint32_t *)buffer;
+  priv->remaining    = buflen;
+  priv->receivecnt   = 0;
+  priv->polltransfer = false;
+
+  modifyreg32(MPFS_EMMCSD_SRS10, MPFS_EMMCSD_SRS10_DMASEL, 0);
+
+  putreg32((uintptr_t)buffer, MPFS_EMMCSD_SRS22);
+  putreg32((uintptr_t)((uint64_t)buffer >> 32), MPFS_EMMCSD_SRS23);
+
+#ifndef CONFIG_SDIO_BLOCKSETUP
+  blockcount = ((buflen - 1) / priv->blocksize) + 1;
+
+  putreg32((priv->blocksize | (blockcount << 16) |
+            MPFS_EMMCSD_SRS01_DMA_SZ_512KB),
+            MPFS_EMMCSD_SRS01);
+#endif
+
+  /* Clear interrupt status */
+
+  putreg32(MPFS_EMMCSD_SRS12_STAT_CLEAR, MPFS_EMMCSD_SRS12);
+
+  mpfs_configxfrints(priv, MPFS_EMMCSD_SEND_MASKDMA);
+
+  return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: mpfs_cancel
+ *
+ * Description:
+ *   Cancel the data transfer setup of EMMCSD_RECVSETUP, EMMCSD_SENDSETUP,
+ *   EMMCSD_DMARECVSETUP or EMMCSD_DMASENDSETUP.  This must be called to
+ *   cancel the data transfer setup if, for some reason, you cannot perform
+ *   the transfer.
+ *
+ * Input Parameters:
+ *   dev  - An instance of the SDIO device interface
+ *
+ * Returned Value:
+ *   OK is success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+static int mpfs_cancel(FAR struct sdio_dev_s *dev)
+{
+  struct mpfs_dev_s *priv = (struct mpfs_dev_s *)dev;
+
+  /* Disable all transfer- and event- related interrupts */
+
+  mpfs_configxfrints(priv, 0);
+  mpfs_configwaitints(priv, 0, 0, 0);
+
+  /* If this was a DMA transfer, make sure that DMA is stopped */
+
+  modifyreg32(MPFS_EMMCSD_SRS03, MPFS_EMMCSD_SRS03_DMAE, 0);
+
+  /* Clearing pending interrupt status on all transfer- and event- related
+   * interrupts
+   */
+
+  putreg32(MPFS_EMMCSD_WAITALL_ICR, MPFS_EMMCSD_SRS12);
+
+  /* Cancel any watchdog timeout */
+
+  wd_cancel(&priv->waitwdog);
+
+  /* Mark no transfer in progress */
+
+  priv->remaining = 0;
+  return OK;
+}
+
+/****************************************************************************
+ * Name: mpfs_waitresponse
+ *
+ * Description:
+ *   Poll-wait for the response to the last command to be ready.
+ *
+ * Input Parameters:
+ *   dev  - An instance of the SDIO device interface
+ *   cmd  - The command that was sent.
+ *
+ * Returned Value:
+ *   OK is success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+static int mpfs_waitresponse(FAR struct sdio_dev_s *dev, uint32_t cmd)
+{
+  struct mpfs_dev_s *priv = (struct mpfs_dev_s *)dev;
+  uint32_t status;
+  int32_t timeout;
+  uint32_t waitbits;
+
+  mcinfo("cmd: %08" PRIx32 "\n", cmd);
+
+  switch (cmd & MMCSD_RESPONSE_MASK)
+    {
+      case MMCSD_NO_RESPONSE:
+        timeout = EMMCSD_CMDTIMEOUT;
+        break;
+
+      case MMCSD_R1_RESPONSE:
+      case MMCSD_R1B_RESPONSE:
+      case MMCSD_R2_RESPONSE:
+      case MMCSD_R4_RESPONSE:
+      case MMCSD_R5_RESPONSE:
+      case MMCSD_R6_RESPONSE:
+        timeout = EMMCSD_LONGTIMEOUT;
+        break;
+
+      case MMCSD_R3_RESPONSE:
+      case MMCSD_R7_RESPONSE:
+        timeout = EMMCSD_CMDTIMEOUT;
+        break;
+
+      default:
+        mcerr("Unknown command\n");
+        return -EINVAL;
+    }
+
+  /* Then wait for the response (or timeout) */
+
+  if (cmd & MMCSD_DATAXFR_MASK)
+    {
+      waitbits = MPFS_EMMCSD_SRS12_CC;
+    }
+
+  do
+    {
+      status = getreg32(MPFS_EMMCSD_SRS12);
+    }
+  while (!(status & (waitbits | MPFS_EMMCSD_SRS12_EINT))
+         && --timeout);
+
+  if (timeout == 0 || (status & MPFS_EMMCSD_SRS12_ECT))
+    {
+      mcerr("ERROR: Timeout cmd: %08" PRIx32 " stat: %08" PRIx32 " wb: %08"
+            PRIx32 "\n", cmd, status, waitbits);
+      return -EBUSY;
+    }
+
+  mcinfo("status: %08" PRIx32 "\n", status);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: mpfs_check_recverror
+ *
+ * Description:
+ *   Receive response to SDIO command.
+ *
+ * Input Parameters:
+ *   priv    - Instance of the EMMCSD private state structure.
+ *
+ * Returned Value:
+ *   OK on success; a negated errno if error detected.
+ *
+ ****************************************************************************/
+
+static int mpfs_check_recverror(struct mpfs_dev_s *priv)
+{
+  uint32_t regval;
+  int ret = OK;
+
+  regval = getreg32(MPFS_EMMCSD_SRS12);
+
+  if (regval & MPFS_EMMCSD_SRS12_EINT)
+    {
+      if (regval & (MPFS_EMMCSD_SRS12_ECT | MPFS_EMMCSD_SRS12_EDT))
+        {
+          mcerr("ERROR: Command timeout: %08" PRIx32 "\n", regval);
+          ret = -ETIMEDOUT;
+        }
+      else if (regval & MPFS_EMMCSD_SRS12_EDCRC)
+        {
+          mcerr("ERROR: CRC failure: %08" PRIx32 "\n", regval);
+          ret = -EIO;
+        }
+      else
+        {
+          mcerr("ERROR: %08" PRIx32 "\n", regval);
+          ret = -EIO;
+        }
+    }
+  else if (!(regval & MPFS_EMMCSD_SRS12_CC))
+    {
+      mcerr("ERROR: Command not completed: %08" PRIx32 "\n", regval);
+      ret = -EIO;
+    }
+
+  if (ret)
+    {
+      /* With an error, reset DAT and CMD lines. Otherwise the next command
+       * will fail as well.
+       */
+
+      mpfs_reset_lines(priv);
+
+      /* Clear all status interrupts */
+
+      putreg32(MPFS_EMMCSD_SRS12_STAT_CLEAR, MPFS_EMMCSD_SRS12);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: mpfs_recvshortcrc
+ *
+ * Description:
+ *   Receive response to SDIO command.
+ *
+ * Input Parameters:
+ *   dev    - An instance of the SDIO device interface
+ *   cmd    - Command
+ *   rshort - Buffer for reveiving the response
+ *
+ * Returned Value:
+ *   OK on success; a negated errno on failure.
+ *
+ ****************************************************************************/
+
+static int mpfs_recvshortcrc(FAR struct sdio_dev_s *dev, uint32_t cmd,
+                              uint32_t *rshort)
+{
+  struct mpfs_dev_s *priv = (struct mpfs_dev_s *)dev;
+  int ret = OK;
+
+  /* Check if a timeout or CRC error occurred */
+
+  if (!(cmd & MMCSD_DATAXFR_MASK)) /* TBD: Fix this bypass! */
+    {
+      ret = mpfs_check_recverror(priv);
+    }
+
+  if (rshort)
+    {
+      *rshort = getreg32(MPFS_EMMCSD_SRS04);
+      mcinfo("recv: %08" PRIx32 "\n", *rshort);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: mpfs_recvshort
+ *
+ * Description:
+ *   Receive response to SDIO command.
+ *
+ * Input Parameters:
+ *   dev    - An instance of the SDIO device interface
+ *   cmd    - Command
+ *   rshort - Buffer for reveiving the response
+ *
+ * Returned Value:
+ *   OK on success; a negated errno on failure.
+ *
+ ****************************************************************************/
+
+static int mpfs_recvshort(FAR struct sdio_dev_s *dev, uint32_t cmd,
+                           uint32_t *rshort)
+{
+  struct mpfs_dev_s *priv = (struct mpfs_dev_s *)dev;
+  int ret = OK;
+
+  if (!(cmd & MMCSD_DATAXFR_MASK))
+    {
+      ret = mpfs_check_recverror(priv);
+    }
+
+  if (rshort)
+    {
+      *rshort = getreg32(MPFS_EMMCSD_SRS04);
+      mcinfo("recv: %08" PRIx32 "\n", *rshort);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: mpfs_recvlong
+ *
+ * Description:
+ *   Receive response to SDIO command.
+ *
+ * Input Parameters:
+ *   dev    - An instance of the SDIO device interface
+ *   cmd    - Command
+ *   rlong  - Buffer for reveiving the response
+ *
+ * Returned Value:
+ *   OK on success; a negated errno on failure.
+ *
+ ****************************************************************************/
+
+static int mpfs_recvlong(FAR struct sdio_dev_s *dev, uint32_t cmd,
+                          uint32_t rlong[4])
+{
+  struct mpfs_dev_s *priv = (struct mpfs_dev_s *)dev;
+  int ret;
+
+  ret = mpfs_check_recverror(priv);
+
+  /* Return the long response */
+
+  if (rlong)
+    {
+      /* Last 8-bits are missing, see SRS04 documemntation, RESP3[23:0]
+       * has only 24 bits unlike RESP2, RESP1 and RESP0 that have 32 bits.
+       * We have to shift left 8 bits to match the proper long response.
+       */
+
+      rlong[3] = getreg32(MPFS_EMMCSD_SRS04) << 8;
+      rlong[2] = getreg32(MPFS_EMMCSD_SRS05) << 8;
+      rlong[1] = getreg32(MPFS_EMMCSD_SRS06) << 8;
+      rlong[0] = getreg32(MPFS_EMMCSD_SRS07) << 8;
+
+      mcinfo("recv: %08" PRIx32 " %08" PRIx32 " %08" PRIx32 " %08" \
+             PRIx32"\n", rlong[0], rlong[1], rlong[2], rlong[3]);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: mpfs_waitenable
+ *
+ * Description:
+ *   Enable/disable of a set of SDIO wait events.  This is part of the
+ *   the EMMCSD_WAITEVENT sequence.  The set of to-be-waited-for events is
+ *   configured before calling mpfs_eventwait.  This is done in this way
+ *   to help the driver to eliminate race conditions between the command
+ *   setup and the subsequent events.
+ *
+ *   The enabled events persist until either (1) EMMCSD_WAITENABLE is called
+ *   again specifying a different set of wait events, or (2) EMMCSD_EVENTWAIT
+ *   returns.
+ *
+ * Input Parameters:
+ *   dev      - An instance of the SDIO device interface
+ *   eventset - A bitset of events to enable or disable (see SDIOWAIT_*
+ *              definitions). 0=disable; 1=enable.
+ *   timeout  - SDIO timeout
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void mpfs_waitenable(FAR struct sdio_dev_s *dev,
+                            sdio_eventset_t eventset, uint32_t timeout)
+{
+  struct mpfs_dev_s *priv = (struct mpfs_dev_s *)dev;
+  uint32_t waitmask = 0;
+
+  mcinfo("eventset: %02" PRIx8 "\n", eventset);
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Disable event-related interrupts */
+
+  mpfs_configwaitints(priv, 0, 0, 0);
+
+  /* Select the interrupt mask that will give us the appropriate wakeup
+   * interrupts.
+   */
+
+  if ((eventset & SDIOWAIT_CMDDONE) != 0)
+    {
+      waitmask |= MPFS_EMMCSD_CMDDONE_MASK;
+    }
+
+  if ((eventset & SDIOWAIT_RESPONSEDONE) != 0)
+    {
+      waitmask |= MPFS_EMMCSD_RESPDONE_MASK;
+    }
+
+  if ((eventset & SDIOWAIT_TRANSFERDONE) != 0)
+    {
+    }
+
+  /* Enable event-related interrupts */
+
+  mpfs_configwaitints(priv, waitmask, eventset, 0);
+
+  /* Check if the timeout event is specified in the event set */
+
+  if ((priv->waitevents & SDIOWAIT_TIMEOUT) != 0)
+    {
+      int delay;
+      int ret;
+
+      /* Yes.. Handle a cornercase: The user request a timeout event but
+       * with timeout == 0?
+       */
+
+      if (!timeout)
+        {
+          priv->wkupevent = SDIOWAIT_TIMEOUT;
+          return;
+        }
+
+      /* Start the watchdog timer */
+
+      delay = MSEC2TICK(timeout);
+      ret   = wd_start(&priv->waitwdog, delay,
+                       mpfs_eventtimeout, (wdparm_t)priv);
+      if (ret < OK)
+        {
+          mcerr("ERROR: wd_start failed: %d\n", ret);
+        }
+    }
+}
+
+/****************************************************************************
+ * Name: mpfs_eventwait
+ *
+ * Description:
+ *   Wait for one of the enabled events to occur (or a timeout).  Note that
+ *   all events enabled by EMMCSD_WAITEVENTS are disabled when mpfs_eventwait
+ *   returns.  EMMCSD_WAITEVENTS must be called again before mpfs_eventwait
+ *   can be used again.
+ *
+ * Input Parameters:
+ *   dev     - An instance of the SDIO device interface
+ *   timeout - Maximum time in milliseconds to wait.  Zero means immediate
+ *             timeout with no wait.  The timeout value is ignored if
+ *             SDIOWAIT_TIMEOUT is not included in the waited-for eventset.
+ *
+ * Returned Value:
+ *   Event set containing the event(s) that ended the wait.  Should always
+ *   be non-zero.  All events are disabled after the wait concludes.
+ *
+ ****************************************************************************/
+
+static sdio_eventset_t mpfs_eventwait(FAR struct sdio_dev_s *dev)
+{
+  struct mpfs_dev_s *priv = (struct mpfs_dev_s *)dev;
+  sdio_eventset_t wkupevent = 0;
+  irqstate_t flags;
+  int ret;
+
+  mcinfo("wait\n");
+
+  /* There is a race condition here... the event may have completed before
+   * we get here.  In this case waitevents will be zero, but wkupevents will
+   * be non-zero (and, hopefully, the semaphore count will also be non-zero.
+   */
+
+  flags = enter_critical_section();
+
+  DEBUGASSERT(priv->waitevents != 0 || priv->wkupevent != 0);
+
+  /* Loop until the event (or the timeout occurs). Race conditions are
+   * avoided by calling mpfs_waitenable prior to triggering the logic that
+   * will cause the wait to terminate.  Under certain race conditions, the
+   * waited-for may have already occurred before this function was called!
+   */
+
+  for (; ; )
+    {
+      /* Wait for an event in event set to occur.  If this the event has
+       * already occurred, then the semaphore will already have been
+       * incremented and there will be no wait.
+       */
+
+      ret = mpfs_takesem(priv);
+      if (ret < 0)
+        {
+          /* Task canceled.  Cancel the wdog (assuming it was started) and
+           * return an SDIO error.
+           */
+
+          wd_cancel(&priv->waitwdog);
+          wkupevent = SDIOWAIT_ERROR;
+          goto errout_with_waitints;
+        }
+
+      wkupevent = priv->wkupevent;
+
+      /* Check if the event has occurred.  When the event has occurred, then
+       * evenset will be set to 0 and wkupevent will be set to a nonzero
+       * value.
+       */
+
+      if (wkupevent != 0)
+        {
+          /* Yes... break out of the loop with wkupevent non-zero */
+
+          break;
+        }
+    }
+
+  /* Disable event-related interrupts */
+
+errout_with_waitints:
+
+  mpfs_configwaitints(priv, 0, 0, 0);
+
+  leave_critical_section(flags);
+  return wkupevent;
+}
+
+/****************************************************************************
+ * Name: mpfs_callbackenable
+ *
+ * Description:
+ *   Enable/disable of a set of SDIO callback events. This is part of the
+ *   the SDIO callback sequence. The set of events is configured to enabled
+ *   callbacks to the function provided in mpfs_registercallback.
+ *
+ *   Events are automatically disabled once the callback is performed and no
+ *   further callback events will occur until they are again enabled by
+ *   calling this method.
+ *
+ * Input Parameters:
+ *   dev      - An instance of the SDIO device interface
+ *   eventset - A bitset of events to enable or disable (see SDIOMEDIA_*
+ *              definitions). 0=disable; 1=enable.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void mpfs_callbackenable(FAR struct sdio_dev_s *dev,
+                                 sdio_eventset_t eventset)
+{
+  struct mpfs_dev_s *priv = (struct mpfs_dev_s *)dev;
+
+  mcinfo("eventset: %02" PRIx8 "\n", eventset);
+  DEBUGASSERT(priv != NULL);
+
+  priv->cbevents = eventset;
+  mpfs_callback(priv);
+}
+
+/****************************************************************************
+ * Name: mpfs_registercallback
+ *
+ * Description:
+ *   Register a callback that that will be invoked on any media status
+ *   change.  Callbacks should not be made from interrupt handlers, rather
+ *   interrupt level events should be handled by calling back on the work
+ *   thread.
+ *
+ *   When this method is called, all callbacks should be disabled until they
+ *   are enabled via a call to EMMCSD_CALLBACKENABLE
+ *
+ * Input Parameters:
+ *   dev      - Device-specific state data
+ *   callback - The function to call on the media change
+ *   arg      - A caller provided value to return with the callback
+ *
+ * Returned Value:
+ *   0 on success; negated errno on failure.
+ *
+ ****************************************************************************/
+
+static int mpfs_registercallback(FAR struct sdio_dev_s *dev,
+                                  worker_t callback, void *arg)
+{
+  struct mpfs_dev_s *priv = (struct mpfs_dev_s *)dev;
+
+  /* Disable callbacks and register this callback and is argument */
+
+  mcinfo("Register %p(%p)\n", callback, arg);
+  DEBUGASSERT(priv != NULL);
+
+  priv->cbevents = 0;
+  priv->cbarg    = arg;
+  priv->callback = callback;
+  return OK;
+}
+
+/****************************************************************************
+ * Name: mpfs_callback
+ *
+ * Description:
+ *   Perform callback.
+ *
+ * Assumptions:
+ *   This function does not execute in the context of an interrupt handler.
+ *   It may be invoked on any user thread or scheduled on the work thread
+ *   from an interrupt handler.
+ *
+ ****************************************************************************/
+
+static void mpfs_callback(void *arg)
+{
+  struct mpfs_dev_s *priv = (struct mpfs_dev_s *)arg;
+
+  /* Is a callback registered? */
+
+  DEBUGASSERT(priv != NULL);
+
+  mcinfo("Callback %p(%p) cbevents: %02" PRIx8 " cdstatus: %02" PRIx8 "\n",
+         priv->callback, priv->cbarg, priv->cbevents, priv->cdstatus);
+
+  if (priv->callback)
+    {
+      /* Yes.. Check for enabled callback events */
+
+      if ((priv->cdstatus & SDIO_STATUS_PRESENT) != 0)
+        {
+          /* Media is present.  Is the media inserted event enabled? */
+
+          if ((priv->cbevents & SDIOMEDIA_INSERTED) == 0)
+            {
+              /* No... return without performing the callback */
+
+              return;
+            }
+        }
+      else
+        {
+          /* Media is not present.  Is the media eject event enabled? */
+
+          if ((priv->cbevents & SDIOMEDIA_EJECTED) == 0)
+            {
+              /* No... return without performing the callback */
+
+              return;
+            }
+        }
+
+      /* Perform the callback, disabling further callbacks.  Of course, the
+       * the callback can (and probably should) re-enable callbacks.
+       */
+
+      priv->cbevents = 0;
+
+      /* Callbacks cannot be performed in the context of an interrupt
+       * handler.  If we are in an interrupt handler, then queue the
+       * callback to be performed later on the work thread.
+       */
+
+      if (up_interrupt_context())
+        {
+          /* Yes.. queue it */
+
+          mcinfo("Queuing callback to %p(%p)\n",
+                 priv->callback, priv->cbarg);
+
+          work_queue(HPWORK, &priv->cbwork, (worker_t)priv->callback,
+                     priv->cbarg, 0);
+        }
+      else
+        {
+          /* No.. then just call the callback here */
+
+          mcinfo("Callback to %p(%p)\n", priv->callback, priv->cbarg);
+          priv->callback(priv->cbarg);
+        }
+    }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: sdio_initialize
+ *
+ * Description:
+ *   Initialize SDIO for operation.
+ *
+ * Input Parameters:
+ *   slotno - Not used.
+ *
+ * Returned Values:
+ *   A reference to an SDIO interface structure.  NULL is returned on
+ *   failures.
+ *
+ ****************************************************************************/
+
+FAR struct sdio_dev_s *sdio_initialize(int slotno)
+{
+  struct mpfs_dev_s *priv = NULL;
+  priv = &g_emmcsd_dev;
+
+  /* Initialize semaphores */
+
+  nxsem_init(&priv->waitsem, 0, 0);
+
+  /* The waitsem semaphore is used for signaling and, hence, should not have
+   * priority inheritance enabled.
+   */
+
+  nxsem_set_protocol(&priv->waitsem, SEM_PRIO_NONE);
+
+  /* Reset the card and assure that it is in the initial, unconfigured
+   * state.
+   */
+
+  if (!mpfs_device_reset(&priv->dev))
+    {
+      return NULL;
+    }
+
+  return &priv->dev;
+}
+
+/****************************************************************************
+ * Name: sdio_mediachange
+ *
+ * Description:
+ *   Called by board-specific logic -- possible from an interrupt handler --
+ *   in order to signal to the driver that a card has been inserted or
+ *   removed from the slot
+ *
+ * Input Parameters:
+ *   dev        - An instance of the SDIO driver device state structure.
+ *   cardinslot - true is a card has been detected in the slot; false if a
+ *                card has been removed from the slot.  Only transitions
+ *                (inserted->removed or removed->inserted should be reported)
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void sdio_mediachange(FAR struct sdio_dev_s *dev, bool cardinslot)
+{
+  struct mpfs_dev_s *priv = (struct mpfs_dev_s *)dev;
+  sdio_statset_t cdstatus;
+  irqstate_t flags;
+
+  /* Update card status */
+
+  flags = enter_critical_section();
+  cdstatus = priv->cdstatus;
+  if (cardinslot)
+    {
+      priv->cdstatus |= SDIO_STATUS_PRESENT;
+    }
+  else
+    {
+      priv->cdstatus &= ~SDIO_STATUS_PRESENT;
+    }
+
+  leave_critical_section(flags);
+
+  mcinfo("cdstatus OLD: %02" PRIx8 " NEW: %02" PRIx8 "\n",
+         cdstatus, priv->cdstatus);
+
+  /* Perform any requested callback if the status has changed */
+
+  if (cdstatus != priv->cdstatus)
+    {
+      mpfs_callback(priv);
+    }
+}
+
+/****************************************************************************
+ * Name: sdio_wrprotect
+ *
+ * Description:
+ *   Called by board-specific logic to report if the card in the slot is
+ *   mechanically write protected.
+ *
+ * Input Parameters:
+ *   dev       - An instance of the SDIO driver device state structure.
+ *   wrprotect - true is a card is writeprotected.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void sdio_wrprotect(FAR struct sdio_dev_s *dev, bool wrprotect)
+{
+  struct mpfs_dev_s *priv = (struct mpfs_dev_s *)dev;
+  irqstate_t flags;
+
+  /* Update card status */
+
+  flags = enter_critical_section();
+  if (wrprotect)
+    {
+      priv->cdstatus |= SDIO_STATUS_WRPROTECTED;
+    }
+  else
+    {
+      priv->cdstatus &= ~SDIO_STATUS_WRPROTECTED;
+    }
+
+  mcinfo("cdstatus: %02" PRIx8 "\n", priv->cdstatus);
+
+  leave_critical_section(flags);
+}
diff --git a/arch/risc-v/src/mpfs/mpfs_emmcsd.h b/arch/risc-v/src/mpfs/mpfs_emmcsd.h
new file mode 100755
index 0000000..747dba6
--- /dev/null
+++ b/arch/risc-v/src/mpfs/mpfs_emmcsd.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+ * arch/risc-v/src/mpfs/mpfs_emmcsd.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_RISCV_SRC_MPFS_MPFS_EMMCSD_H
+#define __ARCH_RISCV_SRC_MPFS_MPFS_EMMCSD_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <sys/types.h>
+#include <stdbool.h>
+
+#include "chip.h"
+#include "hardware/mpfs_emmcsd.h"
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Name: sdio_initialize
+ *
+ * Description:
+ *   Initialize SDIO for operation.
+ *
+ * Input Parameters:
+ *   slotno - Not used.
+ *
+ * Returned Values:
+ *   A reference to an SDIO interface structure.  NULL is returned on
+ *   failures.
+ *
+ ****************************************************************************/
+
+struct sdio_dev_s; /* See include/nuttx/sdio.h */
+FAR struct sdio_dev_s *sdio_initialize(int slotno);
+
+/****************************************************************************
+ * Name: sdio_mediachange
+ *
+ * Description:
+ *   Called by board-specific logic -- possibly from an interrupt handler --
+ *   in order to signal to the driver that a card has been inserted or
+ *   removed from the slot.
+ *
+ * Input Parameters:
+ *   dev        - An instance of the SDIO driver device state structure.
+ *   cardinslot - true is a card has been detected in the slot; false if a
+ *                card has been removed from the slot.  Only transitions
+ *                (inserted->removed or removed->inserted should be reported)
+ *
+ * Returned Values:
+ *   None
+ *
+ ****************************************************************************/
+
+void sdio_mediachange(FAR struct sdio_dev_s *dev, bool cardinslot);
+
+/****************************************************************************
+ * Name: sdio_wrprotect
+ *
+ * Description:
+ *   Called by board-specific logic to report if the card in the slot is
+ *   mechanically write protected.
+ *
+ * Input Parameters:
+ *   dev       - An instance of the SDIO driver device state structure.
+ *   wrprotect - true is a card is writeprotected.
+ *
+ * Returned Values:
+ *   None
+ *
+ ****************************************************************************/
+
+void sdio_wrprotect(FAR struct sdio_dev_s *dev, bool wrprotect);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_RISCV_SRC_MPFS_MPFS_EMMCSD_H */

[incubator-nuttx] 05/05: drivers/mmcsd/mmcsd_spi: fix warning with finfo print

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit f75535607e1348c519784977d9d099f950faf201
Author: Janne Rosberg <ja...@offcode.fi>
AuthorDate: Sat Sep 18 16:41:06 2021 +0300

    drivers/mmcsd/mmcsd_spi: fix warning with finfo print
---
 drivers/mmcsd/mmcsd_spi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mmcsd/mmcsd_spi.c b/drivers/mmcsd/mmcsd_spi.c
index 2b9e0cd..666cd15 100644
--- a/drivers/mmcsd/mmcsd_spi.c
+++ b/drivers/mmcsd/mmcsd_spi.c
@@ -1297,7 +1297,7 @@ static ssize_t mmcsd_read(FAR struct inode *inode, unsigned char *buffer,
   SPI_SEND(spi, 0xff);
   mmcsd_semgive(slot);
 
-  finfo("Read %d bytes:\n", nbytes);
+  finfo("Read %zu bytes:\n", nbytes);
   mmcsd_dumpbuffer("Read buffer", buffer, nbytes);
   return nsectors;