|
@@ -570,6 +570,37 @@ done:
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
+static void dw_mci_ctrl_rd_thld(struct dw_mci *host, struct mmc_data *data)
|
|
|
+{
|
|
|
+ unsigned int blksz = data->blksz;
|
|
|
+ u32 blksz_depth, fifo_depth;
|
|
|
+ u16 thld_size;
|
|
|
+
|
|
|
+ WARN_ON(!(data->flags & MMC_DATA_READ));
|
|
|
+
|
|
|
+ if (host->timing != MMC_TIMING_MMC_HS200 &&
|
|
|
+ host->timing != MMC_TIMING_UHS_SDR104)
|
|
|
+ goto disable;
|
|
|
+
|
|
|
+ blksz_depth = blksz / (1 << host->data_shift);
|
|
|
+ fifo_depth = host->fifo_depth;
|
|
|
+
|
|
|
+ if (blksz_depth > fifo_depth)
|
|
|
+ goto disable;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * If (blksz_depth) >= (fifo_depth >> 1), should be 'thld_size <= blksz'
|
|
|
+ * If (blksz_depth) < (fifo_depth >> 1), should be thld_size = blksz
|
|
|
+ * Currently just choose blksz.
|
|
|
+ */
|
|
|
+ thld_size = blksz;
|
|
|
+ mci_writel(host, CDTHRCTL, SDMMC_SET_RD_THLD(thld_size, 1));
|
|
|
+ return;
|
|
|
+
|
|
|
+disable:
|
|
|
+ mci_writel(host, CDTHRCTL, SDMMC_SET_RD_THLD(0, 0));
|
|
|
+}
|
|
|
+
|
|
|
static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
|
|
|
{
|
|
|
int sg_len;
|
|
@@ -627,10 +658,12 @@ static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data)
|
|
|
host->sg = NULL;
|
|
|
host->data = data;
|
|
|
|
|
|
- if (data->flags & MMC_DATA_READ)
|
|
|
+ if (data->flags & MMC_DATA_READ) {
|
|
|
host->dir_status = DW_MCI_RECV_STATUS;
|
|
|
- else
|
|
|
+ dw_mci_ctrl_rd_thld(host, data);
|
|
|
+ } else {
|
|
|
host->dir_status = DW_MCI_SEND_STATUS;
|
|
|
+ }
|
|
|
|
|
|
if (dw_mci_submit_data_dma(host, data)) {
|
|
|
int flags = SG_MITER_ATOMIC;
|
|
@@ -877,6 +910,7 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
|
|
regs &= ~((0x1 << slot->id) << 16);
|
|
|
|
|
|
mci_writel(slot->host, UHS_REG, regs);
|
|
|
+ slot->host->timing = ios->timing;
|
|
|
|
|
|
/*
|
|
|
* Use mirror of ios->clock to prevent race with mmc
|