lkml.org 
[lkml]   [2022]   [Aug]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[PATCH 6/7] spi: realtek-rtl: add support to configure bus speed
The available datasheets for the RTL8381M and RTL9301 state
that the SPI frequency is 50MHz. Set this maximum spi frequency
unless specified otherwise in the device node.

The SPI device on the RTL83xx and RTL93xx SoCs is also accessed
independently by dedicated SPI-NOR (RTL83xx/RTL93xx) and
SPI-NAND (RTL93xx) hardware, which can perform DMA transfers via
the SPI device.
While these devices can set chip selects, they cannot configure
the SPI frequency for a transfer. The clock divider is therefore
configured once during device probe and not changed for individual
transfers as the SPI frequency is a bus property on this platform.

The clock divider setting can take values 0-7, the actual divider
then is:
clock_divider = 2 * (divider_setting + 1)
allowing for clock dividers with values 2-16. The clock used to
derive the SPI clock on the Realtek SoCs is the Lexra bus clock.
When a clock is provided in the SPI device node, we set a clock
divider corresponding to the maximum spi frequency.

Signed-off-by: Birger Koblitz <mail@birger-koblitz.de>
---
drivers/spi/spi-realtek-rtl.c | 28 +++++++++++++++++++++++++++-
1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi-realtek-rtl.c b/drivers/spi/spi-realtek-rtl.c
index 21c0dc16c8cc..91aa7a0348a2 100644
--- a/drivers/spi/spi-realtek-rtl.c
+++ b/drivers/spi/spi-realtek-rtl.c
@@ -5,15 +5,21 @@
#include <linux/mod_devicetable.h>
#include <linux/spi/spi.h>
#include <linux/property.h>
+#include <linux/of.h>
+#include <linux/clk.h>

struct rtspi {
void __iomem *base;
u32 dev_flags;
u32 cs_all;
+ struct clk *clk;
+ int frequency_div;
};

/* SPI Flash Configuration Register */
#define RTL_SPI_SFCR 0x00
+#define RTL_SPI_SFCR_CLK_DIV_BIT 29
+#define RTL_SPI_SFCR_CLK_DIV_MASK ~(0x7 << RTL_SPI_SFCR_CLK_DIV_BIT)
#define RTL_SPI_SFCR_RBO BIT(28)
#define RTL_SPI_SFCR_WBO BIT(27)

@@ -208,9 +214,14 @@ static void init_hw(struct rtspi *rtspi)
{
u32 value;

- /* Turn on big-endian byte ordering */
+ /* Turn on big-endian byte ordering and set clock divider */
value = readl(REG(RTL_SPI_SFCR));
value |= RTL_SPI_SFCR_RBO | RTL_SPI_SFCR_WBO;
+ if (rtspi->frequency_div >= 0) {
+ value &= RTL_SPI_SFCR_CLK_DIV_MASK;
+ value |= rtspi->frequency_div << RTL_SPI_SFCR_CLK_DIV_BIT;
+ }
+
writel(value, REG(RTL_SPI_SFCR));

/* Disable CS0-CS3, enable CS */
@@ -222,6 +233,7 @@ static int realtek_rtl_spi_probe(struct platform_device *pdev)
{
struct spi_controller *ctrl;
struct rtspi *rtspi;
+ u32 spi_clk;
int err;

ctrl = devm_spi_alloc_master(&pdev->dev, sizeof(*rtspi));
@@ -239,6 +251,20 @@ static int realtek_rtl_spi_probe(struct platform_device *pdev)
return -ENOMEM;
}

+ if (of_property_read_u32(pdev->dev.of_node, "spi-max-frequency",
+ &ctrl->max_speed_hz))
+ ctrl->max_speed_hz = 50000000; /* 50MHz */
+
+ rtspi->frequency_div = -1;
+ rtspi->clk = devm_clk_get(&pdev->dev, NULL);
+ if (!IS_ERR(rtspi->clk)) {
+ spi_clk = clk_get_rate(rtspi->clk);
+ rtspi->frequency_div = DIV_ROUND_UP(spi_clk, ctrl->max_speed_hz);
+ rtspi->frequency_div = (rtspi->frequency_div / 2) - 1;
+ if (rtspi->frequency_div > 0x7)
+ rtspi->frequency_div = 0x7;
+ }
+
init_hw(rtspi);

ctrl->dev.of_node = pdev->dev.of_node;
--
2.25.1
\
 
 \ /
  Last update: 2022-08-01 08:23    [W:0.029 / U:0.568 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site