Commit e0c368d5 authored by Namjae Jeon's avatar Namjae Jeon Committed by Chris Ball

mmc: core: general purpose MMC partition support.

It allows gerneral purpose partitions in MMC Device.  And I try to simply
make mmc_blk_alloc_parts using mmc_part structure suggested by Andrei
Warkentin.  After patching, we see general purpose partitions like this:
> cat /proc/partitions
          179 0 847872 mmcblk0
          179 192 4096 mmcblk0gp3
          179 160 4096 mmcblk0gp2
          179 128 4096 mmcblk0gp1
          179 96  1052672 mmcblk0gp0
          179 64  1024 mmcblk0boot1
          179 32  1024 mmcblk0boot0
Signed-off-by: default avatarNamjae Jeon <linkinjeon@gmail.com>
Acked-by: default avatarAndrei Warkentin <awarkentin@vmware.com>
Signed-off-by: default avatarChris Ball <cjb@laptop.org>
parent 5238acbe
...@@ -1473,26 +1473,29 @@ static int mmc_blk_alloc_part(struct mmc_card *card, ...@@ -1473,26 +1473,29 @@ static int mmc_blk_alloc_part(struct mmc_card *card,
return 0; return 0;
} }
/* MMC Physical partitions consist of two boot partitions and
* up to four general purpose partitions.
* For each partition enabled in EXT_CSD a block device will be allocatedi
* to provide access to the partition.
*/
static int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md) static int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md)
{ {
int ret = 0; int idx, ret = 0;
if (!mmc_card_mmc(card)) if (!mmc_card_mmc(card))
return 0; return 0;
if (card->ext_csd.boot_size && mmc_boot_partition_access(card->host)) { for (idx = 0; idx < card->nr_parts; idx++) {
ret = mmc_blk_alloc_part(card, md, EXT_CSD_PART_CONFIG_ACC_BOOT0, if (card->part[idx].size) {
card->ext_csd.boot_size >> 9, ret = mmc_blk_alloc_part(card, md,
true, card->part[idx].part_cfg,
"boot0"); card->part[idx].size >> 9,
if (ret) card->part[idx].force_ro,
return ret; card->part[idx].name);
ret = mmc_blk_alloc_part(card, md, EXT_CSD_PART_CONFIG_ACC_BOOT1, if (ret)
card->ext_csd.boot_size >> 9, return ret;
true, }
"boot1");
if (ret)
return ret;
} }
return ret; return ret;
......
...@@ -239,7 +239,9 @@ static int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd) ...@@ -239,7 +239,9 @@ static int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd)
*/ */
static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
{ {
int err = 0; int err = 0, idx;
unsigned int part_size;
u8 hc_erase_grp_sz = 0, hc_wp_grp_sz = 0;
BUG_ON(!card); BUG_ON(!card);
...@@ -340,7 +342,14 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) ...@@ -340,7 +342,14 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
* There are two boot regions of equal size, defined in * There are two boot regions of equal size, defined in
* multiples of 128K. * multiples of 128K.
*/ */
card->ext_csd.boot_size = ext_csd[EXT_CSD_BOOT_MULT] << 17; if (ext_csd[EXT_CSD_BOOT_MULT] && mmc_boot_partition_access(card->host)) {
for (idx = 0; idx < MMC_NUM_BOOT_PARTITION; idx++) {
part_size = ext_csd[EXT_CSD_BOOT_MULT] << 17;
mmc_part_add(card, part_size,
EXT_CSD_PART_CONFIG_ACC_BOOT0 + idx,
"boot%d", idx, true);
}
}
} }
card->ext_csd.raw_hc_erase_gap_size = card->ext_csd.raw_hc_erase_gap_size =
...@@ -362,9 +371,9 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) ...@@ -362,9 +371,9 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
card->ext_csd.raw_partition_support = ext_csd[EXT_CSD_PARTITION_SUPPORT]; card->ext_csd.raw_partition_support = ext_csd[EXT_CSD_PARTITION_SUPPORT];
if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) && if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) &&
(ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) { (ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) {
u8 hc_erase_grp_sz = hc_erase_grp_sz =
ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]; ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
u8 hc_wp_grp_sz = hc_wp_grp_sz =
ext_csd[EXT_CSD_HC_WP_GRP_SIZE]; ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
card->ext_csd.enhanced_area_en = 1; card->ext_csd.enhanced_area_en = 1;
...@@ -393,6 +402,41 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) ...@@ -393,6 +402,41 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
card->ext_csd.enhanced_area_offset = -EINVAL; card->ext_csd.enhanced_area_offset = -EINVAL;
card->ext_csd.enhanced_area_size = -EINVAL; card->ext_csd.enhanced_area_size = -EINVAL;
} }
/*
* General purpose partition feature support --
* If ext_csd has the size of general purpose partitions,
* set size, part_cfg, partition name in mmc_part.
*/
if (ext_csd[EXT_CSD_PARTITION_SUPPORT] &
EXT_CSD_PART_SUPPORT_PART_EN) {
if (card->ext_csd.enhanced_area_en != 1) {
hc_erase_grp_sz =
ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
hc_wp_grp_sz =
ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
card->ext_csd.enhanced_area_en = 1;
}
for (idx = 0; idx < MMC_NUM_GP_PARTITION; idx++) {
if (!ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3] &&
!ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 1] &&
!ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 2])
continue;
part_size =
(ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 2]
<< 16) +
(ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 1]
<< 8) +
ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3];
part_size *= (size_t)(hc_erase_grp_sz *
hc_wp_grp_sz);
mmc_part_add(card, part_size << 19,
EXT_CSD_PART_CONFIG_ACC_GP0 + idx,
"gp%d", idx, false);
}
}
card->ext_csd.sec_trim_mult = card->ext_csd.sec_trim_mult =
ext_csd[EXT_CSD_SEC_TRIM_MULT]; ext_csd[EXT_CSD_SEC_TRIM_MULT];
card->ext_csd.sec_erase_mult = card->ext_csd.sec_erase_mult =
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/mmc/core.h> #include <linux/mmc/core.h>
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
#include <linux/genhd.h>
struct mmc_cid { struct mmc_cid {
unsigned int manfid; unsigned int manfid;
...@@ -64,7 +65,6 @@ struct mmc_ext_csd { ...@@ -64,7 +65,6 @@ struct mmc_ext_csd {
bool enhanced_area_en; /* enable bit */ bool enhanced_area_en; /* enable bit */
unsigned long long enhanced_area_offset; /* Units: Byte */ unsigned long long enhanced_area_offset; /* Units: Byte */
unsigned int enhanced_area_size; /* Units: KB */ unsigned int enhanced_area_size; /* Units: KB */
unsigned int boot_size; /* in bytes */
u8 raw_partition_support; /* 160 */ u8 raw_partition_support; /* 160 */
u8 raw_erased_mem_count; /* 181 */ u8 raw_erased_mem_count; /* 181 */
u8 raw_ext_csd_structure; /* 194 */ u8 raw_ext_csd_structure; /* 194 */
...@@ -158,6 +158,23 @@ struct sdio_func_tuple; ...@@ -158,6 +158,23 @@ struct sdio_func_tuple;
#define SDIO_MAX_FUNCS 7 #define SDIO_MAX_FUNCS 7
/* The number of MMC physical partitions. These consist of:
* boot partitions (2), general purpose partitions (4) in MMC v4.4.
*/
#define MMC_NUM_BOOT_PARTITION 2
#define MMC_NUM_GP_PARTITION 4
#define MMC_NUM_PHY_PARTITION 6
/*
* MMC Physical partitions
*/
struct mmc_part {
unsigned int size; /* partition size (in bytes) */
unsigned int part_cfg; /* partition type */
char name[DISK_NAME_LEN];
bool force_ro; /* to make boot parts RO by default */
};
/* /*
* MMC device * MMC device
*/ */
...@@ -219,8 +236,23 @@ struct mmc_card { ...@@ -219,8 +236,23 @@ struct mmc_card {
unsigned int sd_bus_speed; /* Bus Speed Mode set for the card */ unsigned int sd_bus_speed; /* Bus Speed Mode set for the card */
struct dentry *debugfs_root; struct dentry *debugfs_root;
struct mmc_part part[MMC_NUM_PHY_PARTITION]; /* physical partitions */
unsigned int nr_parts;
}; };
/*
* This function fill contents in mmc_part.
*/
static inline void mmc_part_add(struct mmc_card *card, unsigned int size,
unsigned int part_cfg, char *name, int idx, bool ro)
{
card->part[card->nr_parts].size = size;
card->part[card->nr_parts].part_cfg = part_cfg;
sprintf(card->part[card->nr_parts].name, name, idx);
card->part[card->nr_parts].force_ro = ro;
card->nr_parts++;
}
/* /*
* The world is not perfect and supplies us with broken mmc/sdio devices. * The world is not perfect and supplies us with broken mmc/sdio devices.
* For at least some of these bugs we need a work-around. * For at least some of these bugs we need a work-around.
......
...@@ -270,6 +270,7 @@ struct _mmc_csd { ...@@ -270,6 +270,7 @@ struct _mmc_csd {
* EXT_CSD fields * EXT_CSD fields
*/ */
#define EXT_CSD_GP_SIZE_MULT 143 /* R/W */
#define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */ #define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */
#define EXT_CSD_PARTITION_SUPPORT 160 /* RO */ #define EXT_CSD_PARTITION_SUPPORT 160 /* RO */
#define EXT_CSD_RST_N_FUNCTION 162 /* R/W */ #define EXT_CSD_RST_N_FUNCTION 162 /* R/W */
...@@ -313,7 +314,9 @@ struct _mmc_csd { ...@@ -313,7 +314,9 @@ struct _mmc_csd {
#define EXT_CSD_PART_CONFIG_ACC_MASK (0x7) #define EXT_CSD_PART_CONFIG_ACC_MASK (0x7)
#define EXT_CSD_PART_CONFIG_ACC_BOOT0 (0x1) #define EXT_CSD_PART_CONFIG_ACC_BOOT0 (0x1)
#define EXT_CSD_PART_CONFIG_ACC_BOOT1 (0x2) #define EXT_CSD_PART_CONFIG_ACC_GP0 (0x4)
#define EXT_CSD_PART_SUPPORT_PART_EN (0x1)
#define EXT_CSD_CMD_SET_NORMAL (1<<0) #define EXT_CSD_CMD_SET_NORMAL (1<<0)
#define EXT_CSD_CMD_SET_SECURE (1<<1) #define EXT_CSD_CMD_SET_SECURE (1<<1)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment