diff options
author | Julius Werner <jwerner@chromium.org> | 2015-03-26 19:30:25 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-03-26 20:42:21 -0400 |
commit | 76b17e6e4923e4138ed9a4d480cba148ff239dc9 (patch) | |
tree | df93239b9d52f60f9031e3b66aefd5a5153e454f /drivers/spi | |
parent | 2291793cc4c6b1251e28a4ff0f98041147d57e96 (diff) |
spi/rockchip: Add device tree property to configure Rx Sample Delay
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 <jwerner@chromium.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/spi-rockchip.c | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c index 25003c408c92..f65384b3417f 100644 --- a/drivers/spi/spi-rockchip.c +++ b/drivers/spi/spi-rockchip.c | |||
@@ -179,6 +179,7 @@ struct rockchip_spi { | |||
179 | u8 tmode; | 179 | u8 tmode; |
180 | u8 bpw; | 180 | u8 bpw; |
181 | u8 n_bytes; | 181 | u8 n_bytes; |
182 | u8 rsd_nsecs; | ||
182 | unsigned len; | 183 | unsigned len; |
183 | u32 speed; | 184 | u32 speed; |
184 | 185 | ||
@@ -499,6 +500,7 @@ static void rockchip_spi_config(struct rockchip_spi *rs) | |||
499 | { | 500 | { |
500 | u32 div = 0; | 501 | u32 div = 0; |
501 | u32 dmacr = 0; | 502 | u32 dmacr = 0; |
503 | int rsd = 0; | ||
502 | 504 | ||
503 | u32 cr0 = (CR0_BHT_8BIT << CR0_BHT_OFFSET) | 505 | u32 cr0 = (CR0_BHT_8BIT << CR0_BHT_OFFSET) |
504 | | (CR0_SSD_ONE << CR0_SSD_OFFSET); | 506 | | (CR0_SSD_ONE << CR0_SSD_OFFSET); |
@@ -528,6 +530,20 @@ static void rockchip_spi_config(struct rockchip_spi *rs) | |||
528 | div = max_t(u32, rs->max_freq / rs->speed, 1); | 530 | div = max_t(u32, rs->max_freq / rs->speed, 1); |
529 | div = (div + 1) & 0xfffe; | 531 | div = (div + 1) & 0xfffe; |
530 | 532 | ||
533 | /* Rx sample delay is expressed in parent clock cycles (max 3) */ | ||
534 | rsd = DIV_ROUND_CLOSEST(rs->rsd_nsecs * (rs->max_freq >> 8), | ||
535 | 1000000000 >> 8); | ||
536 | if (!rsd && rs->rsd_nsecs) { | ||
537 | pr_warn_once("rockchip-spi: %u Hz are too slow to express %u ns delay\n", | ||
538 | rs->max_freq, rs->rsd_nsecs); | ||
539 | } else if (rsd > 3) { | ||
540 | rsd = 3; | ||
541 | pr_warn_once("rockchip-spi: %u Hz are too fast to express %u ns delay, clamping at %u ns\n", | ||
542 | rs->max_freq, rs->rsd_nsecs, | ||
543 | rsd * 1000000000U / rs->max_freq); | ||
544 | } | ||
545 | cr0 |= rsd << CR0_RSD_OFFSET; | ||
546 | |||
531 | writel_relaxed(cr0, rs->regs + ROCKCHIP_SPI_CTRLR0); | 547 | writel_relaxed(cr0, rs->regs + ROCKCHIP_SPI_CTRLR0); |
532 | 548 | ||
533 | writel_relaxed(rs->len - 1, rs->regs + ROCKCHIP_SPI_CTRLR1); | 549 | writel_relaxed(rs->len - 1, rs->regs + ROCKCHIP_SPI_CTRLR1); |
@@ -620,6 +636,7 @@ static int rockchip_spi_probe(struct platform_device *pdev) | |||
620 | struct rockchip_spi *rs; | 636 | struct rockchip_spi *rs; |
621 | struct spi_master *master; | 637 | struct spi_master *master; |
622 | struct resource *mem; | 638 | struct resource *mem; |
639 | u32 rsd_nsecs; | ||
623 | 640 | ||
624 | master = spi_alloc_master(&pdev->dev, sizeof(struct rockchip_spi)); | 641 | master = spi_alloc_master(&pdev->dev, sizeof(struct rockchip_spi)); |
625 | if (!master) | 642 | if (!master) |
@@ -671,6 +688,10 @@ static int rockchip_spi_probe(struct platform_device *pdev) | |||
671 | rs->dev = &pdev->dev; | 688 | rs->dev = &pdev->dev; |
672 | rs->max_freq = clk_get_rate(rs->spiclk); | 689 | rs->max_freq = clk_get_rate(rs->spiclk); |
673 | 690 | ||
691 | if (!of_property_read_u32(pdev->dev.of_node, "rx-sample-delay-ns", | ||
692 | &rsd_nsecs)) | ||
693 | rs->rsd_nsecs = rsd_nsecs; | ||
694 | |||
674 | rs->fifo_len = get_fifo_len(rs); | 695 | rs->fifo_len = get_fifo_len(rs); |
675 | if (!rs->fifo_len) { | 696 | if (!rs->fifo_len) { |
676 | dev_err(&pdev->dev, "Failed to get fifo length\n"); | 697 | dev_err(&pdev->dev, "Failed to get fifo length\n"); |