diff options
author | Namjae Jeon <linkinjeon@gmail.com> | 2011-10-06 10:41:38 -0400 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2011-10-26 16:32:17 -0400 |
commit | e0c368d571d946ff40f068344b5c2df90c93dd2e (patch) | |
tree | 509fdad0059dac018128610723557b4ca12f29d2 /drivers/mmc | |
parent | 5238acbe36dd5100fb6b035a995ae5fc89dd0708 (diff) |
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: Namjae Jeon <linkinjeon@gmail.com>
Acked-by: Andrei Warkentin <awarkentin@vmware.com>
Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/card/block.c | 31 | ||||
-rw-r--r-- | drivers/mmc/core/mmc.c | 52 |
2 files changed, 65 insertions, 18 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index aa66d3f3abb1..2cf1ba6db910 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
@@ -1473,26 +1473,29 @@ static int mmc_blk_alloc_part(struct mmc_card *card, | |||
1473 | return 0; | 1473 | return 0; |
1474 | } | 1474 | } |
1475 | 1475 | ||
1476 | /* MMC Physical partitions consist of two boot partitions and | ||
1477 | * up to four general purpose partitions. | ||
1478 | * For each partition enabled in EXT_CSD a block device will be allocatedi | ||
1479 | * to provide access to the partition. | ||
1480 | */ | ||
1481 | |||
1476 | static int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md) | 1482 | static int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md) |
1477 | { | 1483 | { |
1478 | int ret = 0; | 1484 | int idx, ret = 0; |
1479 | 1485 | ||
1480 | if (!mmc_card_mmc(card)) | 1486 | if (!mmc_card_mmc(card)) |
1481 | return 0; | 1487 | return 0; |
1482 | 1488 | ||
1483 | if (card->ext_csd.boot_size && mmc_boot_partition_access(card->host)) { | 1489 | for (idx = 0; idx < card->nr_parts; idx++) { |
1484 | ret = mmc_blk_alloc_part(card, md, EXT_CSD_PART_CONFIG_ACC_BOOT0, | 1490 | if (card->part[idx].size) { |
1485 | card->ext_csd.boot_size >> 9, | 1491 | ret = mmc_blk_alloc_part(card, md, |
1486 | true, | 1492 | card->part[idx].part_cfg, |
1487 | "boot0"); | 1493 | card->part[idx].size >> 9, |
1488 | if (ret) | 1494 | card->part[idx].force_ro, |
1489 | return ret; | 1495 | card->part[idx].name); |
1490 | ret = mmc_blk_alloc_part(card, md, EXT_CSD_PART_CONFIG_ACC_BOOT1, | 1496 | if (ret) |
1491 | card->ext_csd.boot_size >> 9, | 1497 | return ret; |
1492 | true, | 1498 | } |
1493 | "boot1"); | ||
1494 | if (ret) | ||
1495 | return ret; | ||
1496 | } | 1499 | } |
1497 | 1500 | ||
1498 | return ret; | 1501 | return ret; |
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index c632b1faf70d..2a4c9a4d3c00 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
@@ -239,7 +239,9 @@ static int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd) | |||
239 | */ | 239 | */ |
240 | static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) | 240 | static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) |
241 | { | 241 | { |
242 | int err = 0; | 242 | int err = 0, idx; |
243 | unsigned int part_size; | ||
244 | u8 hc_erase_grp_sz = 0, hc_wp_grp_sz = 0; | ||
243 | 245 | ||
244 | BUG_ON(!card); | 246 | BUG_ON(!card); |
245 | 247 | ||
@@ -340,7 +342,14 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) | |||
340 | * There are two boot regions of equal size, defined in | 342 | * There are two boot regions of equal size, defined in |
341 | * multiples of 128K. | 343 | * multiples of 128K. |
342 | */ | 344 | */ |
343 | card->ext_csd.boot_size = ext_csd[EXT_CSD_BOOT_MULT] << 17; | 345 | if (ext_csd[EXT_CSD_BOOT_MULT] && mmc_boot_partition_access(card->host)) { |
346 | for (idx = 0; idx < MMC_NUM_BOOT_PARTITION; idx++) { | ||
347 | part_size = ext_csd[EXT_CSD_BOOT_MULT] << 17; | ||
348 | mmc_part_add(card, part_size, | ||
349 | EXT_CSD_PART_CONFIG_ACC_BOOT0 + idx, | ||
350 | "boot%d", idx, true); | ||
351 | } | ||
352 | } | ||
344 | } | 353 | } |
345 | 354 | ||
346 | card->ext_csd.raw_hc_erase_gap_size = | 355 | 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 | card->ext_csd.raw_partition_support = ext_csd[EXT_CSD_PARTITION_SUPPORT]; | 371 | card->ext_csd.raw_partition_support = ext_csd[EXT_CSD_PARTITION_SUPPORT]; |
363 | if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) && | 372 | if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) && |
364 | (ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) { | 373 | (ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) { |
365 | u8 hc_erase_grp_sz = | 374 | hc_erase_grp_sz = |
366 | ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]; | 375 | ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]; |
367 | u8 hc_wp_grp_sz = | 376 | hc_wp_grp_sz = |
368 | ext_csd[EXT_CSD_HC_WP_GRP_SIZE]; | 377 | ext_csd[EXT_CSD_HC_WP_GRP_SIZE]; |
369 | 378 | ||
370 | card->ext_csd.enhanced_area_en = 1; | 379 | 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 | card->ext_csd.enhanced_area_offset = -EINVAL; | 402 | card->ext_csd.enhanced_area_offset = -EINVAL; |
394 | card->ext_csd.enhanced_area_size = -EINVAL; | 403 | card->ext_csd.enhanced_area_size = -EINVAL; |
395 | } | 404 | } |
405 | |||
406 | /* | ||
407 | * General purpose partition feature support -- | ||
408 | * If ext_csd has the size of general purpose partitions, | ||
409 | * set size, part_cfg, partition name in mmc_part. | ||
410 | */ | ||
411 | if (ext_csd[EXT_CSD_PARTITION_SUPPORT] & | ||
412 | EXT_CSD_PART_SUPPORT_PART_EN) { | ||
413 | if (card->ext_csd.enhanced_area_en != 1) { | ||
414 | hc_erase_grp_sz = | ||
415 | ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]; | ||
416 | hc_wp_grp_sz = | ||
417 | ext_csd[EXT_CSD_HC_WP_GRP_SIZE]; | ||
418 | |||
419 | card->ext_csd.enhanced_area_en = 1; | ||
420 | } | ||
421 | |||
422 | for (idx = 0; idx < MMC_NUM_GP_PARTITION; idx++) { | ||
423 | if (!ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3] && | ||
424 | !ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 1] && | ||
425 | !ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 2]) | ||
426 | continue; | ||
427 | part_size = | ||
428 | (ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 2] | ||
429 | << 16) + | ||
430 | (ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 1] | ||
431 | << 8) + | ||
432 | ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3]; | ||
433 | part_size *= (size_t)(hc_erase_grp_sz * | ||
434 | hc_wp_grp_sz); | ||
435 | mmc_part_add(card, part_size << 19, | ||
436 | EXT_CSD_PART_CONFIG_ACC_GP0 + idx, | ||
437 | "gp%d", idx, false); | ||
438 | } | ||
439 | } | ||
396 | card->ext_csd.sec_trim_mult = | 440 | card->ext_csd.sec_trim_mult = |
397 | ext_csd[EXT_CSD_SEC_TRIM_MULT]; | 441 | ext_csd[EXT_CSD_SEC_TRIM_MULT]; |
398 | card->ext_csd.sec_erase_mult = | 442 | card->ext_csd.sec_erase_mult = |