@@ -101,6 +101,9 @@ struct tmio_mmc_host {
void (*clk_disable)(struct tmio_mmc_host *host);
int (*multi_io_quirk)(struct mmc_card *card,
unsigned int direction, int blk_size);
+
+ int (*start_signal_voltage_switch)(struct tmio_mmc_host *host,
+ unsigned char signal_voltage);
};
struct tmio_mmc_host *tmio_mmc_host_alloc(struct platform_device *pdev);
@@ -1008,12 +1008,43 @@ static int tmio_multi_io_quirk(struct mmc_card *card,
return blk_size;
}
+static int tmio_mmc_start_signal_voltage_switch(struct mmc_host *mmc,
+ struct mmc_ios *ios)
+{
+ struct tmio_mmc_host *host = mmc_priv(mmc);
+
+ if (!host->start_signal_voltage_switch)
+ return 0;
+
+ return host->start_signal_voltage_switch(host, ios->signal_voltage);
+}
+
+static int tmio_mmc_card_busy(struct mmc_host *mmc)
+{
+ struct tmio_mmc_host *host = mmc_priv(mmc);
+ u32 status;
+
+ pm_runtime_get_sync(mmc_dev(mmc));
+ status = sd_ctrl_read32(host, CTL_STATUS);
+ pm_runtime_mark_last_busy(mmc_dev(mmc));
+ pm_runtime_put_autosuspend(mmc_dev(mmc));
+
+ /*
+ * Card signals busy by pulling down all of DAT[3:0]. This status
+ * flag appears to reflect DAT3.
+ */
+ return !(status & TMIO_STAT_SIGSTATE_A);
+}
+
static const struct mmc_host_ops tmio_mmc_ops = {
.request = tmio_mmc_request,
.set_ios = tmio_mmc_set_ios,
.get_ro = tmio_mmc_get_ro,
.get_cd = mmc_gpio_get_cd,
.enable_sdio_irq = tmio_mmc_enable_sdio_irq,
+ .start_signal_voltage_switch
+ = tmio_mmc_start_signal_voltage_switch,
+ .card_busy = tmio_mmc_card_busy,
.multi_io_quirk = tmio_multi_io_quirk,
};
Based on work by Shinobu Uehara and Ben Dooks. This adds the voltage switch operation needed for all UHS-I modes, but not the tuning needed for SDR-104 which will come later. The card_busy implementation is a bit of a guess, but works for me on an R8A7790 chip. Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk> --- drivers/mmc/host/tmio_mmc.h | 3 +++ drivers/mmc/host/tmio_mmc_pio.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+)