@@ -20,6 +20,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
+#include <linux/iommu.h>
#include <linux/kernel.h>
#include <linux/mfd/tmio.h>
#include <linux/mmc/host.h>
@@ -46,6 +47,8 @@
#define SDHI_VER_GEN3_SD 0xcc10
#define SDHI_VER_GEN3_SDMMC 0xcd10
+#define SDHI_MAX_SEGS_IN_IOMMU 512
+
struct renesas_sdhi_quirks {
bool hs400_disabled;
bool hs400_4taps;
@@ -203,6 +206,28 @@ static void renesas_sdhi_clk_disable(struct tmio_mmc_host *host)
clk_disable_unprepare(priv->clk_cd);
}
+static void renesas_sdhi_init_card(struct mmc_host *mmc, struct mmc_card *card)
+{
+ struct tmio_mmc_host *host = mmc_priv(mmc);
+
+ /*
+ * If the IOMMU driver has a capable for merging segments to
+ * a segment strictly, this can expose the host->mmc->max_segs with
+ * multiple segments to a block layer by using blk_queue_max_segments()
+ * that mmc_setup_queue() calls. Notes that an sdio card may be
+ * possible to use multiple segments with non page aligned size, so
+ * that this will not expose multiple segments to avoid failing
+ * dma_map_sg() every time.
+ */
+ if (host->pdata->max_segs < SDHI_MAX_SEGS_IN_IOMMU &&
+ iommu_capable(host->pdev->dev.bus, IOMMU_CAP_MERGING) &&
+ (mmc_card_mmc(card) || mmc_card_sd(card)))
+ host->mmc->max_segs = SDHI_MAX_SEGS_IN_IOMMU;
+ else
+ host->mmc->max_segs = host->pdata->max_segs ? :
+ TMIO_DEFAULT_MAX_SEGS;
+}
+
static int renesas_sdhi_card_busy(struct mmc_host *mmc)
{
struct tmio_mmc_host *host = mmc_priv(mmc);
@@ -726,6 +751,8 @@ int renesas_sdhi_probe(struct platform_device *pdev,
/* SDR speeds are only available on Gen2+ */
if (mmc_data->flags & TMIO_MMC_MIN_RCAR2) {
+ host->ops.init_card = renesas_sdhi_init_card;
+
/* card_busy caused issues on r8a73a4 (pre-Gen2) CD-less SDHI */
host->ops.card_busy = renesas_sdhi_card_busy;
host->ops.start_signal_voltage_switch =
@@ -11,6 +11,7 @@
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/io-64-nonatomic-hi-lo.h>
+#include <linux/iommu.h>
#include <linux/mfd/tmio.h>
#include <linux/mmc/host.h>
#include <linux/mod_devicetable.h>
@@ -337,6 +338,9 @@ static int renesas_sdhi_internal_dmac_probe(struct platform_device *pdev)
/* value is max of SD_SECCNT. Confirmed by HW engineers */
dma_set_max_seg_size(dev, 0xffffffff);
+ if (iommu_capable(dev->bus, IOMMU_CAP_MERGING))
+ dma_set_iova_contiguous(dev, true);
+
return renesas_sdhi_probe(pdev, &renesas_sdhi_internal_dmac_dma_ops);
}
If the IOMMU driver has a capable for merging segments to a segment strictly, this can expose the host->mmc->max_segs with multiple segments to a block layer by using blk_queue_max_segments() that mmc_setup_queue() calls. Notes that an sdio card may be possible to use multiple segments with non page aligned size, so that this will not expose multiple segments to avoid failing dma_map_sg() every time. Notes that on renesas_sdhi_sys_dmac, the max_segs value will change from 32 to 512, but the sys_dmac can handle 512 segments, so that this init_card ops is added on "TMIO_MMC_MIN_RCAR2" environment. Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> --- drivers/mmc/host/renesas_sdhi_core.c | 27 +++++++++++++++++++++++++++ drivers/mmc/host/renesas_sdhi_internal_dmac.c | 4 ++++ 2 files changed, 31 insertions(+)