module_param(perdev_minors, int, 0444);
 MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device");
 
+static inline int mmc_blk_part_switch(struct mmc_card *card,
+                                     struct mmc_blk_data *md);
+static int get_card_status(struct mmc_card *card, u32 *status, int retries);
+
 static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)
 {
        struct mmc_blk_data *md;
        return ERR_PTR(err);
 }
 
+static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status,
+                                      u32 retries_max)
+{
+       int err;
+       u32 retry_count = 0;
+
+       if (!status || !retries_max)
+               return -EINVAL;
+
+       do {
+               err = get_card_status(card, status, 5);
+               if (err)
+                       break;
+
+               if (!R1_STATUS(*status) &&
+                               (R1_CURRENT_STATE(*status) != R1_STATE_PRG))
+                       break; /* RPMB programming operation complete */
+
+               /*
+                * Rechedule to give the MMC device a chance to continue
+                * processing the previous command without being polled too
+                * frequently.
+                */
+               usleep_range(1000, 5000);
+       } while (++retry_count < retries_max);
+
+       if (retry_count == retries_max)
+               err = -EPERM;
+
+       return err;
+}
+
 static int mmc_blk_ioctl_cmd(struct block_device *bdev,
        struct mmc_ioc_cmd __user *ic_ptr)
 {
        struct mmc_request mrq = {NULL};
        struct scatterlist sg;
        int err;
+       int is_rpmb = false;
+       u32 status = 0;
 
        /*
         * The caller must have CAP_SYS_RAWIO, and must be calling this on the
                goto cmd_err;
        }
 
+       if (md->area_type & MMC_BLK_DATA_AREA_RPMB)
+               is_rpmb = true;
+
        card = md->queue.card;
        if (IS_ERR(card)) {
                err = PTR_ERR(card);
 
        mmc_claim_host(card->host);
 
+       err = mmc_blk_part_switch(card, md);
+       if (err)
+               goto cmd_rel_host;
+
        if (idata->ic.is_acmd) {
                err = mmc_app_cmd(card->host, card);
                if (err)
                        goto cmd_rel_host;
        }
 
+       if (is_rpmb) {
+               err = mmc_set_blockcount(card, data.blocks,
+                       idata->ic.write_flag & (1 << 31));
+               if (err)
+                       goto cmd_rel_host;
+       }
+
        mmc_wait_for_req(card->host, &mrq);
 
        if (cmd.error) {
                }
        }
 
+       if (is_rpmb) {
+               /*
+                * Ensure RPMB command has completed by polling CMD13
+                * "Send Status".
+                */
+               err = ioctl_rpmb_card_status_poll(card, &status, 5);
+               if (err)
+                       dev_err(mmc_dev(card->host),
+                                       "%s: Card Status=0x%08X, error %d\n",
+                                       __func__, status, err);
+       }
+
 cmd_rel_host:
        mmc_release_host(card->host);