|
@@ -379,6 +379,63 @@ void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
|
|
|
}
|
|
|
EXPORT_SYMBOL(mmc_wait_for_req);
|
|
|
|
|
|
+/**
|
|
|
+ * mmc_interrupt_hpi - Issue for High priority Interrupt
|
|
|
+ * @card: the MMC card associated with the HPI transfer
|
|
|
+ *
|
|
|
+ * Issued High Priority Interrupt, and check for card status
|
|
|
+ * util out-of prg-state.
|
|
|
+ */
|
|
|
+int mmc_interrupt_hpi(struct mmc_card *card)
|
|
|
+{
|
|
|
+ int err;
|
|
|
+ u32 status;
|
|
|
+
|
|
|
+ BUG_ON(!card);
|
|
|
+
|
|
|
+ if (!card->ext_csd.hpi_en) {
|
|
|
+ pr_info("%s: HPI enable bit unset\n", mmc_hostname(card->host));
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ mmc_claim_host(card->host);
|
|
|
+ err = mmc_send_status(card, &status);
|
|
|
+ if (err) {
|
|
|
+ pr_err("%s: Get card status fail\n", mmc_hostname(card->host));
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * If the card status is in PRG-state, we can send the HPI command.
|
|
|
+ */
|
|
|
+ if (R1_CURRENT_STATE(status) == R1_STATE_PRG) {
|
|
|
+ do {
|
|
|
+ /*
|
|
|
+ * We don't know when the HPI command will finish
|
|
|
+ * processing, so we need to resend HPI until out
|
|
|
+ * of prg-state, and keep checking the card status
|
|
|
+ * with SEND_STATUS. If a timeout error occurs when
|
|
|
+ * sending the HPI command, we are already out of
|
|
|
+ * prg-state.
|
|
|
+ */
|
|
|
+ err = mmc_send_hpi_cmd(card, &status);
|
|
|
+ if (err)
|
|
|
+ pr_debug("%s: abort HPI (%d error)\n",
|
|
|
+ mmc_hostname(card->host), err);
|
|
|
+
|
|
|
+ err = mmc_send_status(card, &status);
|
|
|
+ if (err)
|
|
|
+ break;
|
|
|
+ } while (R1_CURRENT_STATE(status) == R1_STATE_PRG);
|
|
|
+ } else
|
|
|
+ pr_debug("%s: Left prg-state\n", mmc_hostname(card->host));
|
|
|
+
|
|
|
+out:
|
|
|
+ mmc_release_host(card->host);
|
|
|
+ return err;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(mmc_interrupt_hpi);
|
|
|
+
|
|
|
/**
|
|
|
* mmc_wait_for_cmd - start a command and wait for completion
|
|
|
* @host: MMC host to start command
|