From patchwork Thu Mar 26 23:30:25 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julius Werner X-Patchwork-Id: 455238 Return-Path: X-Original-To: incoming-dt@patchwork.ozlabs.org Delivered-To: patchwork-incoming-dt@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id A437D14015A for ; Fri, 27 Mar 2015 10:31:42 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="verification failed; unprotected key" header.d=chromium.org header.i=@chromium.org header.b=IldBvqa4; dkim-adsp=none (unprotected policy); dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932112AbbCZXax (ORCPT ); Thu, 26 Mar 2015 19:30:53 -0400 Received: from mail-ig0-f172.google.com ([209.85.213.172]:36695 "EHLO mail-ig0-f172.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932178AbbCZXat (ORCPT ); Thu, 26 Mar 2015 19:30:49 -0400 Received: by igbud6 with SMTP id ud6so6411435igb.1 for ; Thu, 26 Mar 2015 16:30:48 -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:in-reply-to:references; bh=16FcHbJiT91pS3djSQ5zRUDFfh3LIShZjDx7BB1tbYA=; b=IldBvqa4/XF2ITVFAM3Mhf+4Zy9KiXBa10M3zDyuqyb1S2+7J5OJfqt9pD7RpnHjpY vc44nJB9Ci4HNZgBXLhPwF022gLmS2g1Ijti0r4vYBw3EShoYtBrK0+Yx0ytxb6V5cts GjF8sIGTfSQ7osZ+AblDKB0nP1J/txcvgba3g= 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:in-reply-to :references; bh=16FcHbJiT91pS3djSQ5zRUDFfh3LIShZjDx7BB1tbYA=; b=griQ09ovMEJgRjJMI6lkM0pAPdY0u7adIVVFfCByIHS6m5flhqdQebez2HNqUushqN LSykC4yWxQ0dtXGRTz4ot7kDae2AKxDCkceyz8T/im6oSX+HhWyeSjEmGPWdID5kWa6D BETzUh5fGIjJD2gCpihlsqHWSEy3pGw0Iij4JV8gjXGQEiG6+KwBuLRFq7nN5dMeNKCB MjZ6hpJIAbsdJo0o31u0m9XYw4aku24ktniHuOhoPGKLsVaWV3PMtLOFYuwhjqDEErrq siCEBGitvRe1YY5ud9KpDlCKYc/k/yEoau+oqfpsHYR1U5QpBrqyEyo4c54pIVWztZtU A4hw== X-Gm-Message-State: ALoCoQnOlQytK/22TBiSCIvz6ld4QFKeo+ULhXgMT/yKAq7J0F6mRvintHl1MQ+geN/LNs8aXbhY X-Received: by 10.50.82.68 with SMTP id g4mr40428985igy.26.1427412648625; Thu, 26 Mar 2015 16:30:48 -0700 (PDT) Received: from jwerner-linux.mtv.corp.google.com ([172.22.64.164]) by mx.google.com with ESMTPSA id l197sm208191iol.1.2015.03.26.16.30.47 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 26 Mar 2015 16:30:47 -0700 (PDT) From: Julius Werner To: Mark Brown Cc: Mark Rutland , Heiko Stuebner , addy ke , Doug Anderson , devicetree@vger.kernel.org, linux-spi@vger.kernel.org, linux-kernel@vger.kernel.org, Julius Werner Subject: [PATCH 2/2] spi/rockchip: Add device tree property to configure Rx Sample Delay Date: Thu, 26 Mar 2015 16:30:25 -0700 Message-Id: <1427412625-12377-2-git-send-email-jwerner@chromium.org> X-Mailer: git-send-email 2.2.0.rc0.207.ga3a616c In-Reply-To: <1427412625-12377-1-git-send-email-jwerner@chromium.org> References: <1427412625-12377-1-git-send-email-jwerner@chromium.org> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org We have found that we can sometimes see read failures on boards with high-capacitance SPI lines. It seems that the controller samples the Rx data line too early, and its register interface has an "Rx Sample Delay" setting to fine-tune against this issue. This patch adds a new optional device tree entry that can configure this delay in terms of nanoseconds. The kernel will calculate the best-fitting amount of parent clock ticks to program the controller with based on that. Signed-off-by: Julius Werner Reviewed-by: Doug Anderson --- .../devicetree/bindings/spi/spi-rockchip.txt | 4 ++++ drivers/spi/spi-rockchip.c | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/Documentation/devicetree/bindings/spi/spi-rockchip.txt b/Documentation/devicetree/bindings/spi/spi-rockchip.txt index 467dec4..0c491bd 100644 --- a/Documentation/devicetree/bindings/spi/spi-rockchip.txt +++ b/Documentation/devicetree/bindings/spi/spi-rockchip.txt @@ -24,6 +24,9 @@ Optional Properties: - dmas: DMA specifiers for tx and rx dma. See the DMA client binding, Documentation/devicetree/bindings/dma/dma.txt - dma-names: DMA request names should include "tx" and "rx" if present. +- rx-sample-delay-ns: nanoseconds to delay after the SCLK edge before sampling + Rx data (may need to be fine tuned for high capacitance lines). + No delay (0) by default. Example: @@ -33,6 +36,7 @@ Example: reg = <0xff110000 0x1000>; dmas = <&pdma1 11>, <&pdma1 12>; dma-names = "tx", "rx"; + rx-sample-delay-ns = <10>; #address-cells = <1>; #size-cells = <0>; interrupts = ; diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c index 5e4e52c..f89cd5d 100644 --- a/drivers/spi/spi-rockchip.c +++ b/drivers/spi/spi-rockchip.c @@ -179,6 +179,7 @@ struct rockchip_spi { u8 tmode; u8 bpw; u8 n_bytes; + u8 rsd_nsecs; unsigned len; u32 speed; @@ -493,6 +494,7 @@ static void rockchip_spi_config(struct rockchip_spi *rs) { u32 div = 0; u32 dmacr = 0; + int rsd = 0; u32 cr0 = (CR0_BHT_8BIT << CR0_BHT_OFFSET) | (CR0_SSD_ONE << CR0_SSD_OFFSET); @@ -522,6 +524,20 @@ static void rockchip_spi_config(struct rockchip_spi *rs) div = DIV_ROUND_UP(rs->max_freq, rs->speed); div = (div + 1) & 0xfffe; + /* Rx sample delay is expressed in parent clock cycles (max 3) */ + rsd = DIV_ROUND_CLOSEST(rs->rsd_nsecs * (rs->max_freq >> 8), + 1000000000 >> 8); + if (!rsd && rs->rsd_nsecs) { + pr_warn_once("rockchip-spi: %u Hz are too slow to express %u ns delay\n", + rs->max_freq, rs->rsd_nsecs); + } else if (rsd > 3) { + rsd = 3; + pr_warn_once("rockchip-spi: %u Hz are too fast to express %u ns delay, clamping at %u ns\n", + rs->max_freq, rs->rsd_nsecs, + rsd * 1000000000U / rs->max_freq); + } + cr0 |= rsd << CR0_RSD_OFFSET; + writel_relaxed(cr0, rs->regs + ROCKCHIP_SPI_CTRLR0); writel_relaxed(rs->len - 1, rs->regs + ROCKCHIP_SPI_CTRLR1); @@ -614,6 +630,7 @@ static int rockchip_spi_probe(struct platform_device *pdev) struct rockchip_spi *rs; struct spi_master *master; struct resource *mem; + u32 rsd_nsecs; master = spi_alloc_master(&pdev->dev, sizeof(struct rockchip_spi)); if (!master) @@ -665,6 +682,10 @@ static int rockchip_spi_probe(struct platform_device *pdev) rs->dev = &pdev->dev; rs->max_freq = clk_get_rate(rs->spiclk); + if (!of_property_read_u32(pdev->dev.of_node, "rx-sample-delay-ns", + &rsd_nsecs)) + rs->rsd_nsecs = rsd_nsecs; + rs->fifo_len = get_fifo_len(rs); if (!rs->fifo_len) { dev_err(&pdev->dev, "Failed to get fifo length\n");