aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/card
diff options
context:
space:
mode:
authorLoic Pallardy <loic.pallardy-ext@stericsson.com>2012-08-06 11:12:31 -0400
committerChris Ball <cjb@laptop.org>2012-12-06 13:54:49 -0500
commit8d1e977da82ebd1defd44d085edc2c0140aecc2a (patch)
treef355ee13e20aab5ebcd123d68824ff24d4597ac2 /drivers/mmc/card
parent67c79db8d9c0e5d2e2075c9108f42566ce0f8a6f (diff)
mmc: card: Add RPMB support in IOCTL interface
RPMB partition is accessing though /dev/block/mmcXrpmb device User callers can read and write entire data frame(s) as defined by JEDEC Standard JESD84-A441, using standard IOCTL interface. Signed-off-by: Alex Macro <alex.macro@stericsson.com> Signed-off-by: Loic Pallardy <loic.pallardy@stericsson.com> Reviewed-by: Namjae Jeon <linkinjeon@gmail.com> Acked-by: Linus Walleij <linus.walleij@linaro.org> Acked-by: Krishna Konda <kkonda@codeaurora.org> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/card')
-rw-r--r--drivers/mmc/card/block.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 1d341f3878ec..21056b9ef0a0 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -127,6 +127,10 @@ enum mmc_blk_status {
127module_param(perdev_minors, int, 0444); 127module_param(perdev_minors, int, 0444);
128MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device"); 128MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device");
129 129
130static inline int mmc_blk_part_switch(struct mmc_card *card,
131 struct mmc_blk_data *md);
132static int get_card_status(struct mmc_card *card, u32 *status, int retries);
133
130static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk) 134static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)
131{ 135{
132 struct mmc_blk_data *md; 136 struct mmc_blk_data *md;
@@ -358,6 +362,38 @@ out:
358 return ERR_PTR(err); 362 return ERR_PTR(err);
359} 363}
360 364
365static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status,
366 u32 retries_max)
367{
368 int err;
369 u32 retry_count = 0;
370
371 if (!status || !retries_max)
372 return -EINVAL;
373
374 do {
375 err = get_card_status(card, status, 5);
376 if (err)
377 break;
378
379 if (!R1_STATUS(*status) &&
380 (R1_CURRENT_STATE(*status) != R1_STATE_PRG))
381 break; /* RPMB programming operation complete */
382
383 /*
384 * Rechedule to give the MMC device a chance to continue
385 * processing the previous command without being polled too
386 * frequently.
387 */
388 usleep_range(1000, 5000);
389 } while (++retry_count < retries_max);
390
391 if (retry_count == retries_max)
392 err = -EPERM;
393
394 return err;
395}
396
361static int mmc_blk_ioctl_cmd(struct block_device *bdev, 397static int mmc_blk_ioctl_cmd(struct block_device *bdev,
362 struct mmc_ioc_cmd __user *ic_ptr) 398 struct mmc_ioc_cmd __user *ic_ptr)
363{ 399{
@@ -369,6 +405,8 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
369 struct mmc_request mrq = {NULL}; 405 struct mmc_request mrq = {NULL};
370 struct scatterlist sg; 406 struct scatterlist sg;
371 int err; 407 int err;
408 int is_rpmb = false;
409 u32 status = 0;
372 410
373 /* 411 /*
374 * The caller must have CAP_SYS_RAWIO, and must be calling this on the 412 * The caller must have CAP_SYS_RAWIO, and must be calling this on the
@@ -388,6 +426,9 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
388 goto cmd_err; 426 goto cmd_err;
389 } 427 }
390 428
429 if (md->area_type & MMC_BLK_DATA_AREA_RPMB)
430 is_rpmb = true;
431
391 card = md->queue.card; 432 card = md->queue.card;
392 if (IS_ERR(card)) { 433 if (IS_ERR(card)) {
393 err = PTR_ERR(card); 434 err = PTR_ERR(card);
@@ -438,12 +479,23 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
438 479
439 mmc_claim_host(card->host); 480 mmc_claim_host(card->host);
440 481
482 err = mmc_blk_part_switch(card, md);
483 if (err)
484 goto cmd_rel_host;
485
441 if (idata->ic.is_acmd) { 486 if (idata->ic.is_acmd) {
442 err = mmc_app_cmd(card->host, card); 487 err = mmc_app_cmd(card->host, card);
443 if (err) 488 if (err)
444 goto cmd_rel_host; 489 goto cmd_rel_host;
445 } 490 }
446 491
492 if (is_rpmb) {
493 err = mmc_set_blockcount(card, data.blocks,
494 idata->ic.write_flag & (1 << 31));
495 if (err)
496 goto cmd_rel_host;
497 }
498
447 mmc_wait_for_req(card->host, &mrq); 499 mmc_wait_for_req(card->host, &mrq);
448 500
449 if (cmd.error) { 501 if (cmd.error) {
@@ -479,6 +531,18 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
479 } 531 }
480 } 532 }
481 533
534 if (is_rpmb) {
535 /*
536 * Ensure RPMB command has completed by polling CMD13
537 * "Send Status".
538 */
539 err = ioctl_rpmb_card_status_poll(card, &status, 5);
540 if (err)
541 dev_err(mmc_dev(card->host),
542 "%s: Card Status=0x%08X, error %d\n",
543 __func__, status, err);
544 }
545
482cmd_rel_host: 546cmd_rel_host:
483 mmc_release_host(card->host); 547 mmc_release_host(card->host);
484 548