diff options
author | Ulf Hansson <ulf.hansson@linaro.org> | 2017-06-08 15:27:39 +0200 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@linaro.org> | 2017-06-20 10:30:43 +0200 |
commit | 0f2c05125ef98f062c256c6d150ff372125bf523 (patch) | |
tree | 58063bcba8f7a3d26a4f3081bb1c66256b5e3dc2 /drivers/mmc/core/mmc_ops.c | |
parent | mmc: core: Move mmc bkops functions from core.c to mmc_ops.c (diff) | |
download | linux-dev-0f2c05125ef98f062c256c6d150ff372125bf523.tar.xz linux-dev-0f2c05125ef98f062c256c6d150ff372125bf523.zip |
mmc: core: Move mmc_interrupt_hpi() from core.c to mmc_ops.c
The mmc_interrupt_hpi() is a eMMC specific function, let's move it to
mmc_ops.c to make that clear. The move also enables us to make
mmc_send_hpi_cmd() static, so let's do that change as well.
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Reviewed-by: Shawn Lin <shawn.lin@rock-chips.com>
Diffstat (limited to 'drivers/mmc/core/mmc_ops.c')
-rw-r--r-- | drivers/mmc/core/mmc_ops.c | 66 |
1 files changed, 65 insertions, 1 deletions
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index a631f74efca9..26760e76e924 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -807,7 +807,7 @@ int mmc_bus_test(struct mmc_card *card, u8 bus_width) return mmc_send_bus_test(card, card->host, MMC_BUS_TEST_R, width); } -int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status) +static int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status) { struct mmc_command cmd = {}; unsigned int opcode; @@ -841,6 +841,70 @@ int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status) return 0; } +/** + * 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 + * until out-of prg-state. + */ +int mmc_interrupt_hpi(struct mmc_card *card) +{ + int err; + u32 status; + unsigned long prg_wait; + + 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; + } + + switch (R1_CURRENT_STATE(status)) { + case R1_STATE_IDLE: + case R1_STATE_READY: + case R1_STATE_STBY: + case R1_STATE_TRAN: + /* + * In idle and transfer states, HPI is not needed and the caller + * can issue the next intended command immediately + */ + goto out; + case R1_STATE_PRG: + break; + default: + /* In all other states, it's illegal to issue HPI */ + pr_debug("%s: HPI cannot be sent. Card state=%d\n", + mmc_hostname(card->host), R1_CURRENT_STATE(status)); + err = -EINVAL; + goto out; + } + + err = mmc_send_hpi_cmd(card, &status); + if (err) + goto out; + + prg_wait = jiffies + msecs_to_jiffies(card->ext_csd.out_of_int_time); + do { + err = mmc_send_status(card, &status); + + if (!err && R1_CURRENT_STATE(status) == R1_STATE_TRAN) + break; + if (time_after(jiffies, prg_wait)) + err = -ETIMEDOUT; + } while (!err); + +out: + mmc_release_host(card->host); + return err; +} + int mmc_can_ext_csd(struct mmc_card *card) { return (card && card->csd.mmca_vsn > CSD_SPEC_VER_3); |