diff options
-rw-r--r-- | drivers/mmc/card/block.c | 31 | ||||
-rw-r--r-- | drivers/mmc/core/mmc.c | 52 | ||||
-rw-r--r-- | include/linux/mmc/card.h | 34 | ||||
-rw-r--r-- | include/linux/mmc/mmc.h | 5 |
4 files changed, 102 insertions, 20 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 = |
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 5294ddf382ae..92762865f7e0 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h | |||
@@ -12,6 +12,7 @@ | |||
12 | 12 | ||
13 | #include <linux/mmc/core.h> | 13 | #include <linux/mmc/core.h> |
14 | #include <linux/mod_devicetable.h> | 14 | #include <linux/mod_devicetable.h> |
15 | #include <linux/genhd.h> | ||
15 | 16 | ||
16 | struct mmc_cid { | 17 | struct mmc_cid { |
17 | unsigned int manfid; | 18 | unsigned int manfid; |
@@ -64,7 +65,6 @@ struct mmc_ext_csd { | |||
64 | bool enhanced_area_en; /* enable bit */ | 65 | bool enhanced_area_en; /* enable bit */ |
65 | unsigned long long enhanced_area_offset; /* Units: Byte */ | 66 | unsigned long long enhanced_area_offset; /* Units: Byte */ |
66 | unsigned int enhanced_area_size; /* Units: KB */ | 67 | unsigned int enhanced_area_size; /* Units: KB */ |
67 | unsigned int boot_size; /* in bytes */ | ||
68 | u8 raw_partition_support; /* 160 */ | 68 | u8 raw_partition_support; /* 160 */ |
69 | u8 raw_erased_mem_count; /* 181 */ | 69 | u8 raw_erased_mem_count; /* 181 */ |
70 | u8 raw_ext_csd_structure; /* 194 */ | 70 | u8 raw_ext_csd_structure; /* 194 */ |
@@ -158,6 +158,23 @@ struct sdio_func_tuple; | |||
158 | 158 | ||
159 | #define SDIO_MAX_FUNCS 7 | 159 | #define SDIO_MAX_FUNCS 7 |
160 | 160 | ||
161 | /* The number of MMC physical partitions. These consist of: | ||
162 | * boot partitions (2), general purpose partitions (4) in MMC v4.4. | ||
163 | */ | ||
164 | #define MMC_NUM_BOOT_PARTITION 2 | ||
165 | #define MMC_NUM_GP_PARTITION 4 | ||
166 | #define MMC_NUM_PHY_PARTITION 6 | ||
167 | |||
168 | /* | ||
169 | * MMC Physical partitions | ||
170 | */ | ||
171 | struct mmc_part { | ||
172 | unsigned int size; /* partition size (in bytes) */ | ||
173 | unsigned int part_cfg; /* partition type */ | ||
174 | char name[DISK_NAME_LEN]; | ||
175 | bool force_ro; /* to make boot parts RO by default */ | ||
176 | }; | ||
177 | |||
161 | /* | 178 | /* |
162 | * MMC device | 179 | * MMC device |
163 | */ | 180 | */ |
@@ -219,9 +236,24 @@ struct mmc_card { | |||
219 | unsigned int sd_bus_speed; /* Bus Speed Mode set for the card */ | 236 | unsigned int sd_bus_speed; /* Bus Speed Mode set for the card */ |
220 | 237 | ||
221 | struct dentry *debugfs_root; | 238 | struct dentry *debugfs_root; |
239 | struct mmc_part part[MMC_NUM_PHY_PARTITION]; /* physical partitions */ | ||
240 | unsigned int nr_parts; | ||
222 | }; | 241 | }; |
223 | 242 | ||
224 | /* | 243 | /* |
244 | * This function fill contents in mmc_part. | ||
245 | */ | ||
246 | static inline void mmc_part_add(struct mmc_card *card, unsigned int size, | ||
247 | unsigned int part_cfg, char *name, int idx, bool ro) | ||
248 | { | ||
249 | card->part[card->nr_parts].size = size; | ||
250 | card->part[card->nr_parts].part_cfg = part_cfg; | ||
251 | sprintf(card->part[card->nr_parts].name, name, idx); | ||
252 | card->part[card->nr_parts].force_ro = ro; | ||
253 | card->nr_parts++; | ||
254 | } | ||
255 | |||
256 | /* | ||
225 | * The world is not perfect and supplies us with broken mmc/sdio devices. | 257 | * The world is not perfect and supplies us with broken mmc/sdio devices. |
226 | * For at least some of these bugs we need a work-around. | 258 | * For at least some of these bugs we need a work-around. |
227 | */ | 259 | */ |
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index 50af22730c74..ea558eb44c79 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h | |||
@@ -270,6 +270,7 @@ struct _mmc_csd { | |||
270 | * EXT_CSD fields | 270 | * EXT_CSD fields |
271 | */ | 271 | */ |
272 | 272 | ||
273 | #define EXT_CSD_GP_SIZE_MULT 143 /* R/W */ | ||
273 | #define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */ | 274 | #define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */ |
274 | #define EXT_CSD_PARTITION_SUPPORT 160 /* RO */ | 275 | #define EXT_CSD_PARTITION_SUPPORT 160 /* RO */ |
275 | #define EXT_CSD_RST_N_FUNCTION 162 /* R/W */ | 276 | #define EXT_CSD_RST_N_FUNCTION 162 /* R/W */ |
@@ -313,7 +314,9 @@ struct _mmc_csd { | |||
313 | 314 | ||
314 | #define EXT_CSD_PART_CONFIG_ACC_MASK (0x7) | 315 | #define EXT_CSD_PART_CONFIG_ACC_MASK (0x7) |
315 | #define EXT_CSD_PART_CONFIG_ACC_BOOT0 (0x1) | 316 | #define EXT_CSD_PART_CONFIG_ACC_BOOT0 (0x1) |
316 | #define EXT_CSD_PART_CONFIG_ACC_BOOT1 (0x2) | 317 | #define EXT_CSD_PART_CONFIG_ACC_GP0 (0x4) |
318 | |||
319 | #define EXT_CSD_PART_SUPPORT_PART_EN (0x1) | ||
317 | 320 | ||
318 | #define EXT_CSD_CMD_SET_NORMAL (1<<0) | 321 | #define EXT_CSD_CMD_SET_NORMAL (1<<0) |
319 | #define EXT_CSD_CMD_SET_SECURE (1<<1) | 322 | #define EXT_CSD_CMD_SET_SECURE (1<<1) |