From patchwork Sat Dec 15 00:22:20 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sowjanya Komatineni X-Patchwork-Id: 10731915 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 299F814DE for ; Sat, 15 Dec 2018 00:22:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A42122D05F for ; Sat, 15 Dec 2018 00:22:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 92CBE2D0D0; Sat, 15 Dec 2018 00:22:28 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6A9332D05F for ; Sat, 15 Dec 2018 00:22:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726609AbeLOAW0 (ORCPT ); Fri, 14 Dec 2018 19:22:26 -0500 Received: from hqemgate16.nvidia.com ([216.228.121.65]:11415 "EHLO hqemgate16.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726448AbeLOAW0 (ORCPT ); Fri, 14 Dec 2018 19:22:26 -0500 Received: from hqpgpgate101.nvidia.com (Not Verified[216.228.121.13]) by hqemgate16.nvidia.com (using TLS: TLSv1.2, DES-CBC3-SHA) id ; Fri, 14 Dec 2018 16:22:18 -0800 Received: from hqmail.nvidia.com ([172.20.161.6]) by hqpgpgate101.nvidia.com (PGP Universal service); Fri, 14 Dec 2018 16:22:23 -0800 X-PGP-Universal: processed; by hqpgpgate101.nvidia.com on Fri, 14 Dec 2018 16:22:23 -0800 Received: from HQMAIL105.nvidia.com (172.20.187.12) by HQMAIL105.nvidia.com (172.20.187.12) with Microsoft SMTP Server (TLS) id 15.0.1395.4; Sat, 15 Dec 2018 00:22:23 +0000 Received: from hqnvemgw02.nvidia.com (172.16.227.111) by HQMAIL105.nvidia.com (172.20.187.12) with Microsoft SMTP Server (TLS) id 15.0.1395.4 via Frontend Transport; Sat, 15 Dec 2018 00:22:23 +0000 Received: from skomatineni-linux.nvidia.com (Not Verified[10.110.103.52]) by hqnvemgw02.nvidia.com with Trustwave SEG (v7,5,8,10121) id ; Fri, 14 Dec 2018 16:22:23 -0800 From: Sowjanya Komatineni To: , , CC: , , , , Sowjanya Komatineni Subject: [PATCH V1] mmc: tegra: HW Command Queue Support for Tegra SDMMC Date: Fri, 14 Dec 2018 16:22:20 -0800 Message-ID: <1544833340-5024-1-git-send-email-skomatineni@nvidia.com> X-Mailer: git-send-email 2.7.4 X-NVConfidentiality: public MIME-Version: 1.0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1544833338; bh=nZ84WLFvunZ73W0irA8EWdoPgkaqB7m+hKzWvPoUhHA=; h=X-PGP-Universal:From:To:CC:Subject:Date:Message-ID:X-Mailer: X-NVConfidentiality:MIME-Version:Content-Type; b=nsuUP3RUSytfE3BurOfCsYez8yLJqvIMEbjRIvFdmHnVpWwDbxsmeXjxRXWMAbbGd dbRmm/K7PYElwsNC3cQC7RBPY3GZa+3NQcgiwgJ0QukyDxIU3/+06fIDIiUmqS4umQ Dl6Ba6vU6wzwJHEAZAsaPl7VsWkrNPBfN7m+MVV5rXPvPqKQlqcbJ7uH9Xm4+q1JUA 7zKIW1JQHt5c3ylqTupDf8jIwM7iMEpdK8jh9gao+83a442yyrVvrReHmnKNO1PmvM L2OO4QAPuTvdz/0tDkUxfHoaIGCm15jejY4uif84L33UCMWSzXQsyMMs6+szu9x3ah NBL7L53S0LoPA== Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch adds HW Command Queue for supported Tegra SDMMC controllers. Tegra SDHCI with Quirk SDHCI_QUIRK2_BROKEN_64_BIT_DMA disables the use of 64_BIT DMA to disable 64-bit addressing mode access to the system memory and sdhci_cqe_enable using flag SDHCI_USE_64_BIT_DMA for ADMA32/ADMA2 Vs ADMA64/ADMA3 DMA selection. CQE need to use ADMA3 as it need to fetch task descriptor along with transfer descriptor, so this patch forces DMA Select to be ADMA3 for CQE. Note that this patch depends on below patches [0] DMA Config prior to CQE https://lkml.org/lkml/2018/12/14/1062 [1] SDMMC address range https://lkml.org/lkml/2018/12/14/1323 [2] Fix sdhci_do_enable_v4_mode https://lkml.org/lkml/2018/12/14/72 Signed-off-by: Sowjanya Komatineni --- drivers/mmc/host/sdhci-tegra.c | 76 +++++++++++++++++++++++++++++++++++++++++- drivers/mmc/host/sdhci.c | 18 +++++++++- drivers/mmc/host/sdhci.h | 1 + 3 files changed, 93 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 7b95d088fdef..eaebe5e22183 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -33,6 +33,7 @@ #include #include "sdhci-pltfm.h" +#include "cqhci.h" /* Tegra SDHOST controller vendor register definitions */ #define SDHCI_TEGRA_VENDOR_CLOCK_CTRL 0x100 @@ -89,6 +90,10 @@ #define NVQUIRK_NEEDS_PAD_CONTROL BIT(7) #define NVQUIRK_DIS_CARD_CLK_CONFIG_TAP BIT(8) +/* SDMMC CQE Base Address for Tegra Host Ver 4.1 and Higher */ +#define SDHCI_TEGRA_CQE_BASE_ADDR 0xF000 + + struct sdhci_tegra_soc_data { const struct sdhci_pltfm_data *pdata; u32 nvquirks; @@ -128,6 +133,7 @@ struct sdhci_tegra { u32 default_tap; u32 default_trim; u32 dqs_trim; + bool enable_hwcq; }; static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg) @@ -836,6 +842,17 @@ static void tegra_sdhci_voltage_switch(struct sdhci_host *host) tegra_host->pad_calib_required = true; } +static void sdhci_tegra_dumpregs(struct mmc_host *mmc) +{ + sdhci_dumpregs(mmc_priv(mmc)); +} + +static const struct cqhci_host_ops sdhci_tegra_cqhci_ops = { + .enable = sdhci_cqe_enable, + .disable = sdhci_cqe_disable, + .dumpregs = sdhci_tegra_dumpregs, +}; + static const struct sdhci_ops tegra_sdhci_ops = { .get_ro = tegra_sdhci_get_ro, .read_w = tegra_sdhci_readw, @@ -989,6 +1006,7 @@ static const struct sdhci_ops tegra186_sdhci_ops = { .set_uhs_signaling = tegra_sdhci_set_uhs_signaling, .voltage_switch = tegra_sdhci_voltage_switch, .get_max_clock = tegra_sdhci_get_max_clock, + .irq = sdhci_cqhci_irq, }; static const struct sdhci_pltfm_data sdhci_tegra186_pdata = { @@ -1030,6 +1048,55 @@ static const struct of_device_id sdhci_tegra_dt_match[] = { }; MODULE_DEVICE_TABLE(of, sdhci_tegra_dt_match); +static int sdhci_tegra_add_host(struct sdhci_host *host) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); + struct cqhci_host *cq_host; + bool dma64; + int ret; + + if (!tegra_host->enable_hwcq) + return sdhci_add_host(host); + + host->v4_mode = true; + + ret = sdhci_setup_host(host); + if (ret) + return ret; + + host->mmc->caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD; + + cq_host = devm_kzalloc(host->mmc->parent, + sizeof(*cq_host), GFP_KERNEL); + if (!cq_host) { + ret = -ENOMEM; + goto cleanup; + } + + cq_host->mmio = host->ioaddr + SDHCI_TEGRA_CQE_BASE_ADDR; + cq_host->ops = &sdhci_tegra_cqhci_ops; + + dma64 = host->flags & SDHCI_USE_64_BIT_DMA; + if (dma64) + cq_host->caps |= CQHCI_TASK_DESC_SZ_128; + + ret = cqhci_init(cq_host, host->mmc, dma64); + if (ret) + goto cleanup; + + ret = __sdhci_add_host(host); + if (ret) + goto cleanup; + + return 0; + +cleanup: + sdhci_cleanup_host(host); + return ret; + +} + static int sdhci_tegra_probe(struct platform_device *pdev) { const struct of_device_id *match; @@ -1039,6 +1106,7 @@ static int sdhci_tegra_probe(struct platform_device *pdev) struct sdhci_tegra *tegra_host; struct clk *clk; int rc; + struct resource *iomem; match = of_match_device(sdhci_tegra_dt_match, &pdev->dev); if (!match) @@ -1056,6 +1124,12 @@ static int sdhci_tegra_probe(struct platform_device *pdev) tegra_host->pad_control_available = false; tegra_host->soc_data = soc_data; + iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (resource_size(iomem) > SDHCI_TEGRA_CQE_BASE_ADDR) + tegra_host->enable_hwcq = true; + else + tegra_host->enable_hwcq = false; + if (soc_data->nvquirks & NVQUIRK_NEEDS_PAD_CONTROL) { rc = tegra_sdhci_init_pinctrl_info(&pdev->dev, tegra_host); if (rc == 0) @@ -1117,7 +1191,7 @@ static int sdhci_tegra_probe(struct platform_device *pdev) usleep_range(2000, 4000); - rc = sdhci_add_host(host); + rc = sdhci_tegra_add_host(host); if (rc) goto err_add_host; diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 99bdae53fa2e..8c03c7a3dab2 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -36,6 +36,7 @@ #include #include "sdhci.h" +#include "cqhci.h" #define DRIVER_NAME "sdhci" @@ -3308,7 +3309,8 @@ void sdhci_cqe_enable(struct mmc_host *mmc) ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); ctrl &= ~SDHCI_CTRL_DMA_MASK; - if (host->flags & SDHCI_USE_64_BIT_DMA) + if ((host->flags & SDHCI_USE_64_BIT_DMA) || + (host->quirks2 & SDHCI_QUIRK2_BROKEN_64_BIT_DMA)) ctrl |= SDHCI_CTRL_ADMA64; else ctrl |= SDHCI_CTRL_ADMA32; @@ -3361,6 +3363,20 @@ void sdhci_cqe_disable(struct mmc_host *mmc, bool recovery) } EXPORT_SYMBOL_GPL(sdhci_cqe_disable); +u32 sdhci_cqhci_irq(struct sdhci_host *host, u32 intmask) +{ + int cmd_error = 0; + int data_error = 0; + + if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error)) + return intmask; + + cqhci_irq(host->mmc, intmask, cmd_error, data_error); + + return 0; +} +EXPORT_SYMBOL_GPL(sdhci_cqhci_irq); + bool sdhci_cqe_irq(struct sdhci_host *host, u32 intmask, int *cmd_error, int *data_error) { diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index b001cf4d3d7e..9ff7a138270e 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -777,6 +777,7 @@ void sdhci_cqe_enable(struct mmc_host *mmc); void sdhci_cqe_disable(struct mmc_host *mmc, bool recovery); bool sdhci_cqe_irq(struct sdhci_host *host, u32 intmask, int *cmd_error, int *data_error); +u32 sdhci_cqhci_irq(struct sdhci_host *host, u32 intmask); void sdhci_dumpregs(struct sdhci_host *host); void sdhci_enable_v4_mode(struct sdhci_host *host);