summaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorSowjanya Komatineni <skomatineni@nvidia.com>2019-01-23 14:30:54 -0500
committerUlf Hansson <ulf.hansson@linaro.org>2019-02-25 02:40:58 -0500
commit3c4019f979783575c50db35eae80f30b382e9e49 (patch)
treee61f3beadf0a2e0326e776e7b32be6d70e815e2e /drivers/mmc
parent4c4faff62bf59e64c5175b7704727e6b9db361f2 (diff)
mmc: tegra: HW Command Queue Support for Tegra SDMMC
This patch adds HW Command Queue for supported Tegra SDMMC controllers. Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com> Acked-by: Adrian Hunter <adrian.hunter@intel.com> Acked-by: Thierry Reding <treding@nvidia.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/Kconfig1
-rw-r--r--drivers/mmc/host/sdhci-tegra.c117
2 files changed, 114 insertions, 4 deletions
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index d1769f1d060d..28fcd8f580a1 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -251,6 +251,7 @@ config MMC_SDHCI_TEGRA
251 depends on ARCH_TEGRA 251 depends on ARCH_TEGRA
252 depends on MMC_SDHCI_PLTFM 252 depends on MMC_SDHCI_PLTFM
253 select MMC_SDHCI_IO_ACCESSORS 253 select MMC_SDHCI_IO_ACCESSORS
254 select MMC_CQHCI
254 help 255 help
255 This selects the Tegra SD/MMC controller. If you have a Tegra 256 This selects the Tegra SD/MMC controller. If you have a Tegra
256 platform with SD or MMC devices, say Y or M here. 257 platform with SD or MMC devices, say Y or M here.
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 7d681a8fa4ba..31d7ae4f1e20 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -33,6 +33,7 @@
33#include <linux/ktime.h> 33#include <linux/ktime.h>
34 34
35#include "sdhci-pltfm.h" 35#include "sdhci-pltfm.h"
36#include "cqhci.h"
36 37
37/* Tegra SDHOST controller vendor register definitions */ 38/* Tegra SDHOST controller vendor register definitions */
38#define SDHCI_TEGRA_VENDOR_CLOCK_CTRL 0x100 39#define SDHCI_TEGRA_VENDOR_CLOCK_CTRL 0x100
@@ -90,6 +91,9 @@
90#define NVQUIRK_NEEDS_PAD_CONTROL BIT(7) 91#define NVQUIRK_NEEDS_PAD_CONTROL BIT(7)
91#define NVQUIRK_DIS_CARD_CLK_CONFIG_TAP BIT(8) 92#define NVQUIRK_DIS_CARD_CLK_CONFIG_TAP BIT(8)
92 93
94/* SDMMC CQE Base Address for Tegra Host Ver 4.1 and Higher */
95#define SDHCI_TEGRA_CQE_BASE_ADDR 0xF000
96
93struct sdhci_tegra_soc_data { 97struct sdhci_tegra_soc_data {
94 const struct sdhci_pltfm_data *pdata; 98 const struct sdhci_pltfm_data *pdata;
95 u32 nvquirks; 99 u32 nvquirks;
@@ -131,6 +135,7 @@ struct sdhci_tegra {
131 u32 default_tap; 135 u32 default_tap;
132 u32 default_trim; 136 u32 default_trim;
133 u32 dqs_trim; 137 u32 dqs_trim;
138 bool enable_hwcq;
134}; 139};
135 140
136static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg) 141static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)
@@ -685,6 +690,20 @@ static void tegra_sdhci_parse_tap_and_trim(struct sdhci_host *host)
685 tegra_host->dqs_trim = 0x11; 690 tegra_host->dqs_trim = 0x11;
686} 691}
687 692
693static void tegra_sdhci_parse_dt(struct sdhci_host *host)
694{
695 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
696 struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
697
698 if (device_property_read_bool(host->mmc->parent, "supports-cqe"))
699 tegra_host->enable_hwcq = true;
700 else
701 tegra_host->enable_hwcq = false;
702
703 tegra_sdhci_parse_pad_autocal_dt(host);
704 tegra_sdhci_parse_tap_and_trim(host);
705}
706
688static void tegra_sdhci_set_clock(struct sdhci_host *host, unsigned int clock) 707static void tegra_sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
689{ 708{
690 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 709 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -914,6 +933,49 @@ static void tegra_sdhci_voltage_switch(struct sdhci_host *host)
914 tegra_host->pad_calib_required = true; 933 tegra_host->pad_calib_required = true;
915} 934}
916 935
936static void sdhci_tegra_cqe_enable(struct mmc_host *mmc)
937{
938 struct cqhci_host *cq_host = mmc->cqe_private;
939 u32 cqcfg = 0;
940
941 /*
942 * Tegra SDMMC Controller design prevents write access to BLOCK_COUNT
943 * registers when CQE is enabled.
944 */
945 cqcfg = cqhci_readl(cq_host, CQHCI_CFG);
946 if (cqcfg & CQHCI_ENABLE)
947 cqhci_writel(cq_host, (cqcfg & ~CQHCI_ENABLE), CQHCI_CFG);
948
949 sdhci_cqe_enable(mmc);
950
951 if (cqcfg & CQHCI_ENABLE)
952 cqhci_writel(cq_host, cqcfg, CQHCI_CFG);
953}
954
955static void sdhci_tegra_dumpregs(struct mmc_host *mmc)
956{
957 sdhci_dumpregs(mmc_priv(mmc));
958}
959
960static u32 sdhci_tegra_cqhci_irq(struct sdhci_host *host, u32 intmask)
961{
962 int cmd_error = 0;
963 int data_error = 0;
964
965 if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error))
966 return intmask;
967
968 cqhci_irq(host->mmc, intmask, cmd_error, data_error);
969
970 return 0;
971}
972
973static const struct cqhci_host_ops sdhci_tegra_cqhci_ops = {
974 .enable = sdhci_tegra_cqe_enable,
975 .disable = sdhci_cqe_disable,
976 .dumpregs = sdhci_tegra_dumpregs,
977};
978
917static const struct sdhci_ops tegra_sdhci_ops = { 979static const struct sdhci_ops tegra_sdhci_ops = {
918 .get_ro = tegra_sdhci_get_ro, 980 .get_ro = tegra_sdhci_get_ro,
919 .read_w = tegra_sdhci_readw, 981 .read_w = tegra_sdhci_readw,
@@ -1067,6 +1129,7 @@ static const struct sdhci_ops tegra186_sdhci_ops = {
1067 .set_uhs_signaling = tegra_sdhci_set_uhs_signaling, 1129 .set_uhs_signaling = tegra_sdhci_set_uhs_signaling,
1068 .voltage_switch = tegra_sdhci_voltage_switch, 1130 .voltage_switch = tegra_sdhci_voltage_switch,
1069 .get_max_clock = tegra_sdhci_get_max_clock, 1131 .get_max_clock = tegra_sdhci_get_max_clock,
1132 .irq = sdhci_tegra_cqhci_irq,
1070}; 1133};
1071 1134
1072static const struct sdhci_pltfm_data sdhci_tegra186_pdata = { 1135static const struct sdhci_pltfm_data sdhci_tegra186_pdata = {
@@ -1108,6 +1171,54 @@ static const struct of_device_id sdhci_tegra_dt_match[] = {
1108}; 1171};
1109MODULE_DEVICE_TABLE(of, sdhci_tegra_dt_match); 1172MODULE_DEVICE_TABLE(of, sdhci_tegra_dt_match);
1110 1173
1174static int sdhci_tegra_add_host(struct sdhci_host *host)
1175{
1176 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
1177 struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
1178 struct cqhci_host *cq_host;
1179 bool dma64;
1180 int ret;
1181
1182 if (!tegra_host->enable_hwcq)
1183 return sdhci_add_host(host);
1184
1185 sdhci_enable_v4_mode(host);
1186
1187 ret = sdhci_setup_host(host);
1188 if (ret)
1189 return ret;
1190
1191 host->mmc->caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD;
1192
1193 cq_host = devm_kzalloc(host->mmc->parent,
1194 sizeof(*cq_host), GFP_KERNEL);
1195 if (!cq_host) {
1196 ret = -ENOMEM;
1197 goto cleanup;
1198 }
1199
1200 cq_host->mmio = host->ioaddr + SDHCI_TEGRA_CQE_BASE_ADDR;
1201 cq_host->ops = &sdhci_tegra_cqhci_ops;
1202
1203 dma64 = host->flags & SDHCI_USE_64_BIT_DMA;
1204 if (dma64)
1205 cq_host->caps |= CQHCI_TASK_DESC_SZ_128;
1206
1207 ret = cqhci_init(cq_host, host->mmc, dma64);
1208 if (ret)
1209 goto cleanup;
1210
1211 ret = __sdhci_add_host(host);
1212 if (ret)
1213 goto cleanup;
1214
1215 return 0;
1216
1217cleanup:
1218 sdhci_cleanup_host(host);
1219 return ret;
1220}
1221
1111static int sdhci_tegra_probe(struct platform_device *pdev) 1222static int sdhci_tegra_probe(struct platform_device *pdev)
1112{ 1223{
1113 const struct of_device_id *match; 1224 const struct of_device_id *match;
@@ -1155,9 +1266,7 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
1155 if (tegra_host->soc_data->nvquirks & NVQUIRK_ENABLE_DDR50) 1266 if (tegra_host->soc_data->nvquirks & NVQUIRK_ENABLE_DDR50)
1156 host->mmc->caps |= MMC_CAP_1_8V_DDR; 1267 host->mmc->caps |= MMC_CAP_1_8V_DDR;
1157 1268
1158 tegra_sdhci_parse_pad_autocal_dt(host); 1269 tegra_sdhci_parse_dt(host);
1159
1160 tegra_sdhci_parse_tap_and_trim(host);
1161 1270
1162 tegra_host->power_gpio = devm_gpiod_get_optional(&pdev->dev, "power", 1271 tegra_host->power_gpio = devm_gpiod_get_optional(&pdev->dev, "power",
1163 GPIOD_OUT_HIGH); 1272 GPIOD_OUT_HIGH);
@@ -1195,7 +1304,7 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
1195 1304
1196 usleep_range(2000, 4000); 1305 usleep_range(2000, 4000);
1197 1306
1198 rc = sdhci_add_host(host); 1307 rc = sdhci_tegra_add_host(host);
1199 if (rc) 1308 if (rc)
1200 goto err_add_host; 1309 goto err_add_host;
1201 1310