Received: by 2002:ac0:950c:0:0:0:0:0 with SMTP id f12csp3318187imc; Wed, 13 Mar 2019 14:47:05 -0700 (PDT) X-Google-Smtp-Source: APXvYqxygBnVz3G3gfaoAOzy+cClo2gSGwFuWr4wZBtfNY4AI3BH9hpsuQkd25V8DJNFTzXpv4ql X-Received: by 2002:a62:a10c:: with SMTP id b12mr45574266pff.234.1552513625119; Wed, 13 Mar 2019 14:47:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1552513625; cv=none; d=google.com; s=arc-20160816; b=LaWZ30XNM+bNKqUivLCl+jz+XX1Gw/ytYzU7AoBira18piYjzRyJXRrMMoUOmGrY5+ xjerJE0ia6SDnEz/Px+DUrMhR/aegvhMTjxzRDJuVuZfHUWLyramQ7kbVHBATxW0rU8A tPUuP4i/+eouHLg2e68zPm0HgLwH5MgzV5WyRyZIa3E26b4/tCJ/LPsxyRd4CkUSVbr0 qHxA/Ji0vAwZduZTklvqtIMyezm32bNLQzTcfthIaXwQGC9UZydDSak44gmaLdw2HQfQ /CWXFzY2qCq7UucVQCXdyb0slZzX9FBbFrDhLxBDwmhcrmsY65H9/ltvg8OEwznwrOeL m+Ug== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:dkim-signature:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from; bh=DguQa0ntN9xE9Z540e0bu31/uO1/gabW7rA3OEYVaGk=; b=rWF5bQ6KC7asr6cWKSVWMij2MvtUVevJ+t+78UaundHugy2dlyr7RwWvRP1NXSR/79 fjGQIeV51VVRXyLpJxRNDIMAtYhKOGjidfa6NBjRuyQv5gmmpnWKrpiwbYWS3LP/8dlQ gdRVD6ezZ15DR3SWmDk2IYppOSiZHNGWT9CxTWC2uYxWabIzF79p1HFQjQK23C/WAcah 6xOs1qsfLnCzorH6bqSLJFMD2cOhwGw8fT9E9Vl+jRGeXU97dlR90bqyqeLAQdtVSvuq kn2UFChXqqUlpkImVd96QTda79TX8sRSpurMjHPno+TBJAAWEjpIvdQTtoHwWdW+VLog HVpg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@nvidia.com header.s=n1 header.b=RHmLd9bv; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=nvidia.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id p9si301394plq.127.2019.03.13.14.46.49; Wed, 13 Mar 2019 14:47:05 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@nvidia.com header.s=n1 header.b=RHmLd9bv; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=nvidia.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727617AbfCMVqG (ORCPT + 99 others); Wed, 13 Mar 2019 17:46:06 -0400 Received: from hqemgate15.nvidia.com ([216.228.121.64]:19143 "EHLO hqemgate15.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727586AbfCMVqD (ORCPT ); Wed, 13 Mar 2019 17:46:03 -0400 Received: from hqpgpgate101.nvidia.com (Not Verified[216.228.121.13]) by hqemgate15.nvidia.com (using TLS: TLSv1.2, DES-CBC3-SHA) id ; Wed, 13 Mar 2019 14:45:49 -0700 Received: from hqmail.nvidia.com ([172.20.161.6]) by hqpgpgate101.nvidia.com (PGP Universal service); Wed, 13 Mar 2019 14:46:01 -0700 X-PGP-Universal: processed; by hqpgpgate101.nvidia.com on Wed, 13 Mar 2019 14:46:01 -0700 Received: from HQMAIL104.nvidia.com (172.18.146.11) by HQMAIL108.nvidia.com (172.18.146.13) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Wed, 13 Mar 2019 21:46:01 +0000 Received: from hqnvemgw02.nvidia.com (172.16.227.111) by HQMAIL104.nvidia.com (172.18.146.11) with Microsoft SMTP Server (TLS) id 15.0.1473.3 via Frontend Transport; Wed, 13 Mar 2019 21:46:01 +0000 Received: from skomatineni-linux.nvidia.com (Not Verified[10.110.103.74]) by hqnvemgw02.nvidia.com with Trustwave SEG (v7,5,8,10121) id ; Wed, 13 Mar 2019 14:46:01 -0700 From: Sowjanya Komatineni To: , , , , CC: , , , , , , , Subject: [PATCH V3 09/10] mmc: tegra: fix CQE enable and resume sequence Date: Wed, 13 Mar 2019 14:45:51 -0700 Message-ID: <1552513552-23423-9-git-send-email-skomatineni@nvidia.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1552513552-23423-1-git-send-email-skomatineni@nvidia.com> References: <1552513552-23423-1-git-send-email-skomatineni@nvidia.com> X-NVConfidentiality: public MIME-Version: 1.0 Content-Type: text/plain DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1552513550; bh=DguQa0ntN9xE9Z540e0bu31/uO1/gabW7rA3OEYVaGk=; h=X-PGP-Universal:From:To:CC:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:X-NVConfidentiality:MIME-Version: Content-Type; b=RHmLd9bvwACB4Ht4fksECbDkCRmhoKz/fs//dH1NmwOk0y/j2lHLc7hg6YIc5Y6Pb M5eJe2bPJysRluhQzNEGvRS3O6Ihsnn8Jrhph2G6BpTqDNJUplc9l4Mc8rmuRacGdm oAng6upvJVmq67VP7XN53rxF8B+o1zqe/qoQTExnT4cARLFN3Yp9pQMNaWffcg9xfK 7PnO3facpAm+rhWt79GvTpuCwLb6QOaoGA7qnqZ3fAv47XqKXmCVF1vkziBj9Caqom aQJ7AczPVpdy93me6TH2s6Qg94BAefKyrS3dWMwzUareBrUssxGaxMqSfxHlr4wY0b nJ/Jr0kHUB0dg== Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Tegra CQHCI/SDHCI design prevents write access to SDHCI block size register when CQE is enabled and unhalted. CQHCI driver enables CQE prior to invoking sdhci_cqe_enable which violates this Tegra specific host requirement. This patch fixes this by configuring sdhci block registers prior to CQE unhalt. This patch also has a fix for retry of unhalt due to known Tegra specific CQE resume bug where first unhalt might not succeed when clear all tasks is performed prior to resume and need a second unhalt. This patch also includes CQE enable fix for CMD CRC errors that happen with the specific sandisk emmc device when status command is sent during the transfer of last data block due to marginal timing. Tested-by: Jon Hunter Acked-by: Adrian Hunter Signed-off-by: Sowjanya Komatineni --- drivers/mmc/host/sdhci-tegra.c | 72 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 62 insertions(+), 10 deletions(-) diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 2f08b6e480df..eafaaefab4a6 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -1124,6 +1124,43 @@ static void tegra_sdhci_voltage_switch(struct sdhci_host *host) tegra_host->pad_calib_required = true; } +static void tegra_cqhci_writel(struct cqhci_host *cq_host, u32 val, int reg) +{ + struct mmc_host *mmc = cq_host->mmc; + u8 ctrl; + ktime_t timeout; + bool timed_out; + + /* + * During CQE resume/unhalt, CQHCI driver unhalts CQE prior to + * cqhci_host_ops enable where SDHCI DMA and BLOCK_SIZE registers need + * to be re-configured. + * Tegra CQHCI/SDHCI prevents write access to block size register when + * CQE is unhalted. So handling CQE resume sequence here to configure + * SDHCI block registers prior to exiting CQE halt state. + */ + if (reg == CQHCI_CTL && !(val & CQHCI_HALT) && + cqhci_readl(cq_host, CQHCI_CTL) & CQHCI_HALT) { + sdhci_cqe_enable(mmc); + writel(val, cq_host->mmio + reg); + timeout = ktime_add_us(ktime_get(), 50); + while (1) { + timed_out = ktime_compare(ktime_get(), timeout) > 0; + ctrl = cqhci_readl(cq_host, CQHCI_CTL); + if (!(ctrl & CQHCI_HALT) || timed_out) + break; + } + /* + * CQE usually resumes very quick, but incase if Tegra CQE + * doesn't resume retry unhalt. + */ + if (timed_out) + writel(val, cq_host->mmio + reg); + } else { + writel(val, cq_host->mmio + reg); + } +} + static void sdhci_tegra_update_dcmd_desc(struct mmc_host *mmc, struct mmc_request *mrq, u64 *data) { @@ -1139,20 +1176,34 @@ static void sdhci_tegra_update_dcmd_desc(struct mmc_host *mmc, static void sdhci_tegra_cqe_enable(struct mmc_host *mmc) { struct cqhci_host *cq_host = mmc->cqe_private; - u32 cqcfg = 0; + u32 val; /* - * Tegra SDMMC Controller design prevents write access to BLOCK_COUNT - * registers when CQE is enabled. + * Tegra CQHCI/SDMMC design prevents write access to sdhci block size + * register when CQE is enabled and unhalted. + * CQHCI driver enables CQE prior to activation, so disable CQE before + * programming block size in sdhci controller and enable it back. */ - cqcfg = cqhci_readl(cq_host, CQHCI_CFG); - if (cqcfg & CQHCI_ENABLE) - cqhci_writel(cq_host, (cqcfg & ~CQHCI_ENABLE), CQHCI_CFG); - - sdhci_cqe_enable(mmc); + if (!cq_host->activated) { + val = cqhci_readl(cq_host, CQHCI_CFG); + if (val & CQHCI_ENABLE) + cqhci_writel(cq_host, (val & ~CQHCI_ENABLE), + CQHCI_CFG); + sdhci_cqe_enable(mmc); + if (val & CQHCI_ENABLE) + cqhci_writel(cq_host, val, CQHCI_CFG); + } - if (cqcfg & CQHCI_ENABLE) - cqhci_writel(cq_host, cqcfg, CQHCI_CFG); + /* + * CMD CRC errors are seen sometimes with some eMMC devices when status + * command is sent during transfer of last data block which is the + * default case as send status command block counter (CBC) is 1. + * Recommended fix to set CBC to 0 allowing send status command only + * when data lines are idle. + */ + val = cqhci_readl(cq_host, CQHCI_SSC1); + val &= ~CQHCI_SSC1_CBC_MASK; + cqhci_writel(cq_host, val, CQHCI_SSC1); } static void sdhci_tegra_dumpregs(struct mmc_host *mmc) @@ -1174,6 +1225,7 @@ static u32 sdhci_tegra_cqhci_irq(struct sdhci_host *host, u32 intmask) } static const struct cqhci_host_ops sdhci_tegra_cqhci_ops = { + .write_l = tegra_cqhci_writel, .enable = sdhci_tegra_cqe_enable, .disable = sdhci_cqe_disable, .dumpregs = sdhci_tegra_dumpregs, -- 2.7.4