diff --git a/drivers/mmcsd/mmcsd.h b/drivers/mmcsd/mmcsd.h index 1f374af86eb70..3c6f0fe694f04 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 */ @@ -70,11 +72,12 @@ struct mmcsd_part_s 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 0000000000000..60070e9fd3be4 --- /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 +#include + +/**************************************************************************** + * 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 ffd81b495bbc9..cf26b98cefdeb 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 * @@ -1466,9 +1484,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 +1503,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 +1633,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 +1654,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 +1808,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 +1829,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 +1992,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 +2016,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 +2116,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 +2369,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 +2379,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 +2450,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 +2460,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 @@ -2520,7 +2616,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 +2627,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 +2883,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 %" PRId32 "\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 +2963,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 +3104,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 +3239,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 +3516,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; @@ -3431,9 +3594,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; @@ -3447,7 +3611,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); @@ -4004,8 +4168,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); @@ -4100,7 +4265,7 @@ static int mmcsd_probe(FAR struct mmcsd_state_s *priv) /* Yes... */ finfo("Capacity: %" PRIu32 " Kbytes\n", - MMCSD_CAPACITY(priv->part.nblocks, + MMCSD_CAPACITY(priv->part[0].nblocks, priv->blockshift)); priv->mediachanged = true; } @@ -4108,15 +4273,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, @@ -4158,12 +4325,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. @@ -4397,7 +4569,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 922b604d32519..8b3451ab7df7a 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)