From patchwork Thu Dec 4 12:09:20 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Barry Song <21cnbao@gmail.com> X-Patchwork-Id: 5437901 Return-Path: X-Original-To: patchwork-linux-mmc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 34BB19F319 for ; Thu, 4 Dec 2014 12:09:39 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 40D59201F4 for ; Thu, 4 Dec 2014 12:09:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 263D9201F2 for ; Thu, 4 Dec 2014 12:09:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753924AbaLDMJg (ORCPT ); Thu, 4 Dec 2014 07:09:36 -0500 Received: from mail-pd0-f181.google.com ([209.85.192.181]:35976 "EHLO mail-pd0-f181.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753915AbaLDMJf (ORCPT ); Thu, 4 Dec 2014 07:09:35 -0500 Received: by mail-pd0-f181.google.com with SMTP id v10so12250290pde.12 for ; Thu, 04 Dec 2014 04:09:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=CqT5cV/gSq3OTOJpy9eGlNykyhiHHKZk26ZzcjdO4QA=; b=sLV3izQpEo7CTVx3OfpiIAkXs98Cjdt9iLyXHLmsUfm+7v/8vXMgmbACswLVmHSxL9 n6UPbkoUKgblYmwrzrOm6ki+ELmOmKW5OTDSrv9SkJLsAbnHCLw9VCwHPwCXgAzw2ZKG KmHjxEu7qxKH2VGvKu8BDiijtrAVT9guOZh8R3Thq6wh+7dqV2hcirV4r+xmfyg2zcFC go4Cu7+u/EA++JHqO+uMui286T/0YLcQa42SK/5knF2niCb1rFQM0yPBdLkFYnfq/cWZ BO4DKr7LUH1vn4mYPVMI3CT4qRMLd+ZSejgNEXGst7Zh7uuyRx0DcmjAwm/5eGyzenfN 0gAQ== X-Received: by 10.70.47.37 with SMTP id a5mr17965944pdn.93.1417694974731; Thu, 04 Dec 2014 04:09:34 -0800 (PST) Received: from localhost.localdomain ([61.135.213.198]) by mx.google.com with ESMTPSA id m5sm25930459pdp.53.2014.12.04.04.09.28 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 04 Dec 2014 04:09:33 -0800 (PST) From: Barry Song <21cnbao@gmail.com> To: ulf.hansson@linaro.org, chris@printf.net Cc: linux-mmc@vger.kernel.org, linux-arm-kernel@lists.infradead.org, workgroup.linux@csr.com, Minda Chen , Barry Song Subject: [PATCH v2] mmc: sdhci-sirf: add sirf tuning function (cmd 19) Date: Thu, 4 Dec 2014 20:09:20 +0800 Message-Id: <1417694960-5664-1-git-send-email-21cnbao@gmail.com> X-Mailer: git-send-email 1.9.1 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Minda Chen Add manual tuning function in CSR atlas7 SoC. It is mainly used for the UHS-I SD card working SDR50 SDR104 mode. The tuning principle can be seen in SD spec part1 v3.01 4.2.4.5 (tuning command). SD host send the cmd19 and set the delay value(0-127). and the sdcard return 64 bytes data. If the data is same with the tuning data. The delay value is valid. Execute this commmand 128 times. And calculate the longest window of the valid values. The value in the middle of this window is the best value. Signed-off-by: Minda Chen Signed-off-by: Barry Song --- drivers/mmc/host/sdhci-sirf.c | 71 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/drivers/mmc/host/sdhci-sirf.c b/drivers/mmc/host/sdhci-sirf.c index dd29d47..e458d18 100644 --- a/drivers/mmc/host/sdhci-sirf.c +++ b/drivers/mmc/host/sdhci-sirf.c @@ -15,7 +15,9 @@ #include #include "sdhci-pltfm.h" +#define SDHCI_CLK_DELAY_SETTING 0x4C #define SDHCI_SIRF_8BITBUS BIT(3) +#define SIRF_TUNING_COUNT 128 struct sdhci_sirf_priv { struct clk *clk; @@ -49,7 +51,76 @@ static void sdhci_sirf_set_bus_width(struct sdhci_host *host, int width) sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); } +static int sdhci_sirf_execute_tuning(struct sdhci_host *host, u32 opcode) +{ + int tuning_seq_cnt = 3; + u8 phase, tuned_phases[SIRF_TUNING_COUNT]; + u8 tuned_phase_cnt = 0; + int rc, longest_range = 0; + int start = -1, end = 0, tuning_value = -1, range = 0; + u16 clock_setting; + struct mmc_host *mmc = host->mmc; + + clock_setting = sdhci_readw(host, SDHCI_CLK_DELAY_SETTING); + clock_setting &= ~0x3fff; + +retry: + phase = 0; + do { + sdhci_writel(host, + clock_setting | phase | (phase << 7) | (phase << 16), + SDHCI_CLK_DELAY_SETTING); + + if (!mmc_send_tuning(mmc->card)) { + /* Tuning is successful at this tuning point */ + tuned_phases[tuned_phase_cnt++] = phase; + dev_dbg(mmc_dev(mmc), "%s: Found good phase = %d\n", + mmc_hostname(mmc), phase); + if (start == -1) + start = phase; + end = phase; + range++; + if (phase == (SIRF_TUNING_COUNT - 1) + && range > longest_range) + tuning_value = (start + end) / 2; + } else { + dev_dbg(mmc_dev(mmc), "%s: Found bad phase = %d\n", + mmc_hostname(mmc), phase); + if (range > longest_range) { + tuning_value = (start + end) / 2; + longest_range = range; + } + start = -1; + end = range = 0; + } + } while (++phase < ARRAY_SIZE(tuned_phases)); + + if (tuned_phase_cnt && tuning_value > 0) { + /* + * Finally set the selected phase in delay + * line hw block. + */ + phase = tuning_value; + sdhci_writel(host, + clock_setting | phase | (phase << 7) | (phase << 16), + SDHCI_CLK_DELAY_SETTING); + + dev_dbg(mmc_dev(mmc), "%s: Setting the tuning phase to %d\n", + mmc_hostname(mmc), phase); + } else { + if (--tuning_seq_cnt) + goto retry; + /* Tuning failed */ + dev_dbg(mmc_dev(mmc), "%s: No tuning point found\n", + mmc_hostname(mmc)); + rc = -EIO; + } + + return rc; +} + static struct sdhci_ops sdhci_sirf_ops = { + .platform_execute_tuning = sdhci_sirf_execute_tuning, .set_clock = sdhci_set_clock, .get_max_clock = sdhci_sirf_get_max_clk, .set_bus_width = sdhci_sirf_set_bus_width,