From patchwork Fri Jul 14 06:42:56 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chen-Yu Tsai X-Patchwork-Id: 9839959 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id C0DF3602D8 for ; Fri, 14 Jul 2017 06:43:43 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B027A28763 for ; Fri, 14 Jul 2017 06:43:43 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A521628780; Fri, 14 Jul 2017 06:43:43 +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=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable 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 52F6928763 for ; Fri, 14 Jul 2017 06:43:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753330AbdGNGnY (ORCPT ); Fri, 14 Jul 2017 02:43:24 -0400 Received: from mirror2.csie.ntu.edu.tw ([140.112.30.76]:58800 "EHLO wens.csie.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751340AbdGNGnT (ORCPT ); Fri, 14 Jul 2017 02:43:19 -0400 Received: by wens.csie.org (Postfix, from userid 1000) id 1AC855FEE6; Fri, 14 Jul 2017 14:43:08 +0800 (CST) From: Chen-Yu Tsai To: Maxime Ripard , Ulf Hansson , Michael Turquette , Stephen Boyd , Rob Herring , Mark Rutland Cc: Chen-Yu Tsai , linux-arm-kernel@lists.infradead.org, linux-mmc@vger.kernel.org, linux-clk@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-sunxi@googlegroups.com Subject: [PATCH 05/11] mmc: sunxi: Support controllers that can use both old and new timings Date: Fri, 14 Jul 2017 14:42:56 +0800 Message-Id: <20170714064302.20383-6-wens@csie.org> X-Mailer: git-send-email 2.13.2 In-Reply-To: <20170714064302.20383-1-wens@csie.org> References: <20170714064302.20383-1-wens@csie.org> Sender: linux-clk-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-clk@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP On the SoCs that introduced the new timing mode for MMC controllers, both the old (where the clock delays are set in the CCU) and new (where the clock delays are set in the MMC controller) timing modes are available, and we have to support them both. However there are two bits that control which mode is active. One is in the CCU, the other is in the MMC controller. The settings on both sides must be the same, or nothing will work. The CCU's get/set_phase callbacks return -ENOTSUPP when the new timing mode is active. This provides a way to know which mode is active on that side, and we can set the bit on the MMC controller side accordingly. Signed-off-by: Chen-Yu Tsai --- drivers/mmc/host/sunxi-mmc.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c index 0fb4e4c119e1..56e45c65b52d 100644 --- a/drivers/mmc/host/sunxi-mmc.c +++ b/drivers/mmc/host/sunxi-mmc.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -259,7 +260,7 @@ struct sunxi_mmc_cfg { /* Does DATA0 needs to be masked while the clock is updated */ bool mask_data0; - bool needs_new_timings; + bool has_new_timings; }; struct sunxi_mmc_host { @@ -293,6 +294,9 @@ struct sunxi_mmc_host { /* vqmmc */ bool vqmmc_enabled; + + /* timings */ + bool use_new_timings; }; static int sunxi_mmc_reset_host(struct sunxi_mmc_host *host) @@ -714,7 +718,7 @@ static int sunxi_mmc_clk_set_phase(struct sunxi_mmc_host *host, { int index; - if (!host->cfg->clk_delays) + if (host->use_new_timings) return 0; /* determine delays */ @@ -765,6 +769,15 @@ static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host, ios->bus_width == MMC_BUS_WIDTH_8) clock <<= 1; + if (host->use_new_timings) { + ret = sunxi_ccu_set_mmc_timing_mode(host->clk_mmc, true); + if (ret) { + dev_err(mmc_dev(mmc), + "error setting new timing mode\n"); + return ret; + } + } + rate = clk_round_rate(host->clk_mmc, clock); if (rate < 0) { dev_err(mmc_dev(mmc), "error rounding clk to %d: %ld\n", @@ -793,7 +806,7 @@ static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host, } mmc_writel(host, REG_CLKCR, rval); - if (host->cfg->needs_new_timings) { + if (host->use_new_timings) { /* Don't touch the delay bits */ rval = mmc_readl(host, REG_SD_NTSR); rval |= SDXC_2X_TIMING_MODE; @@ -1105,7 +1118,7 @@ static const struct sunxi_mmc_cfg sun50i_a64_cfg = { .clk_delays = NULL, .can_calibrate = true, .mask_data0 = true, - .needs_new_timings = true, + .has_new_timings = true, }; static const struct sunxi_mmc_cfg sun50i_a64_emmc_cfg = { @@ -1262,6 +1275,19 @@ static int sunxi_mmc_probe(struct platform_device *pdev) goto error_free_host; } + if (host->cfg->clk_delays && host->cfg->has_new_timings) { + /* + * Supports both old and new timing modes. + * Try setting the clk to new timing mode. + */ + ret = sunxi_ccu_set_mmc_timing_mode(host->clk_mmc, true); + if (!ret) + host->use_new_timings = true; + } else if (host->cfg->has_new_timings) { + /* Supports new timing mode only */ + host->use_new_timings = true; + } + mmc->ops = &sunxi_mmc_ops; mmc->max_blk_count = 8192; mmc->max_blk_size = 4096;