From 51a644a1b84272ef49ffc8affe5599ef645a98fe Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Sun, 3 Feb 2019 16:17:32 +0100 Subject: [PATCH] rockchip: spi: add driver-data and a 'rxonly_manages_fifo' flag The SPI controller's documentation (I only had access to the RK3399, RK3368 and PX30 TRMs) specifies that, when operating in master-mode, the controller will stop the SCLK to avoid RXFIFO overruns and TXFIFO underruns. Looks like my worries that we'd need to support DMA-330 (aka PL330) to make any further progress were unfounded. This adds a driver-data structure to capture hardware-specific settings of individual controller instances (after all, we don't know if all versions are well-behaved) and adds a 'master_manages_fifo' flag to it. The first use of said flag is in the optimised receive-only transfer-handler, which can now request 64Kframe (i.e. 128KByte) bursts of data on each reprogramming of CTRLR1 (i.e. every time through the loop). This improves throughput to 46.85MBit/s (a 94.65% bus-utilisation). Signed-off-by: Philipp Tomsich --- drivers/spi/rk_spi.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/spi/rk_spi.c b/drivers/spi/rk_spi.c index fec41a4243..7b39d1c9e7 100644 --- a/drivers/spi/rk_spi.c +++ b/drivers/spi/rk_spi.c @@ -26,6 +26,11 @@ /* Change to 1 to output registers at the start of each transaction */ #define DEBUG_RK_SPI 0 +struct rockchip_spi_params { + /* RXFIFO overruns and TXFIFO underruns stop the master clock */ + bool master_manages_fifo; +}; + struct rockchip_spi_platdata { #if CONFIG_IS_ENABLED(OF_PLATDATA) struct dtd_rockchip_rk3288_spi of_plat; @@ -364,6 +369,15 @@ static inline int rockchip_spi_16bit_reader(struct udevice *dev, return 0; } + /* + * If we know that the hardware will manage RXFIFO overruns + * (i.e. stop the SPI clock until there's space in the FIFO), + * we the allow largest possible chunk size that can be + * represented in CTRLR1. + */ + if (data && data->master_manages_fifo) + max_chunk_size = 0x10000; + // rockchip_spi_configure(dev, mode, size) rkspi_enable_chip(regs, false); clrsetbits_le32(®s->ctrlr0, @@ -524,10 +538,16 @@ static const struct dm_spi_ops rockchip_spi_ops = { */ }; +const struct rockchip_spi_params rk3399_spi_params = { + .master_manages_fifo = true, +}; + static const struct udevice_id rockchip_spi_ids[] = { { .compatible = "rockchip,rk3288-spi" }, - { .compatible = "rockchip,rk3368-spi" }, - { .compatible = "rockchip,rk3399-spi" }, + { .compatible = "rockchip,rk3368-spi", + .data = (ulong)&rk3399_spi_params }, + { .compatible = "rockchip,rk3399-spi", + .data = (ulong)&rk3399_spi_params }, { } }; -- 2.39.5