Commit 03813c81 authored by Prathamesh Shete's avatar Prathamesh Shete Committed by Ulf Hansson
Browse files

mmc: sdhci-tegra: Add support to program MC stream ID



SMMU clients are supposed to program stream ID from their respective
address spaces instead of MC override. Define NVQUIRK_PROGRAM_STREAMID
and use it to program SMMU stream ID from the SDMMC client address
space.

Signed-off-by: default avatarAniruddha TVS Rao <anrao@nvidia.com>
Signed-off-by: default avatarPrathamesh Shete <pshete@nvidia.com>
Acked-by: default avatarAdrian Hunter <adrian.hunter@intel.com>
Acked-by: default avatarThierry Reding <treding@nvidia.com>
Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
Link: https://lore.kernel.org/r/20221206165945.3551774-6-thierry.reding@gmail.com


[Ulf: Fixed a checkpatch error]
Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent 8f00ad01
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@
 * Copyright (C) 2010 Google, Inc.
 */

#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
@@ -10,6 +11,7 @@
#include <linux/gpio/consumer.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/iommu.h>
#include <linux/iopoll.h>
#include <linux/ktime.h>
#include <linux/mmc/card.h>
@@ -95,6 +97,8 @@
#define SDHCI_TEGRA_AUTO_CAL_STATUS			0x1ec
#define SDHCI_TEGRA_AUTO_CAL_ACTIVE			BIT(31)

#define SDHCI_TEGRA_CIF2AXI_CTRL_0			0x1fc

#define NVQUIRK_FORCE_SDHCI_SPEC_200			BIT(0)
#define NVQUIRK_ENABLE_BLOCK_GAP_DET			BIT(1)
#define NVQUIRK_ENABLE_SDHCI_SPEC_300			BIT(2)
@@ -122,6 +126,7 @@
#define NVQUIRK_HAS_TMCLK				BIT(10)

#define NVQUIRK_HAS_ANDROID_GPT_SECTOR			BIT(11)
#define NVQUIRK_PROGRAM_STREAMID			BIT(12)

/* SDMMC CQE Base Address for Tegra Host Ver 4.1 and Higher */
#define SDHCI_TEGRA_CQE_BASE_ADDR			0xF000
@@ -178,6 +183,7 @@ struct sdhci_tegra {
	bool enable_hwcq;
	unsigned long curr_clk_rate;
	u8 tuned_tap_delay;
	u32 stream_id;
};

static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)
@@ -1561,6 +1567,7 @@ static const struct sdhci_tegra_soc_data soc_data_tegra234 = {
		    NVQUIRK_DIS_CARD_CLK_CONFIG_TAP |
		    NVQUIRK_ENABLE_SDR50 |
		    NVQUIRK_ENABLE_SDR104 |
		    NVQUIRK_PROGRAM_STREAMID |
		    NVQUIRK_HAS_TMCLK,
	.min_tap_delay = 95,
	.max_tap_delay = 111,
@@ -1627,6 +1634,19 @@ static int sdhci_tegra_add_host(struct sdhci_host *host)
	return ret;
}

/* Program MC streamID for DMA transfers */
static void sdhci_tegra_program_stream_id(struct sdhci_host *host)
{
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);

	if (tegra_host->soc_data->nvquirks & NVQUIRK_PROGRAM_STREAMID) {
		tegra_sdhci_writel(host, FIELD_PREP(GENMASK(15, 8), tegra_host->stream_id) |
					 FIELD_PREP(GENMASK(7, 0), tegra_host->stream_id),
					 SDHCI_TEGRA_CIF2AXI_CTRL_0);
	}
}

static int sdhci_tegra_probe(struct platform_device *pdev)
{
	const struct sdhci_tegra_soc_data *soc_data;
@@ -1687,6 +1707,12 @@ static int sdhci_tegra_probe(struct platform_device *pdev)

	tegra_sdhci_parse_dt(host);

	if (tegra_host->soc_data->nvquirks & NVQUIRK_PROGRAM_STREAMID &&
	    !tegra_dev_iommu_get_stream_id(&pdev->dev, &tegra_host->stream_id)) {
		dev_warn(mmc_dev(host->mmc), "missing IOMMU stream ID\n");
		tegra_host->stream_id = 0x7f;
	}

	tegra_host->power_gpio = devm_gpiod_get_optional(&pdev->dev, "power",
							 GPIOD_OUT_HIGH);
	if (IS_ERR(tegra_host->power_gpio)) {
@@ -1772,6 +1798,8 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
	if (rc)
		goto err_add_host;

	sdhci_tegra_program_stream_id(host);

	return 0;

err_add_host:
@@ -1868,6 +1896,8 @@ static int sdhci_tegra_resume(struct device *dev)
	if (ret)
		return ret;

	sdhci_tegra_program_stream_id(host);

	ret = sdhci_resume_host(host);
	if (ret)
		goto disable_clk;