From patchwork Thu May 12 18:31:50 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Douglas Anderson X-Patchwork-Id: 9085581 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.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 803689F1C1 for ; Thu, 12 May 2016 18:32:25 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 601E72025A for ; Thu, 12 May 2016 18:32:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 23EF72024C for ; Thu, 12 May 2016 18:32:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752518AbcELScW (ORCPT ); Thu, 12 May 2016 14:32:22 -0400 Received: from mail-pf0-f171.google.com ([209.85.192.171]:36394 "EHLO mail-pf0-f171.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752386AbcELScV (ORCPT ); Thu, 12 May 2016 14:32:21 -0400 Received: by mail-pf0-f171.google.com with SMTP id c189so34588229pfb.3 for ; Thu, 12 May 2016 11:32:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id; bh=CmY/D76lCrIIXdlMAGFrLTuHmeYoC19fk2kQpFp3Qwo=; b=I8EHuEN+75NX5up+jRhpSbrZxbfIx4nY6hkzDgXQI/QeSsOLIpxre6dYexYi624Oup BScAx4g+/6AMqXALOQP6a5Vqfwt780z8xmw4jfIBO7ajlemOwEJJIb9oKCStFKzYJWO3 sRHVZQSNkfpDQ56qkCd+tLk3rGzekMaZZafo4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=CmY/D76lCrIIXdlMAGFrLTuHmeYoC19fk2kQpFp3Qwo=; b=DdYvhcCWoTtEkY9Lf1SgOf+W1xRG/a/xr7Jokdt3gyNFcgRIF8De9VUTNf/b6yUvRZ 9qCAwoJQCA2EC4079mTMFgaJv0N9mdqDwIvcIlVjC3QqoeiV9gKsgpMgC1M0DVXJ6xaD 8DAiwvlhcwuf26JhwbCWVkHks8a693pFcFpV4F9vbd9AJsmwK5+84kon0YWooH0qLqPK oP7FkP+tgdf4/jEs6uAwFH+0z9iY16jJ+FvsrH/EDR0pw5Y2hhliIjxRUictjXfa81pn wSwMFpc+xTZPvuozlA4xYBMY8jLQSyJuW88pfnt8/Q5GkHjOB5mGnlSDX9dzz22gaVFz kBJw== X-Gm-Message-State: AOPr4FW2pN8Zg9EJTNDcxnkVA3sOoEiIH14r+7+IQfKehi6hgQk6kf7FZ/7AIe8whx8icQ== X-Received: by 10.98.96.194 with SMTP id u185mr16009803pfb.13.1463077940398; Thu, 12 May 2016 11:32:20 -0700 (PDT) Received: from tictac.mtv.corp.google.com ([172.22.65.76]) by smtp.gmail.com with ESMTPSA id dh4sm21506768pad.37.2016.05.12.11.32.19 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 12 May 2016 11:32:19 -0700 (PDT) From: Douglas Anderson To: jh80.chung@samsung.com, Ulf Hansson , Heiko Stuebner , shawn.lin@rock-chips.com Cc: linux-rockchip@lists.infradead.org, briannorris@chromium.org, Douglas Anderson , linux-mmc@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH v3] mmc: dw_mmc: rockchip: Set the drive phase properly Date: Thu, 12 May 2016 11:31:50 -0700 Message-Id: <1463077910-25914-1-git-send-email-dianders@chromium.org> X-Mailer: git-send-email 2.8.0.rc3.226.g39d4020 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org X-Spam-Status: No, score=-8.2 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,T_DKIM_INVALID,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 Historically for Rockchip devices we've relied on the power-on default (or perhaps the firmware setting) to get the correct drive phase for dw_mmc devices. This worked OK for the most part, but: * Relying on the setting just "being right" is a bit fragile. * As soon as there is an instance where the power on default is wrong or where the firmware didn't configure this properly then we'll get a mysterious failure. In commit 7a03fe6f48f3 ("clk: rockchip: reset init state before mmc card initialization") we actually started setting this explicitly in the kernel, but that commit wasn't quite right and also wasn't quite enough. See for some details. Let's explicitly set this phase in dw_mmc. The comments inside this patch try to explain the situation quite throughly, but the high level overview of this is: Before this patch on rk3288 devices tested (after revert of the clock patch described above): * eMMC: 180 degrees * SDMMC/SDIO0/SDIO1: 90 degrees After this patch: * Use 90 degree phase offset usually. * Use 180 degree phase offset for MMC_DDR52, SDR104, HS200. That means we are _changing_ behavior for those devices in this way: * If we have HS200 eMMC or DDR52 eMMC, we'll run ID mode at 90 degrees (vs 180) but otherwise have no change. * For any non-HS200 / non-DDR52 eMMC devices we'll now _always_ run at 90 degrees (vs 180). It seems fairly unlikely that building modern hardware is using an eMMC that isn't using DDR52 or HS200, of course. * For SDR104 cards we'll now run with 180 degree phase offset (vs 90). It's expected that 90 degree phase offset would have worked OK, but this gives us extra margin. I have tested this by inserting my collection of uSD cards (mostly UHS, though a few not) into a veyron_minnie and confirmed that they still seem to enumerate properly. For a subset of them I tried putting a filesystem on them and also tried running mmc_test. Fixes: 7a03fe6f48f3 ("clk: rockchip: reset init state before mmc card initialization") Signed-off-by: Douglas Anderson Reviewed-by: Shawn Lin Tested-by: Heiko Stuebner Tested-by: Enric Balletbo i Serra --- Changes in v3: - Fixed minor typo; point that this really fixes something in desc. - Add Shawn's Reviewed-by Changes in v2: - Now use 90 degrees for some modes; updated comments to say why. drivers/mmc/host/dw_mmc-rockchip.c | 64 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c index 8c20b81cafd8..b9e4fe5a2393 100644 --- a/drivers/mmc/host/dw_mmc-rockchip.c +++ b/drivers/mmc/host/dw_mmc-rockchip.c @@ -66,6 +66,70 @@ static void dw_mci_rk3288_set_ios(struct dw_mci *host, struct mmc_ios *ios) /* Make sure we use phases which we can enumerate with */ if (!IS_ERR(priv->sample_clk)) clk_set_phase(priv->sample_clk, priv->default_sample_phase); + + /* + * Set the drive phase offset based on speed mode to achieve hold times. + * + * NOTE: this is _not_ a value that is dynamically tuned and is also + * _not_ a value that will vary from board to board. It is a value + * that could vary between different SoC models if they had massively + * different output clock delays inside their dw_mmc IP block (delay_o), + * but since it's OK to overshoot a little we don't need to do complex + * calculations and can pick values that will just work for everyone. + * + * When picking values we'll stick with picking 0/90/180/270 since + * those can be made very accurately on all known Rockchip SoCs. + * + * Note that these values match values from the DesignWare Databook + * tables for the most part except for SDR12 and "ID mode". For those + * two modes the databook calculations assume a clock in of 50MHz. As + * seen above, we always use a clock in rate that is exactly the + * card's input clock (times RK3288_CLKGEN_DIV, but that gets divided + * back out before the controller sees it). + * + * From measurement of a single device, it appears that delay_o is + * about .5 ns. Since we try to leave a bit of margin, it's expected + * that numbers here will be fine even with much larger delay_o + * (the 1.4 ns assumed by the DesignWare Databook would result in the + * same results, for instance). + */ + if (!IS_ERR(priv->drv_clk)) { + int phase; + + /* + * In almost all cases a 90 degree phase offset will provide + * sufficient hold times across all valid input clock rates + * assuming delay_o is not absurd for a given SoC. We'll use + * that as a default. + */ + phase = 90; + + switch (ios->timing) { + case MMC_TIMING_MMC_DDR52: + /* + * Since clock in rate with MMC_DDR52 is doubled when + * bus width is 8 we need to double the phase offset + * to get the same timings. + */ + if (ios->bus_width == MMC_BUS_WIDTH_8) + phase = 180; + break; + case MMC_TIMING_UHS_SDR104: + case MMC_TIMING_MMC_HS200: + /* + * In the case of 150 MHz clock (typical max for + * Rockchip SoCs), 90 degree offset will add a delay + * of 1.67 ns. That will meet min hold time of .8 ns + * as long as clock output delay is < .87 ns. On + * SoCs measured this seems to be OK, but it doesn't + * hurt to give margin here, so we use 180. + */ + phase = 180; + break; + } + + clk_set_phase(priv->drv_clk, phase); + } } #define NUM_PHASES 360