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

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


The following commit(s) were added to refs/heads/master by this push:
     new 23c39f9dab mmcsd: add multi partitions support
23c39f9dab is described below

commit 23c39f9dab8d0c1780ea649dc8c74b5f7056a9ac
Author: wanggang26 <wanggan...@xiaomi.com>
AuthorDate: Tue Oct 15 14:35:19 2024 +0800

    mmcsd: add multi partitions support
    
    include boot0,boot1,gp1,gp2,gp3,gp4,rpmb
    
    Signed-off-by: wanggang26 <wanggan...@xiaomi.com>
---
 drivers/mmcsd/mmcsd.h        |  15 +-
 drivers/mmcsd/mmcsd_extcsd.h |  76 +++++++++
 drivers/mmcsd/mmcsd_sdio.c   | 361 ++++++++++++++++++++++++++++++++++---------
 drivers/mmcsd/mmcsd_sdio.h   |  12 ++
 4 files changed, 387 insertions(+), 77 deletions(-)

diff --git a/drivers/mmcsd/mmcsd.h b/drivers/mmcsd/mmcsd.h
index 1f374af86e..67cb2a3ec6 100644
--- a/drivers/mmcsd/mmcsd.h
+++ b/drivers/mmcsd/mmcsd.h
@@ -42,6 +42,8 @@
 #  undef CONFIG_MMCSD_DUMPALL
 #endif
 
+#define MMCSD_PART_COUNT             8
+
 /* Card type */
 
 #define MMCSD_CARDTYPE_UNKNOWN       0  /* Unknown card type */
@@ -63,18 +65,19 @@
 struct mmcsd_part_s
 {
   FAR struct mmcsd_state_s *priv;
-  uint32_t nblocks; /* Number of blocks */
+  blkcnt_t nblocks; /* Number of blocks */
 };
 
 /* This structure is contains the unique state of the MMC/SD block driver */
 
 struct mmcsd_state_s
 {
-  FAR struct sdio_dev_s *dev;      /* The SDIO device bound to this instance */
-  uint8_t  crefs;                  /* Open references on the driver */
-  mutex_t  lock;                   /* Assures mutually exclusive access to the 
slot */
-  int      minor;                  /* Device number */
-  struct mmcsd_part_s part;        /* Partition data */
+  FAR struct sdio_dev_s *dev;                  /* The SDIO device bound to 
this instance */
+  uint8_t  crefs;                              /* Open references on the 
driver */
+  mutex_t  lock;                               /* Assures mutually exclusive 
access to the slot */
+  int      minor;                              /* Device number */
+  struct mmcsd_part_s part[MMCSD_PART_COUNT];  /* Partition data */
+  uint32_t partnum;                            /* Partition number */
 
   /* Status flags */
 
diff --git a/drivers/mmcsd/mmcsd_extcsd.h b/drivers/mmcsd/mmcsd_extcsd.h
new file mode 100644
index 0000000000..60070e9fd3
--- /dev/null
+++ b/drivers/mmcsd/mmcsd_extcsd.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+ * drivers/mmcsd/mmcsd_extcsd.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 __DRIVERS_MMCSD_MMCSD_EXTCSD_H
+#define __DRIVERS_MMCSD_MMCSD_EXTCSD_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <stdint.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* The Extended CSD register defines the Device properties and selected
+ * modes. It is 512 bytes long. The most significant 320 bytes are the
+ * Properties segment, that defines the Device capabilities and cannot be
+ * modified by the host. The lower 192 bytes are the Modes segment, that
+ * defines the configuration the Device is working in. These modes can be
+ * changed by the host by means of the SWITCH command.
+ * Multi bytes field is interpreted in little endian byte order.
+ */
+
+#define MMCSD_PART_SETTING_COMPLETED               0x1
+#define MMCSD_PART_SUPPORT_PART_EN                 0x1
+
+#define MMCSD_EXTCSD_GP_SIZE_MULT                  143  /* R/W */
+#define MMCSD_EXTCSD_PARTITION_SETTING_COMPLETED   155  /* R/W */
+#define MMCSD_EXTCSD_PARTITION_SUPPORT             160  /* RO */
+#define MMCSD_EXTCSD_RPMB_SIZE_MULT                168  /* RO */
+#define MMCSD_EXTCSD_HC_WP_GRP_SIZE                221  /* RO */
+#define MMCSD_EXTCSD_HC_ERASE_GRP_SIZE             224  /* RO */
+#define MMCSD_EXTCSD_BOOT_SIZE_MULT                226  /* RO */
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions Definitions
+ ****************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+#endif /* __DRIVERS_MMCSD_MMCSD_EXTCSD_H */
diff --git a/drivers/mmcsd/mmcsd_sdio.c b/drivers/mmcsd/mmcsd_sdio.c
index 8cf5c72081..2683ebdaa0 100644
--- a/drivers/mmcsd/mmcsd_sdio.c
+++ b/drivers/mmcsd/mmcsd_sdio.c
@@ -55,11 +55,16 @@
 #include "mmcsd.h"
 #include "mmcsd_sdio.h"
 #include "mmcsd_csd.h"
+#include "mmcsd_extcsd.h"
 
 /****************************************************************************
  * Pre-processor Definitions
  ****************************************************************************/
 
+#define MCSD_SZ_512             0x00000200UL
+#define MCSD_SZ_128K            0x00020000UL
+#define MCSD_SZ_512K            0x00080000UL
+
 /* The maximum number of references on the driver (because a uint8_t is used.
  * Use a larger type if more references are needed.
  */
@@ -153,6 +158,7 @@ static int     mmcsd_get_r1(FAR struct mmcsd_state_s *priv,
                             FAR uint32_t *r1);
 static int     mmcsd_verifystate(FAR struct mmcsd_state_s *priv,
                                  uint32_t status);
+static int     mmcsd_switch(FAR struct mmcsd_state_s *priv, uint32_t arg);
 
 /* Transfer helpers *********************************************************/
 
@@ -169,18 +175,18 @@ static int     mmcsd_setblocklen(FAR struct mmcsd_state_s 
*priv,
 static int     mmcsd_setblockcount(FAR struct mmcsd_state_s *priv,
                                    uint32_t nblocks);
 #endif
-static ssize_t mmcsd_readsingle(FAR struct mmcsd_state_s *priv,
+static ssize_t mmcsd_readsingle(FAR struct mmcsd_part_s *part,
                                 FAR uint8_t *buffer, off_t startblock);
 #if MMCSD_MULTIBLOCK_LIMIT != 1
-static ssize_t mmcsd_readmultiple(FAR struct mmcsd_state_s *priv,
+static ssize_t mmcsd_readmultiple(FAR struct mmcsd_part_s *part,
                                   FAR uint8_t *buffer, off_t startblock,
                                   size_t nblocks);
 #endif
-static ssize_t mmcsd_writesingle(FAR struct mmcsd_state_s *priv,
+static ssize_t mmcsd_writesingle(FAR struct mmcsd_part_s *part,
                                  FAR const uint8_t *buffer,
                                  off_t startblock);
 #if MMCSD_MULTIBLOCK_LIMIT != 1
-static ssize_t mmcsd_writemultiple(FAR struct mmcsd_state_s *priv,
+static ssize_t mmcsd_writemultiple(FAR struct mmcsd_part_s *part,
                                    FAR const uint8_t *buffer,
                                    off_t startblock,
                                    size_t nblocks);
@@ -209,6 +215,8 @@ static int     mmcsd_widebus(FAR struct mmcsd_state_s 
*priv);
 static int     mmcsd_mmcinitialize(FAR struct mmcsd_state_s *priv);
 static int     mmcsd_read_extcsd(FAR struct mmcsd_state_s *priv,
                                  FAR uint8_t *extcsd);
+static void    mmcsd_decode_extcsd(FAR struct mmcsd_state_s *priv,
+                                   FAR const uint8_t *extcsd);
 #endif
 static int     mmcsd_sdinitialize(FAR struct mmcsd_state_s *priv);
 static int     mmcsd_cardidentify(FAR struct mmcsd_state_s *priv);
@@ -216,9 +224,9 @@ static int     mmcsd_probe(FAR struct mmcsd_state_s *priv);
 static int     mmcsd_removed(FAR struct mmcsd_state_s *priv);
 static int     mmcsd_hwinitialize(FAR struct mmcsd_state_s *priv);
 #ifdef CONFIG_MMCSD_IOCSUPPORT
-static int     mmcsd_iocmd(FAR struct mmcsd_state_s *priv,
+static int     mmcsd_iocmd(FAR struct mmcsd_part_s *part,
                            FAR struct mmc_ioc_cmd *ic_ptr);
-static int     mmcsd_multi_iocmd(FAR struct mmcsd_state_s *priv,
+static int     mmcsd_multi_iocmd(FAR struct mmcsd_part_s *part,
                                  FAR struct mmc_ioc_multi_cmd *imc_ptr);
 #endif
 
@@ -236,6 +244,18 @@ static const struct block_operations g_bops =
   mmcsd_ioctl     /* ioctl    */
 };
 
+static FAR const char *g_partname[MMCSD_PART_COUNT] =
+    {
+      "",
+      "boot0",
+      "boot1",
+      "rpmb",
+      "gp1",
+      "gp2",
+      "gp3",
+      "gp4"
+    };
+
 /****************************************************************************
  * Private Functions
  ****************************************************************************/
@@ -464,7 +484,7 @@ static int mmcsd_recv_r6(FAR struct mmcsd_state_s *priv, 
uint32_t cmd)
  *   Obtain the SD card's Configuration Register (SCR)
  *
  * Returned Value:
- *   OK on success; a negated ernno on failure.
+ *   OK on success; a negated errno on failure.
  *
  ****************************************************************************/
 
@@ -660,15 +680,15 @@ static void mmcsd_decode_csd(FAR struct mmcsd_state_s 
*priv, uint32_t csd[4])
 
           if (csize != MMCSD_CSD_CSIZE_THRESHOLD)
             {
-              priv->part.nblocks = ((uint32_t)csize + 1) *
-                                   (1 << (csizemult + 2));
+              priv->part[0].nblocks = ((uint32_t)csize + 1) *
+                                      (1 << (csizemult + 2));
             }
 
           if (priv->blocksize > 512)
             {
               if (csize != MMCSD_CSD_CSIZE_THRESHOLD)
                 {
-                  priv->part.nblocks <<= (priv->blockshift - 9);
+                  priv->part[0].nblocks <<= (priv->blockshift - 9);
                 }
 
               priv->blocksize   = 512;
@@ -703,7 +723,7 @@ static void mmcsd_decode_csd(FAR struct mmcsd_state_s 
*priv, uint32_t csd[4])
 
           priv->blockshift      = 9;
           priv->blocksize       = 1 << 9;
-          priv->part.nblocks    = (csize + 1) << (19 - priv->blockshift);
+          priv->part[0].nblocks = (csize + 1) << (19 - priv->blockshift);
 
 #ifdef CONFIG_DEBUG_FS_INFO
           decoded.u.sdblock.csize        = csize;
@@ -724,7 +744,7 @@ static void mmcsd_decode_csd(FAR struct mmcsd_state_s 
*priv, uint32_t csd[4])
                                   ((csd[2] >> 30) & 3);
       uint8_t  csizemult        = (csd[2] >> 15) & 7;
 
-      priv->part.nblocks        = ((uint32_t)csize + 1) *
+      priv->part[0].nblocks     = ((uint32_t)csize + 1) *
                                   (1 << (csizemult + 2));
       priv->blockshift          = readbllen;
       priv->blocksize           = (1 << readbllen);
@@ -739,7 +759,7 @@ static void mmcsd_decode_csd(FAR struct mmcsd_state_s 
*priv, uint32_t csd[4])
 
       if (priv->blocksize > 512)
         {
-          priv->part.nblocks  <<= (priv->blockshift - 9);
+          priv->part[0].nblocks <<= (priv->blockshift - 9);
           priv->blocksize       = 512;
           priv->blockshift      = 9;
         }
@@ -896,8 +916,9 @@ static void mmcsd_decode_csd(FAR struct mmcsd_state_s 
*priv, uint32_t csd[4])
         decoded.fileformat, decoded.mmcecc, decoded.crc);
 
   finfo("Capacity: %luKb, Block size: %db, nblocks: %d wrprotect: %d\n",
-        (unsigned long)MMCSD_CAPACITY(priv->part.nblocks, priv->blockshift),
-        priv->blocksize, priv->part.nblocks, priv->wrprotect);
+        (unsigned long)MMCSD_CAPACITY(priv->part[0].nblocks,
+                                      priv->blockshift),
+        priv->blocksize, priv->part[0].nblocks, priv->wrprotect);
 #endif
 }
 
@@ -1044,7 +1065,6 @@ static void mmcsd_decode_scr(FAR struct mmcsd_state_s 
*priv, uint32_t scr[2])
 #endif
 }
 
-#ifdef CONFIG_MMCSD_IOCSUPPORT
 /****************************************************************************
  * Name: mmcsd_switch
  *
@@ -1100,8 +1120,6 @@ static int mmcsd_switch(FAR struct mmcsd_state_s *priv, 
uint32_t arg)
   return mmcsd_recv_r1(priv, MMCSD_CMD6);
 }
 
-#endif /* CONFIG_MMCSD_IOCSUPPORT */
-
 /****************************************************************************
  * Name: mmcsd_get_r1
  *
@@ -1311,7 +1329,7 @@ static int mmcsd_transferready(FAR struct mmcsd_state_s 
*priv)
       if (ret != OK)
         {
           ferr("ERROR: mmcsd_get_r1 failed: %d\n", ret);
-          goto errorout;
+          return ret;
         }
 
       /* Now check if the card is in the expected transfer state. */
@@ -1341,8 +1359,7 @@ static int mmcsd_transferready(FAR struct mmcsd_state_s 
*priv)
            */
 
           ferr("ERROR: Unexpected R1 state: %08" PRIx32 "\n", r1);
-          ret = -EINVAL;
-          goto errorout;
+          return -EINVAL;
         }
 
       /* Do not hog the CPU */
@@ -1364,10 +1381,6 @@ static int mmcsd_transferready(FAR struct mmcsd_state_s 
*priv)
   while (elapsed < TICK_PER_SEC);
 
   return -ETIMEDOUT;
-
-errorout:
-  mmcsd_removed(priv);
-  return ret;
 }
 
 /****************************************************************************
@@ -1466,9 +1479,11 @@ static int mmcsd_setblockcount(FAR struct mmcsd_state_s 
*priv,
  *
  ****************************************************************************/
 
-static ssize_t mmcsd_readsingle(FAR struct mmcsd_state_s *priv,
+static ssize_t mmcsd_readsingle(FAR struct mmcsd_part_s *part,
                                 FAR uint8_t *buffer, off_t startblock)
 {
+  FAR struct mmcsd_state_s *priv = part->priv;
+  uint32_t partnum = part - priv->part;
   off_t offset;
   int ret;
 
@@ -1483,6 +1498,20 @@ static ssize_t mmcsd_readsingle(FAR struct mmcsd_state_s 
*priv,
       return -EPERM;
     }
 
+  if (priv->partnum != partnum)
+    {
+      ret = mmcsd_switch(priv, MMC_CMD6_MODE(MMC_CMD6_MODE_WRITE_BYTE) |
+                               MMC_CMD6_INDEX(EXT_CSD_PART_CONF) |
+                               MMC_CMD6_VALUE(partnum));
+      if (ret != OK)
+        {
+          ferr("ERROR: mmcsd_switch failed: %d\n", ret);
+          return ret;
+        }
+
+      priv->partnum = partnum;
+    }
+
 #if defined(CONFIG_SDIO_DMA) && defined(CONFIG_ARCH_HAVE_SDIO_PREFLIGHT)
   /* If we think we are going to perform a DMA transfer, make sure that we
    * will be able to before we commit the card to the operation.
@@ -1599,16 +1628,18 @@ static ssize_t mmcsd_readsingle(FAR struct 
mmcsd_state_s *priv,
  ****************************************************************************/
 
 #if MMCSD_MULTIBLOCK_LIMIT != 1
-static ssize_t mmcsd_readmultiple(FAR struct mmcsd_state_s *priv,
+static ssize_t mmcsd_readmultiple(FAR struct mmcsd_part_s *part,
                                   FAR uint8_t *buffer, off_t startblock,
                                   size_t nblocks)
 {
+  FAR struct mmcsd_state_s *priv = part->priv;
   size_t nbytes = nblocks << priv->blockshift;
+  uint32_t partnum = part - priv->part;
   off_t  offset;
   int ret;
 
   finfo("startblock=%jd nblocks=%zu\n", (intmax_t)startblock, nblocks);
-  DEBUGASSERT(priv != NULL && buffer != NULL && nblocks > 1);
+  DEBUGASSERT(priv != NULL && buffer != NULL);
 
   /* Check if the card is locked */
 
@@ -1618,6 +1649,20 @@ static ssize_t mmcsd_readmultiple(FAR struct 
mmcsd_state_s *priv,
       return -EPERM;
     }
 
+  if (priv->partnum != partnum)
+    {
+      ret = mmcsd_switch(priv, MMC_CMD6_MODE(MMC_CMD6_MODE_WRITE_BYTE) |
+                               MMC_CMD6_INDEX(EXT_CSD_PART_CONF) |
+                               MMC_CMD6_VALUE(partnum));
+      if (ret != OK)
+        {
+          ferr("ERROR: mmcsd_switch failed: %d\n", ret);
+          return ret;
+        }
+
+      priv->partnum = partnum;
+    }
+
 #if defined(CONFIG_SDIO_DMA) && defined(CONFIG_ARCH_HAVE_SDIO_PREFLIGHT)
   /* If we think we are going to perform a DMA transfer, make sure that we
    * will be able to before we commit the card to the operation.
@@ -1758,9 +1803,11 @@ static ssize_t mmcsd_readmultiple(FAR struct 
mmcsd_state_s *priv,
  *
  ****************************************************************************/
 
-static ssize_t mmcsd_writesingle(FAR struct mmcsd_state_s *priv,
+static ssize_t mmcsd_writesingle(FAR struct mmcsd_part_s *part,
                                  FAR const uint8_t *buffer, off_t startblock)
 {
+  FAR struct mmcsd_state_s *priv = part->priv;
+  uint32_t partnum = part - priv->part;
   off_t offset;
   int ret;
 
@@ -1777,6 +1824,20 @@ static ssize_t mmcsd_writesingle(FAR struct 
mmcsd_state_s *priv,
       return -EPERM;
     }
 
+  if (priv->partnum != partnum)
+    {
+      ret = mmcsd_switch(priv, MMC_CMD6_MODE(MMC_CMD6_MODE_WRITE_BYTE) |
+                               MMC_CMD6_INDEX(EXT_CSD_PART_CONF) |
+                               MMC_CMD6_VALUE(partnum));
+      if (ret != OK)
+        {
+          ferr("ERROR: mmcsd_switch failed: %d\n", ret);
+          return ret;
+        }
+
+      priv->partnum = partnum;
+    }
+
 #if defined(CONFIG_SDIO_DMA) && defined(CONFIG_ARCH_HAVE_SDIO_PREFLIGHT)
   /* If we think we are going to perform a DMA transfer, make sure that we
    * will be able to before we commit the card to the operation.
@@ -1926,17 +1987,19 @@ static ssize_t mmcsd_writesingle(FAR struct 
mmcsd_state_s *priv,
  ****************************************************************************/
 
 #if MMCSD_MULTIBLOCK_LIMIT != 1
-static ssize_t mmcsd_writemultiple(FAR struct mmcsd_state_s *priv,
+static ssize_t mmcsd_writemultiple(FAR struct mmcsd_part_s *part,
                                    FAR const uint8_t *buffer,
                                    off_t startblock, size_t nblocks)
 {
+  FAR struct mmcsd_state_s *priv = part->priv;
   size_t nbytes = nblocks << priv->blockshift;
+  uint32_t partnum = part - priv->part;
   off_t  offset;
   int ret;
   int evret = OK;
 
   finfo("startblock=%jd nblocks=%zu\n", (intmax_t)startblock, nblocks);
-  DEBUGASSERT(priv != NULL && buffer != NULL && nblocks > 1);
+  DEBUGASSERT(priv != NULL && buffer != NULL);
 
   /* Check if the card is locked or write protected (either via software or
    * via the mechanical write protect on the card)
@@ -1948,6 +2011,20 @@ static ssize_t mmcsd_writemultiple(FAR struct 
mmcsd_state_s *priv,
       return -EPERM;
     }
 
+  if (priv->partnum != partnum)
+    {
+      ret = mmcsd_switch(priv, MMC_CMD6_MODE(MMC_CMD6_MODE_WRITE_BYTE) |
+                               MMC_CMD6_INDEX(EXT_CSD_PART_CONF) |
+                               MMC_CMD6_VALUE(partnum));
+      if (ret != OK)
+        {
+          ferr("ERROR: mmcsd_switch failed: %d\n", ret);
+          return ret;
+        }
+
+      priv->partnum = partnum;
+    }
+
 #if defined(CONFIG_SDIO_DMA) && defined(CONFIG_ARCH_HAVE_SDIO_PREFLIGHT)
   /* If we think we are going to perform a DMA transfer, make sure that we
    * will be able to before we commit the card to the operation.
@@ -2034,11 +2111,25 @@ static ssize_t mmcsd_writemultiple(FAR struct 
mmcsd_state_s *priv,
         }
     }
 
+  /* Data to the RPMB is programmed with the WRITE_MULTIPLE_BLOCK(CMD25),
+   * in prior to the command CMD25 the block count is set by CMD23,
+   * with argument bit [31] set as 1 to indicate Reliable Write type of
+   * programming access.
+   */
+
 #ifdef CONFIG_MMCSD_MMCSUPPORT
-  if (IS_MMC(priv->type) || (IS_SD(priv->type) && priv->cmd23support))
-#else
-  if (IS_SD(priv->type) && priv->cmd23support)
+  if (IS_MMC(priv->type))
+    {
+      ret = mmcsd_setblockcount(priv, priv->partnum == MMCSD_PART_RPMB ?
+                                ((1 << 31) | nblocks) : nblocks);
+      if (ret != OK)
+        {
+          return ret;
+        }
+    }
+  else
 #endif
+  if (IS_SD(priv->type) && priv->cmd23support)
     {
       ret = mmcsd_setblockcount(priv, nblocks);
       if (ret != OK)
@@ -2273,7 +2364,7 @@ static ssize_t mmcsd_read(FAR struct inode *inode, 
unsigned char *buffer,
 #if MMCSD_MULTIBLOCK_LIMIT == 1
           /* Read each block using only the single block transfer method */
 
-          nread = mmcsd_readsingle(priv, buffer, sector);
+          nread = mmcsd_readsingle(part, buffer, sector);
 #else
           nread = endsector - sector;
           if (nread > MMCSD_MULTIBLOCK_LIMIT)
@@ -2283,11 +2374,11 @@ static ssize_t mmcsd_read(FAR struct inode *inode, 
unsigned char *buffer,
 
           if (nread == 1)
             {
-              nread = mmcsd_readsingle(priv, buffer, sector);
+              nread = mmcsd_readsingle(part, buffer, sector);
             }
           else
             {
-              nread = mmcsd_readmultiple(priv, buffer, sector, nread);
+              nread = mmcsd_readmultiple(part, buffer, sector, nread);
             }
 
 #endif
@@ -2354,7 +2445,7 @@ static ssize_t mmcsd_write(FAR struct inode *inode,
 #if MMCSD_MULTIBLOCK_LIMIT == 1
           /* Write each block using only the single block transfer method */
 
-          nwrite = mmcsd_writesingle(priv, buffer, sector);
+          nwrite = mmcsd_writesingle(part, buffer, sector);
 #else
           nwrite = endsector - sector;
           if (nwrite > MMCSD_MULTIBLOCK_LIMIT)
@@ -2364,11 +2455,11 @@ static ssize_t mmcsd_write(FAR struct inode *inode,
 
           if (nwrite == 1)
             {
-              nwrite = mmcsd_writesingle(priv, buffer, sector);
+              nwrite = mmcsd_writesingle(part, buffer, sector);
             }
           else
             {
-              nwrite = mmcsd_writemultiple(priv, buffer, sector, nwrite);
+              nwrite = mmcsd_writemultiple(part, buffer, sector, nwrite);
             }
 
 #endif
@@ -2442,8 +2533,8 @@ static int mmcsd_geometry(FAR struct inode *inode, struct 
geometry *geometry)
           finfo("available: true mediachanged: %s writeenabled: %s\n",
                  geometry->geo_mediachanged ? "true" : "false",
                  geometry->geo_writeenabled ? "true" : "false");
-          finfo("nsectors: %lu sectorsize: %" PRIi16 "\n",
-                 (unsigned long)geometry->geo_nsectors,
+          finfo("nsectors: %" PRIuOFF " sectorsize: %" PRIi16 "\n",
+                 geometry->geo_nsectors,
                  geometry->geo_sectorsize);
 
           priv->mediachanged = false;
@@ -2520,7 +2611,7 @@ static int mmcsd_ioctl(FAR struct inode *inode, int cmd, 
unsigned long arg)
     case MMC_IOC_CMD: /* MMCSD device ioctl commands */
       {
         finfo("MMC_IOC_CMD\n");
-        ret = mmcsd_iocmd(priv, (FAR struct mmc_ioc_cmd *)arg);
+        ret = mmcsd_iocmd(part, (FAR struct mmc_ioc_cmd *)arg);
         if (ret != OK)
           {
             ferr("ERROR: mmcsd_iocmd failed: %d\n", ret);
@@ -2531,7 +2622,7 @@ static int mmcsd_ioctl(FAR struct inode *inode, int cmd, 
unsigned long arg)
     case MMC_IOC_MULTI_CMD: /* MMCSD device ioctl muti commands */
       {
         finfo("MMC_IOC_MULTI_CMD\n");
-        ret = mmcsd_multi_iocmd(priv, (FAR struct mmc_ioc_multi_cmd *)arg);
+        ret = mmcsd_multi_iocmd(part, (FAR struct mmc_ioc_multi_cmd *)arg);
         if (ret != OK)
           {
             ferr("ERROR: mmcsd_iocmd failed: %d\n", ret);
@@ -2787,6 +2878,77 @@ static int mmcsd_widebus(FAR struct mmcsd_state_s *priv)
   return OK;
 }
 
+#ifdef CONFIG_MMCSD_MMCSUPPORT
+/****************************************************************************
+ * Name: mmcsd_decode_extcsd
+ *
+ * Description:
+ *   Get all partitions size in block numbers
+ *
+ ****************************************************************************/
+
+static void mmcsd_decode_extcsd(FAR struct mmcsd_state_s *priv,
+                                FAR const uint8_t *extcsd)
+{
+  uint8_t hc_erase_grp_sz;
+  uint8_t hc_wp_grp_sz;
+  int idx;
+
+  /* User data partition size = SEC_COUNT x 512B for densities greater
+   * than 2 GB
+   */
+
+  priv->part[0].nblocks = (extcsd[215] << 24) | (extcsd[214] << 16) |
+                          (extcsd[213] << 8) | extcsd[212];
+  finfo("MMC ext CSD read succsesfully, number of block %" PRIuOFF "\n",
+                                                priv->part[0].nblocks);
+
+  if (extcsd[MMCSD_EXTCSD_PARTITION_SUPPORT] & MMCSD_PART_SUPPORT_PART_EN)
+    {
+      /* Boot partition size = 128KB byte x BOOT_SIZE_MULT */
+
+      priv->part[MMCSD_PART_BOOT0].nblocks =
+            extcsd[MMCSD_EXTCSD_BOOT_SIZE_MULT] * MCSD_SZ_128K / MCSD_SZ_512;
+      priv->part[MMCSD_PART_BOOT1].nblocks =
+            extcsd[MMCSD_EXTCSD_BOOT_SIZE_MULT] * MCSD_SZ_128K / MCSD_SZ_512;
+
+      /* RPMB partition size = 128KB byte x RPMB_SIZE_MULT */
+
+      priv->part[MMCSD_PART_RPMB].nblocks =
+            extcsd[MMCSD_EXTCSD_RPMB_SIZE_MULT] * MCSD_SZ_128K / MCSD_SZ_512;
+
+      hc_erase_grp_sz = extcsd[MMCSD_EXTCSD_HC_ERASE_GRP_SIZE];
+      hc_wp_grp_sz = extcsd[MMCSD_EXTCSD_HC_WP_GRP_SIZE];
+
+      for (idx = 0; idx < 4; idx++)
+        {
+          if (!extcsd[MMCSD_EXTCSD_GP_SIZE_MULT + idx * 3] &&
+              !extcsd[MMCSD_EXTCSD_GP_SIZE_MULT + idx * 3 + 1] &&
+              !extcsd[MMCSD_EXTCSD_GP_SIZE_MULT + idx * 3 + 2])
+            {
+              continue;
+            }
+
+          if (extcsd[MMCSD_EXTCSD_PARTITION_SETTING_COMPLETED] == 0)
+            {
+              finfo("Partition size defined without setting complete!\n");
+              break;
+            }
+
+          /* General purpose partition size = (GP_SIZE_MULT_X_2 << 16 +
+           *  GP_SIZE_MULT_X_1 << 8 + GP_SIZE_MULT_X_0) x HC_WP_GRP_SIZE x
+           *  HC_ERASE_GRP_SIZE x 512kBytes
+           */
+
+          priv->part[MMCSD_PART_GENP0 + idx].nblocks =
+                ((extcsd[MMCSD_EXTCSD_GP_SIZE_MULT + idx * 3 + 2] << 16) +
+                 (extcsd[MMCSD_EXTCSD_GP_SIZE_MULT + idx * 3 + 1] << 8) +
+                 extcsd[MMCSD_EXTCSD_GP_SIZE_MULT + idx * 3]) *
+                hc_erase_grp_sz * hc_wp_grp_sz * MCSD_SZ_512K / MCSD_SZ_512;
+        }
+    }
+}
+
 /****************************************************************************
  * Name: mmcsd_mmcinitialize
  *
@@ -2796,7 +2958,6 @@ static int mmcsd_widebus(FAR struct mmcsd_state_s *priv)
  *
  ****************************************************************************/
 
-#ifdef CONFIG_MMCSD_MMCSUPPORT
 static int mmcsd_mmcinitialize(FAR struct mmcsd_state_s *priv)
 {
   uint8_t extcsd[512] aligned_data(16);
@@ -2938,6 +3099,8 @@ static int mmcsd_mmcinitialize(FAR struct mmcsd_state_s 
*priv)
           ferr("ERROR: Failed to determinate number of blocks: %d\n", ret);
           return ret;
         }
+
+      mmcsd_decode_extcsd(priv, extcsd);
     }
 
   mmcsd_decode_csd(priv, priv->csd);
@@ -3071,12 +3234,6 @@ static int mmcsd_read_extcsd(FAR struct mmcsd_state_s 
*priv,
       return ret;
     }
 
-  priv->part.nblocks = (extcsd[215] << 24) | (extcsd[214] << 16) |
-                       (extcsd[213] << 8) | extcsd[212];
-
-  finfo("MMC ext CSD read succsesfully, number of block %" PRId32 "\n",
-        priv->part.nblocks);
-
   SDIO_GOTEXTCSD(priv->dev, extcsd);
 
   /* Return value:  One sector read */
@@ -3354,9 +3511,10 @@ static int mmcsd_general_cmd_read(FAR struct 
mmcsd_state_s *priv,
  *
  ****************************************************************************/
 
-static int mmcsd_iocmd(FAR struct mmcsd_state_s *priv,
+static int mmcsd_iocmd(FAR struct mmcsd_part_s *part,
                        FAR struct mmc_ioc_cmd *ic_ptr)
 {
+  FAR struct mmcsd_state_s *priv = part->priv;
   uint32_t opcode;
   int ret = OK;
 
@@ -3403,6 +3561,54 @@ static int mmcsd_iocmd(FAR struct mmcsd_state_s *priv,
           }
       }
       break;
+#if MMCSD_MULTIBLOCK_LIMIT != 1
+    case MMCSD_CMDIDX18: /* Read multi blocks commands */
+      {
+        if (ic_ptr->blocks > 0)
+          {
+            /* Address argument in CMD18, 25 will be ignored in rpmb case */
+
+            ret = mmcsd_readmultiple(part,
+                                  (FAR uint8_t *)(uintptr_t)ic_ptr->data_ptr,
+                                   ic_ptr->arg, ic_ptr->blocks);
+            if (ret != ic_ptr->blocks)
+              {
+                ferr("ERROR: mmcsd_readmultiple failed: %d\n", ret);
+              }
+            else
+              {
+                ret = OK;
+              }
+          }
+      }
+      break;
+    case MMCSD_CMDIDX23: /* Set transfer block counts */
+      {
+        ret = mmcsd_setblockcount(priv,
+                              ic_ptr->blocks ? ic_ptr->blocks : ic_ptr->arg);
+      }
+      break;
+    case MMCSD_CMDIDX25: /* Write multi blocks commands */
+      {
+        if (ic_ptr->blocks > 0)
+          {
+            /* Address argument in CMD18, 25 will be ignored in rpmb case */
+
+            ret = mmcsd_writemultiple(part,
+                            (const FAR uint8_t *)(uintptr_t)ic_ptr->data_ptr,
+                             ic_ptr->arg, ic_ptr->blocks);
+            if (ret != ic_ptr->blocks)
+              {
+                ferr("ERROR: mmcsd_writemultiple failed: %d\n", ret);
+              }
+            else
+              {
+                ret = OK;
+              }
+          }
+      }
+      break;
+#endif
     case MMCSD_CMDIDX56: /* General commands */
       {
         if (ic_ptr->write_flag)
@@ -3446,9 +3652,10 @@ static int mmcsd_iocmd(FAR struct mmcsd_state_s *priv,
  *
  ****************************************************************************/
 
-static int mmcsd_multi_iocmd(FAR struct mmcsd_state_s *priv,
+static int mmcsd_multi_iocmd(FAR struct mmcsd_part_s *part,
                              FAR struct mmc_ioc_multi_cmd *imc_ptr)
 {
+  FAR struct mmcsd_state_s *priv = part->priv;
   int ret;
   int i;
 
@@ -3462,7 +3669,7 @@ static int mmcsd_multi_iocmd(FAR struct mmcsd_state_s 
*priv,
 
   for (i = 0; i < imc_ptr->num_of_cmds; ++i)
     {
-      ret = mmcsd_iocmd(priv, &imc_ptr->cmds[i]);
+      ret = mmcsd_iocmd(part, &imc_ptr->cmds[i]);
       if (ret != OK)
         {
           ferr("cmds %d failed.\n", i);
@@ -4019,8 +4226,9 @@ static int mmcsd_cardidentify(FAR struct mmcsd_state_s 
*priv)
 
 static int mmcsd_probe(FAR struct mmcsd_state_s *priv)
 {
-  char devname[16];
+  char devname[32];
   int ret;
+  int i;
 
   finfo("type: %d probed: %d\n", priv->type, priv->probed);
 
@@ -4114,8 +4322,8 @@ static int mmcsd_probe(FAR struct mmcsd_state_s *priv)
             {
               /* Yes...  */
 
-              finfo("Capacity: %" PRIu32 " Kbytes\n",
-                    MMCSD_CAPACITY(priv->part.nblocks,
+              finfo("Capacity: %" PRIuOFF " Kbytes\n",
+                    MMCSD_CAPACITY(priv->part[0].nblocks,
                                    priv->blockshift));
               priv->mediachanged = true;
             }
@@ -4123,15 +4331,17 @@ static int mmcsd_probe(FAR struct mmcsd_state_s *priv)
           /* When the card is identified, we have probed this card */
 
           priv->probed = true;
-
-          /* Create a MMCSD device name */
-
-          priv->part.priv = priv;
-          snprintf(devname, sizeof(devname), "/dev/mmcsd%d", priv->minor);
-
-          /* Inode private data is a reference to the MMCSD state structure */
-
-          register_blockdriver(devname, &g_bops, 0666, &priv->part);
+          for (i = 0; i < MMCSD_PART_COUNT; i++)
+            {
+              priv->part[i].priv = priv;
+              if (priv->part[i].nblocks != 0)
+                {
+                  snprintf(devname, sizeof(devname), "/dev/mmcsd%d%s",
+                           priv->minor, g_partname[i]);
+                  register_blockdriver(devname, &g_bops, 0666,
+                                       &priv->part[i]);
+                }
+            }
         }
 
       /* Regardless of whether or not a card was successfully initialized,
@@ -4173,12 +4383,17 @@ static int mmcsd_probe(FAR struct mmcsd_state_s *priv)
 
 static int mmcsd_removed(FAR struct mmcsd_state_s *priv)
 {
-  char devname[16];
+  char devname[32];
+  int i;
 
   finfo("type: %d present: %d\n", priv->type, SDIO_PRESENT(priv->dev));
 
-  snprintf(devname, sizeof(devname), "/dev/mmcsd%d", priv->minor);
-  unregister_blockdriver(devname);
+  for (i = 0; i < MMCSD_PART_COUNT; i++)
+    {
+      snprintf(devname, sizeof(devname), "/dev/mmcsd%d%s",
+               priv->minor, g_partname[i]);
+      unregister_blockdriver(devname);
+    }
 
   /* Forget the card geometry, pretend the slot is empty (it might not
    * be), and that the card has never been initialized.
@@ -4197,7 +4412,11 @@ static int mmcsd_removed(FAR struct mmcsd_state_s *priv)
   priv->buswidth     = MMCSD_SCR_BUSWIDTH_1BIT;
   SDIO_WIDEBUS(priv->dev, false);
   priv->widebus      = false;
-  mmcsd_widebus(priv);
+
+  if (mmcsd_widebus(priv) != OK)
+    {
+      ferr("ERROR: Failed to set wide bus operation\n");
+    }
 
   /* Disable clocking to the card */
 
@@ -4412,7 +4631,7 @@ int mmcsd_slotinitialize(int minor, FAR struct sdio_dev_s 
*dev)
   snprintf(devname, sizeof(devname), "/dev/mmcsd%d", minor);
 
   finfo("MMC: %s %" PRIu64 "KB %s %s mode\n", devname,
-         ((uint64_t)priv->part.nblocks << priv->blockshift) >> 10,
+         ((uint64_t)priv->part[0].nblocks << priv->blockshift) >> 10,
          priv->widebus ? "4-bits" : "1-bit",
          mmc_get_mode_name(priv->mode));
 
diff --git a/drivers/mmcsd/mmcsd_sdio.h b/drivers/mmcsd/mmcsd_sdio.h
index 922b604d32..8185741984 100644
--- a/drivers/mmcsd/mmcsd_sdio.h
+++ b/drivers/mmcsd/mmcsd_sdio.h
@@ -58,6 +58,7 @@
 #define MMC_CMD6_MODE_CLEAR_BITS    (0x02)  /* Clear bits which are 1 in value 
*/
 #define MMC_CMD6_MODE_WRITE_BYTE    (0x03)  /* Set target to value */
 
+#define EXT_CSD_PART_CONF           179     /* R/W */
 #define EXT_CSD_BUS_WIDTH           183     /* WO */
 #define EXT_CSD_HS_TIMING           185     /* R/W */
 
@@ -82,6 +83,17 @@
                                      MMC_CMD6_INDEX(EXT_CSD_HS_TIMING) | \
                                      MMC_CMD6_MODE(MMC_CMD6_MODE_WRITE_BYTE))
 
+/* Partition type */
+
+#  define MMCSD_PART_UDATA            0
+#  define MMCSD_PART_BOOT0            1
+#  define MMCSD_PART_BOOT1            2
+#  define MMCSD_PART_RPMB             3
+#  define MMCSD_PART_GENP0            4
+#  define MMCSD_PART_GENP1            5
+#  define MMCSD_PART_GENP2            6
+#  define MMCSD_PART_GENP3            7
+
 /* CMD8 Argument:
  *    [31:12]: Reserved (shall be set to '0')
  *    [11:8]: Supply Voltage (VHS) 0x1 (Range: 2.7-3.6 V)


Reply via email to