From patchwork Mon Aug 28 14:29:15 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 9925701 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 D762760329 for ; Mon, 28 Aug 2017 14:40:27 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C565527F4B for ; Mon, 28 Aug 2017 14:40:27 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BA204280CF; Mon, 28 Aug 2017 14:40:27 +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=-2.6 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_LOW autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id E064E27FE4 for ; Mon, 28 Aug 2017 14:40:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=4ihFX2sQ9KM6nVpGDjIjD2HEWBhzPiXR+553xXmAa1I=; b=pFGcMPg4W+ajkEJW7sDSYUWC+i TMok10CtOxWF3jnnYbrTdtreiof0sgZxnM8jHn3qMRrKwuZg5kJna7bIGoVf7VT5+FiGCOYNdoP7X JkiP63L3MY1SZXOntNRGKlOiTCztLJMUtXoC6WvGeH3FDCUm3Q/1+if54mZLCB3K/L8XWu2+0TGrG smle3gnyhn0T0bSyFgFTJ4RSoBS50xkNLGTnVqjuQKmbVA3Y6SV6de8CC+6KDG8iX80xdrc2KAfyc NWespdbipv8HFgcpd5q4cHdAoFrHaq051YnQHxcddTtjA/sPo8viCWtdzM9VyIl/tZfej8Yxq2AEj hbgB9DnQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1dmLDB-0005UD-Ta; Mon, 28 Aug 2017 14:40:21 +0000 Received: from casper.infradead.org ([2001:8b0:10b:1236::1]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1dmLD8-0003nf-AJ for linux-arm-kernel@bombadil.infradead.org; Mon, 28 Aug 2017 14:40:18 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Sender:Reply-To:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=6/p7RNjyKOVhaAY7O3Thr4HF79bMnzRn5Kab+yXzW7I=; b=alFZtlR2lLqVG6tQhmtMM6fJq wHEq0ir9nJmlCHxHsHCUHvWkGNFGoshk9GEG1SxujQ8L0Tm5Uy24M3TWVRJW1ndtm9YWVVNc/cTMk AQcV2MYU/USNP+S6TGGBdGfDHBHkRcxSerZfw7j0txCQjP9uVnUR7ZEfkWVjxq+j9fO75ksXwo+Li MLbjfO9P7cZZMC7xpdCq43bAup5+xSjJsgzJyhXIRLWE6PS9TECr0uxfOhbgJyw3x27MpZENEgD54 vtvm/ZU+SbjyEyzS/xDNLp7frvxxTJv7OHHA5fjgqAMYOcEfgwJ0o+JC/VZ2L7c5Y5DY3BLOKVwm5 rL57FWUpw==; Received: from mail-wm0-x22a.google.com ([2a00:1450:400c:c09::22a]) by casper.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1dmL34-0004Ci-8m for linux-arm-kernel@lists.infradead.org; Mon, 28 Aug 2017 14:29:56 +0000 Received: by mail-wm0-x22a.google.com with SMTP id b14so13477330wme.0 for ; Mon, 28 Aug 2017 07:29:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=6/p7RNjyKOVhaAY7O3Thr4HF79bMnzRn5Kab+yXzW7I=; b=qdBuZoLi06F4BdZ6RpRhkcxDDJgbp7U9cxUIhwpWuMPPj/qz+YBPVXupJZ86MsJCTU uuFP4kxjI7WUWZTvTKhMqB+1RLGbl/p68rsdrXcnppSkaNb0RPpP4BSmFn4Gbn5qCjvo PIabLZNkE1wI7oxZDZ5OFxN9HC+AWVwNbOzTdp3X+T6wDi9bymZtYBR+CeytOwOVsM0F A5C9Uoj3bKRKhTkpQHHt4IR2WJSk/26C3KvVK1v1gZfwLs2CjF3H2rjIDA9Y8mvv1GnY DmS2gvM3qxEldcf2aXAHzKoNgzrnuObcn3FJwUjpmE8PCydjTzrVYqg9KuGDDKEBzlBD ZxRQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=6/p7RNjyKOVhaAY7O3Thr4HF79bMnzRn5Kab+yXzW7I=; b=pYv7OsicKDwfoGF6BGO9MJOF8q3b/7TCWF0bbzlWZmqnixP5f6HS0EOrWPpaIwRTW/ Lo6naYpTlDfFZZ3y3W7Vd7r8pfxr/xe/WmMBNfuZLD6uWAa48rEjsXaBET548R+X+iZP ppELK5X3mT/cb7ZH8EwVzmxzLDI6SdLAsAocsmmsCSmP6FfnGSBW2YBD6xoXI2haLsij 0tHadmBJ5AfaMgWoFDq5N5spEggNfCdo53kANv9TIRQ3LthojSI59LYjNzhzb4/Fc0JP IgSndu277N0w8u/rhKEoCBfTT1aHJCONe84Z97hHT/rkNnJmbjAj4eQ81ViszVKnwrHZ r+YQ== X-Gm-Message-State: AHYfb5gHN+7KRC0lFBiymBfL4bjT3pTGLVKneIIo2dxi1ukCTn5xb+ka HizQs9lUO+1jkA2i X-Received: by 10.28.13.130 with SMTP id 124mr486495wmn.13.1503930572535; Mon, 28 Aug 2017 07:29:32 -0700 (PDT) Received: from localhost.localdomain (uluru.liltaz.com. [163.172.81.188]) by smtp.googlemail.com with ESMTPSA id z39sm604792wrz.61.2017.08.28.07.29.31 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 28 Aug 2017 07:29:31 -0700 (PDT) From: Jerome Brunet To: Ulf Hansson , Kevin Hilman , Carlo Caione Subject: [PATCH v3 13/13] mmc: meson-gx: rework tuning function Date: Mon, 28 Aug 2017 16:29:15 +0200 Message-Id: <20170828142915.27020-14-jbrunet@baylibre.com> X-Mailer: git-send-email 2.9.5 In-Reply-To: <20170828142915.27020-1-jbrunet@baylibre.com> References: <20170828142915.27020-1-jbrunet@baylibre.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170828_152954_387522_F2DB6E7C X-CRM114-Status: GOOD ( 27.23 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-amlogic@lists.infradead.org, linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Jerome Brunet MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Rework tuning function of the rx phase. Now that the phase can be more precisely set using CCF, test more phase setting and find the largest working window. Then the tuning selected is the one at the center of the window. This rework allows to use new modes, such as UHS SDR50 Reviewed-by: Kevin Hilman Signed-off-by: Jerome Brunet --- drivers/mmc/host/meson-gx-mmc.c | 161 +++++++++++++++++++++++++++------------- 1 file changed, 111 insertions(+), 50 deletions(-) diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index efffd36c8d77..987bae98c61f 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -49,6 +49,8 @@ #define CLK_TX_DELAY_MASK GENMASK(19, 16) #define CLK_RX_DELAY_MASK GENMASK(23, 20) #define CLK_DELAY_STEP_PS 200 +#define CLK_PHASE_STEP 30 +#define CLK_PHASE_POINT_NUM (360 / CLK_PHASE_STEP) #define CLK_ALWAYS_ON BIT(24) #define SD_EMMC_DELAY 0x4 @@ -119,12 +121,6 @@ #define MUX_CLK_NUM_PARENTS 2 -struct meson_tuning_params { - unsigned int core_phase; - unsigned int tx_phase; - unsigned int rx_phase; -}; - struct sd_emmc_desc { u32 cmd_cfg; u32 cmd_arg; @@ -155,7 +151,6 @@ struct meson_host { struct sd_emmc_desc *descs; dma_addr_t descs_dma_addr; - struct meson_tuning_params tp; bool vqmmc_enabled; }; @@ -458,13 +453,6 @@ static int meson_mmc_clk_set(struct meson_host *host, struct mmc_ios *ios) return 0; } -static void meson_mmc_set_phase_params(struct meson_host *host) -{ - clk_set_phase(host->mmc_clk, host->tp.core_phase); - clk_set_phase(host->tx_clk, host->tp.tx_phase); - clk_set_phase(host->rx_clk, host->tp.rx_phase); -} - /* * The SD/eMMC IP block has an internal mux and divider used for * generating the MMC clock. Use the clock framework to create and @@ -617,18 +605,122 @@ static int meson_mmc_clk_init(struct meson_host *host) if (WARN_ON(PTR_ERR_OR_ZERO(host->rx_clk))) return PTR_ERR(host->rx_clk); - /* Set the initial phase parameters */ - meson_mmc_set_phase_params(host); - /* init SD_EMMC_CLOCK to sane defaults w/min clock rate */ host->mmc->f_min = clk_round_rate(host->mmc_clk, 400000); ret = clk_set_rate(host->mmc_clk, host->mmc->f_min); if (ret) return ret; + /* + * Set phases : These values are mostly the datasheet recommended ones + * except for the Tx phase. Datasheet recommends 180 but some cards + * fail at initialisation with it. 270 works just fine, it fixes these + * initialisation issues and enable eMMC DDR52 mode. + */ + clk_set_phase(host->mmc_clk, 180); + clk_set_phase(host->tx_clk, 270); + clk_set_phase(host->rx_clk, 0); + return clk_prepare_enable(host->mmc_clk); } +static void meson_mmc_shift_map(unsigned long *map, unsigned long shift) +{ + DECLARE_BITMAP(left, CLK_PHASE_POINT_NUM); + DECLARE_BITMAP(right, CLK_PHASE_POINT_NUM); + + /* + * shift the bitmap right and reintroduce the dropped bits on the left + * of the bitmap + */ + bitmap_shift_right(right, map, shift, CLK_PHASE_POINT_NUM); + bitmap_shift_left(left, map, CLK_PHASE_POINT_NUM - shift, + CLK_PHASE_POINT_NUM); + bitmap_or(map, left, right, CLK_PHASE_POINT_NUM); +} + +static void meson_mmc_find_next_region(unsigned long *map, + unsigned long *start, + unsigned long *stop) +{ + *start = find_next_bit(map, CLK_PHASE_POINT_NUM, *start); + *stop = find_next_zero_bit(map, CLK_PHASE_POINT_NUM, *start); +} + +static int meson_mmc_find_tuning_point(unsigned long *test) +{ + unsigned long shift, stop, offset = 0, start = 0, size = 0; + + /* Get the all good/all bad situation out the way */ + if (bitmap_full(test, CLK_PHASE_POINT_NUM)) + return 0; /* All points are good so point 0 will do */ + else if (bitmap_empty(test, CLK_PHASE_POINT_NUM)) + return -EIO; /* No successful tuning point */ + + /* + * Now we know there is a least one region find. Make sure it does + * not wrap by the shifting the bitmap if necessary + */ + shift = find_first_zero_bit(test, CLK_PHASE_POINT_NUM); + if (shift != 0) + meson_mmc_shift_map(test, shift); + + while (start < CLK_PHASE_POINT_NUM) { + meson_mmc_find_next_region(test, &start, &stop); + + if ((stop - start) > size) { + offset = start; + size = stop - start; + } + + start = stop; + } + + /* Get the center point of the region */ + offset += (size / 2); + + /* Shift the result back */ + offset = (offset + shift) % CLK_PHASE_POINT_NUM; + + return offset; +} + +static int meson_mmc_clk_phase_tuning(struct mmc_host *mmc, u32 opcode, + struct clk *clk) +{ + int point, ret; + DECLARE_BITMAP(test, CLK_PHASE_POINT_NUM); + + dev_dbg(mmc_dev(mmc), "%s phase/delay tunning...\n", + __clk_get_name(clk)); + bitmap_zero(test, CLK_PHASE_POINT_NUM); + + /* Explore tuning points */ + for (point = 0; point < CLK_PHASE_POINT_NUM; point++) { + clk_set_phase(clk, point * CLK_PHASE_STEP); + ret = mmc_send_tuning(mmc, opcode, NULL); + if (!ret) + set_bit(point, test); + } + + /* Find the optimal tuning point and apply it */ + point = meson_mmc_find_tuning_point(test); + if (point < 0) + return point; /* tuning failed */ + + clk_set_phase(clk, point * CLK_PHASE_STEP); + dev_dbg(mmc_dev(mmc), "success with phase: %d\n", + clk_get_phase(clk)); + return 0; +} + +static int meson_mmc_execute_tuning(struct mmc_host *mmc, u32 opcode) +{ + struct meson_host *host = mmc_priv(mmc); + + return meson_mmc_clk_phase_tuning(mmc, opcode, host->rx_clk); +} + static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) { struct meson_host *host = mmc_priv(mmc); @@ -667,6 +759,8 @@ static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) host->vqmmc_enabled = true; } + /* Reset rx phase */ + clk_set_phase(host->rx_clk, 0); break; } @@ -989,29 +1083,6 @@ static irqreturn_t meson_mmc_irq_thread(int irq, void *dev_id) return IRQ_HANDLED; } -static int meson_mmc_execute_tuning(struct mmc_host *mmc, u32 opcode) -{ - struct meson_host *host = mmc_priv(mmc); - struct meson_tuning_params tp_old = host->tp; - int ret = -EINVAL, i, cmd_error; - - dev_info(mmc_dev(mmc), "(re)tuning...\n"); - - for (i = 0; i < 360; i += 90) { - host->tp.rx_phase = i; - /* exclude the active parameter set if retuning */ - if (!memcmp(&tp_old, &host->tp, sizeof(tp_old)) && - mmc->doing_retune) - continue; - meson_mmc_set_phase_params(host); - ret = mmc_send_tuning(mmc, opcode, &cmd_error); - if (!ret) - break; - } - - return ret; -} - /* * NOTE: we only need this until the GPIO/pinctrl driver can handle * interrupts. For now, the MMC core will use this for polling. @@ -1156,16 +1227,6 @@ static int meson_mmc_probe(struct platform_device *pdev) if (ret) goto free_host; - /* - * Set phases : These values are mostly the datasheet recommended ones - * except for the Tx phase. Datasheet recommends 180 but some cards - * fail at initialisation with it. 270 works just fine, it fixes these - * initialisation issues and enable eMMC DDR52 mode. - */ - host->tp.core_phase = 180; - host->tp.tx_phase = 270; - host->tp.rx_phase = 0; - ret = meson_mmc_clk_init(host); if (ret) goto err_core_clk;