From patchwork Mon Aug 21 16:03:01 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 9913283 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 5F34F600C8 for ; Mon, 21 Aug 2017 16:18:52 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 509A11FEBA for ; Mon, 21 Aug 2017 16:18:52 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4536A27CEA; Mon, 21 Aug 2017 16:18:52 +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 B29191FEBA for ; Mon, 21 Aug 2017 16:18:51 +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=UaZLcT4cyRiBsbZjI6SX2ZplzNgUO+4B5csh8UHmmeo=; b=jRu2s5KAfQpsJBqfojabaiKRj8 dw8pJHY9bm9AteFzAy+lNS7j9QO02qr9IIIMi8vIP5uT46tCDEsTAHPI4eV2Jo1+T4z2dq0VusK8i vM8EDIjjkQ7cNq/TRgGfv4xVGT+Pp6SNxalxk24rp8bc0e0jZYojT3G4vWcNxBYcyoYkzMLIBn69N 9SLfPtfrXoZXLgP5A+CqvvNis5adJ/e7bpdWTGfLPQUoeCGzl7Xmbdv12c5LCYXNHwIig0FMLg7bR ahe9HybCBQl51Ll9mqRJDBSgVg5YVaQTN/eFMPVkW2LqEmeUNcSBUFMdCU2C9rh9snk4nlf1rWwZK tG9cY2CQ==; 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 1djpPb-0006ZJ-SP; Mon, 21 Aug 2017 16:18:47 +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 1djpNu-0005G8-0Q for linux-arm-kernel@bombadil.infradead.org; Mon, 21 Aug 2017 16:17:02 +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=FWSza7nhxFmVrAqzMRATkKe+54E1gYR3WI8OGLT7VxQ=; b=OZXTI/2udB6Jiduxp7wUNfgAL YdWF/RjqYT5gOBrhuZgFsj51qG0WSjgK7XHQlg4HR1TJ9R2OncAbzO6VUoSMaUvBgzWrxjZpih7vu erPK9XfMdy29VBp0mKckBDLAtdeqsytqmOSUMAoAIumUh5modsGsDuZARiQKqIxBk3AVrayneZ7lu FtStssKdqjVVJLBS8ydiDbFHLGRLvOoGcY98V6QethQk28QAbT+/7Ij6O5oy1COV2h+nOR2jxXUt3 pIRXlayHm5uUS0qd9MJ2jmhGiCTM6Hi6PI/c7qKBxTr0eeadgXdJLv1wZQ12RusP8XiEceBc+RyOf y+pt0D9/w==; Received: from mail-wr0-x22f.google.com ([2a00:1450:400c:c0c::22f]) by casper.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1djpB2-0003Hv-3e for linux-arm-kernel@lists.infradead.org; Mon, 21 Aug 2017 16:03:46 +0000 Received: by mail-wr0-x22f.google.com with SMTP id k46so28393619wre.2 for ; Mon, 21 Aug 2017 09:03:24 -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=FWSza7nhxFmVrAqzMRATkKe+54E1gYR3WI8OGLT7VxQ=; b=PMnzi2MqCiK+E8STsUOZeHRCziCVyZHgSCbVEiAVpeYGTo/c+F+kZkx6JJTtrCHtQt FaQoHLX28wL6/wQ+hXss7Izk98UUFIGFc0dC1rDd0K5L7BAw2VEFWctp/N0d/x164BrO +ZBYMTiJRxlgBDtAY7aSrRgCYL/fhypOzsVcjyPhML52W2WJZcLX3af3TlapmKM+2GEk laFZDH1jgC1/PwuBGsh0/eL8fk6TLzrVTQXqdKYWQFqiH+qFh9cJBGdD63CNwka/X75E hcftaRPYB44Ir8GdTbEBM4g2S2bRHS0ZrZqecICW1gBAI7C73MtiY9l7fifKAKO6rV7V dblg== 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=FWSza7nhxFmVrAqzMRATkKe+54E1gYR3WI8OGLT7VxQ=; b=BfWPVfgku0QoTkXYW+eUNoYKwA7SRBUOh2vCVfUHlMvMXQkIWzggaOFQdjDNm8hEmX yply80zXOOQ2rNp/mi8EDaMiLLtE1uq/ZsO1IcUjEp/f/3J6+j3p6Xzi2TebXYMrTYkR yEyhax4G1W9LbIjT/nJYPhmCwYopFeRkpY4AUVoxaeuK0jF1cWi93PunBkAqIlYZd7VK z3sEzqdANZ4p3mYBj7ixCeg9OUpM5//+zCXSblWBK9V9EdX5CFrGrpE0a76/tdGVMiXs ETv6qwk8x81PeRPx+MLjfySvPStY2zm5TRBrXhkofDOHQKc7Ehqk138XJ10SRk/xEAEh i4OQ== X-Gm-Message-State: AHYfb5i7Kx1alWMihVKOZVVEHq5fPVzed8oPJkGMpHzzxDU8FRYFRei8 rGWQbCWpHJql7mtY X-Received: by 10.28.193.203 with SMTP id r194mr6401039wmf.85.1503331402733; Mon, 21 Aug 2017 09:03:22 -0700 (PDT) Received: from localhost.localdomain ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id 63sm8120063wra.30.2017.08.21.09.03.21 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 21 Aug 2017 09:03:22 -0700 (PDT) From: Jerome Brunet To: Ulf Hansson , Kevin Hilman , Carlo Caione Subject: [PATCH v2 16/16] mmc: meson-gx: rework tuning function Date: Mon, 21 Aug 2017 18:03:01 +0200 Message-Id: <20170821160301.21899-17-jbrunet@baylibre.com> X-Mailer: git-send-email 2.9.5 In-Reply-To: <20170821160301.21899-1-jbrunet@baylibre.com> References: <20170821160301.21899-1-jbrunet@baylibre.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170821_170344_325134_67430B2A X-CRM114-Status: GOOD ( 27.38 ) 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 290631d46a4b..137b93227629 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; } @@ -990,29 +1084,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. @@ -1158,16 +1229,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;