diff mbox

[U-Boot,v3,1/7] rockchip: clk: rk3399: add clock support for SCLK_SPI1 and SCLK_SPI5

Message ID 1492443832-50881-2-git-send-email-philipp.tomsich@theobroma-systems.com
State Superseded
Delegated to: Simon Glass
Headers show

Commit Message

Philipp Tomsich April 17, 2017, 3:43 p.m. UTC
This change adds support for configuring the module clocks for SPI1 and
SPI5 from the 594MHz GPLL.

Note that the driver (rk_spi.c) always sets this to 99MHz, but the
implemented functionality is more general and will also support
different clock configurations.

X-AffectedPlatforms: RK3399-Q7
Signed-off-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
Tested-by: Jakob Unterwurzacher <jakob.unterwurzacher@theobroma-systems.com>
Tested-by: Klaus Goger <klaus.goger@theobroma-systems.com>

Cover-Letter:
rockchip: spi: rk3399: add SPI support for the RK3399

This series adds SPI support for the RK3399 (SPI1 and SPI5). This
consists of the following individual changes:
- clock support for the SPI blocks clocked from GRF (i.e. SPI1, SPI2,
  SPI 4 and SPI5)
- pinctrl for SPI1 and SPI5
- changes the SPI module input clock to 198MHz (instead of 99MHz) for
  the RK3399 to improve the available bitrates at higher frequencies
  (e.g. adding the 39MBit and 28MBit operating points)
- modifies the calculation of the top frequency permissible (as the
  49.5MBit operating point had not been permissible due to a hard
  limit at 48MBit)
END

---

Changes in v3:
- replaced macro-pasting with a lookup table to improve readability
  (as requested by Simon)

Changes in v2:
- fixes a wrong macro usage, which caused the SPI module input clock
  frequency to be significantly higher than intended
- frequencies have now been validated using an oscilloscope (keep in mind
  that all frequencies are derived from a 99MHz module input clock) at the
  following measurement points (assuming the other fix for the usage of
  DIV_RATE from the series):
    *  1 MHz ...  0.99 MHz
    *  5 MHz ...  4.95 MHz
    * 10 MHz ...  9.9  MHz
    * 30 MHz ... 33    MHz
    * 50 MHz ... 49.5  MHz

 drivers/clk/rockchip/clk_rk3399.c | 114 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 108 insertions(+), 6 deletions(-)

Comments

Simon Glass April 18, 2017, 3:59 a.m. UTC | #1
On 17 April 2017 at 09:43, Philipp Tomsich <
philipp.tomsich@theobroma-systems.com> wrote:
> This change adds support for configuring the module clocks for SPI1 and
> SPI5 from the 594MHz GPLL.
>
> Note that the driver (rk_spi.c) always sets this to 99MHz, but the
> implemented functionality is more general and will also support
> different clock configurations.
>
> X-AffectedPlatforms: RK3399-Q7
> Signed-off-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
> Tested-by: Jakob Unterwurzacher <
jakob.unterwurzacher@theobroma-systems.com>
> Tested-by: Klaus Goger <klaus.goger@theobroma-systems.com>
>
> Cover-Letter:

Odd that this came through - is it the capital L?

> rockchip: spi: rk3399: add SPI support for the RK3399
>
> This series adds SPI support for the RK3399 (SPI1 and SPI5). This
> consists of the following individual changes:
> - clock support for the SPI blocks clocked from GRF (i.e. SPI1, SPI2,
> SPI 4 and SPI5)
> - pinctrl for SPI1 and SPI5
> - changes the SPI module input clock to 198MHz (instead of 99MHz) for
> the RK3399 to improve the available bitrates at higher frequencies
> (e.g. adding the 39MBit and 28MBit operating points)
> - modifies the calculation of the top frequency permissible (as the
> 49.5MBit operating point had not been permissible due to a hard
> limit at 48MBit)
> END
>
> ---
>
> Changes in v3:
> - replaced macro-pasting with a lookup table to improve readability
> (as requested by Simon)
>
> Changes in v2:
> - fixes a wrong macro usage, which caused the SPI module input clock
> frequency to be significantly higher than intended
> - frequencies have now been validated using an oscilloscope (keep in mind
> that all frequencies are derived from a 99MHz module input clock) at the
> following measurement points (assuming the other fix for the usage of
> DIV_RATE from the series):
> * 1 MHz ... 0.99 MHz
> * 5 MHz ... 4.95 MHz
> * 10 MHz ... 9.9 MHz
> * 30 MHz ... 33 MHz
> * 50 MHz ... 49.5 MHz
>
> drivers/clk/rockchip/clk_rk3399.c | 114
++++++++++++++++++++++++++++++++++++--
> 1 file changed, 108 insertions(+), 6 deletions(-)

Acked-by: Simon Glass <sjg@chromium.org>
Simon Glass April 20, 2017, 9:05 p.m. UTC | #2
On 17 April 2017 at 21:59, Simon Glass <sjg@chromium.org> wrote:
> On 17 April 2017 at 09:43, Philipp Tomsich
> <philipp.tomsich@theobroma-systems.com> wrote:
>> This change adds support for configuring the module clocks for SPI1 and
>> SPI5 from the 594MHz GPLL.
>>
>> Note that the driver (rk_spi.c) always sets this to 99MHz, but the
>> implemented functionality is more general and will also support
>> different clock configurations.
>>
>> X-AffectedPlatforms: RK3399-Q7
>> Signed-off-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
>> Tested-by: Jakob Unterwurzacher
>> <jakob.unterwurzacher@theobroma-systems.com>
>> Tested-by: Klaus Goger <klaus.goger@theobroma-systems.com>
>>
>> Cover-Letter:
>
> Odd that this came through - is it the capital L?
>
>
>> rockchip: spi: rk3399: add SPI support for the RK3399
>>
>> This series adds SPI support for the RK3399 (SPI1 and SPI5). This
>> consists of the following individual changes:
>> - clock support for the SPI blocks clocked from GRF (i.e. SPI1, SPI2,
>> SPI 4 and SPI5)
>> - pinctrl for SPI1 and SPI5
>> - changes the SPI module input clock to 198MHz (instead of 99MHz) for
>> the RK3399 to improve the available bitrates at higher frequencies
>> (e.g. adding the 39MBit and 28MBit operating points)
>> - modifies the calculation of the top frequency permissible (as the
>> 49.5MBit operating point had not been permissible due to a hard
>> limit at 48MBit)
>> END
>>
>> ---
>>
>> Changes in v3:
>> - replaced macro-pasting with a lookup table to improve readability
>> (as requested by Simon)
>>
>> Changes in v2:
>> - fixes a wrong macro usage, which caused the SPI module input clock
>> frequency to be significantly higher than intended
>> - frequencies have now been validated using an oscilloscope (keep in mind
>> that all frequencies are derived from a 99MHz module input clock) at the
>> following measurement points (assuming the other fix for the usage of
>> DIV_RATE from the series):
>> * 1 MHz ... 0.99 MHz
>> * 5 MHz ... 4.95 MHz
>> * 10 MHz ... 9.9 MHz
>> * 30 MHz ... 33 MHz
>> * 50 MHz ... 49.5 MHz
>>
>> drivers/clk/rockchip/clk_rk3399.c | 114
>> ++++++++++++++++++++++++++++++++++++--
>> 1 file changed, 108 insertions(+), 6 deletions(-)
>
> Acked-by: Simon Glass <sjg@chromium.org>

Applied to u-boot-rockchip/next, thanks!
diff mbox

Patch

diff --git a/drivers/clk/rockchip/clk_rk3399.c b/drivers/clk/rockchip/clk_rk3399.c
index f778ddf..fab36fa 100644
--- a/drivers/clk/rockchip/clk_rk3399.c
+++ b/drivers/clk/rockchip/clk_rk3399.c
@@ -1,5 +1,6 @@ 
 /*
  * (C) Copyright 2015 Google, Inc
+ * (C) 2017 Theobroma Systems Design und Consulting GmbH
  *
  * SPDX-License-Identifier:	GPL-2.0
  */
@@ -207,12 +208,15 @@  enum {
 	DCLK_VOP_DIV_CON_SHIFT          = 0,
 
 	/* CLKSEL_CON58 */
-	CLK_SPI_PLL_SEL_MASK		= 1,
-	CLK_SPI_PLL_SEL_CPLL		= 0,
-	CLK_SPI_PLL_SEL_GPLL		= 1,
-	CLK_SPI_PLL_DIV_CON_MASK	= 0x7f,
-	CLK_SPI5_PLL_DIV_CON_SHIFT	= 8,
-	CLK_SPI5_PLL_SEL_SHIFT		= 15,
+	CLK_SPI_PLL_SEL_WIDTH = 1,
+	CLK_SPI_PLL_SEL_MASK = ((1 < CLK_SPI_PLL_SEL_WIDTH) - 1),
+	CLK_SPI_PLL_SEL_CPLL = 0,
+	CLK_SPI_PLL_SEL_GPLL = 1,
+	CLK_SPI_PLL_DIV_CON_WIDTH = 7,
+	CLK_SPI_PLL_DIV_CON_MASK = ((1 << CLK_SPI_PLL_DIV_CON_WIDTH) - 1),
+
+	CLK_SPI5_PLL_DIV_CON_SHIFT      = 8,
+	CLK_SPI5_PLL_SEL_SHIFT	        = 15,
 
 	/* CLKSEL_CON59 */
 	CLK_SPI1_PLL_SEL_SHIFT		= 15,
@@ -605,6 +609,96 @@  static ulong rk3399_i2c_set_clk(struct rk3399_cru *cru, ulong clk_id, uint hz)
 	return DIV_TO_RATE(GPLL_HZ, src_clk_div);
 }
 
+/*
+ * RK3399 SPI clocks have a common divider-width (7 bits) and a single bit
+ * to select either CPLL or GPLL as the clock-parent. The location within
+ * the enclosing CLKSEL_CON (i.e. div_shift and sel_shift) are variable.
+ */
+
+struct spi_clkreg {
+	uint8_t reg;  /* CLKSEL_CON[reg] register in CRU */
+	uint8_t div_shift;
+	uint8_t sel_shift;
+};
+
+/*
+ * The entries are numbered relative to their offset from SCLK_SPI0.
+ *
+ * Note that SCLK_SPI3 (which is configured via PMUCRU and requires different
+ * logic is not supported).
+ */
+static const struct spi_clkreg spi_clkregs[] = {
+	[0] = { .reg = 59,
+		.div_shift = CLK_SPI0_PLL_DIV_CON_SHIFT,
+		.sel_shift = CLK_SPI0_PLL_SEL_SHIFT, },
+	[1] = { .reg = 59,
+		.div_shift = CLK_SPI1_PLL_DIV_CON_SHIFT,
+		.sel_shift = CLK_SPI1_PLL_SEL_SHIFT, },
+	[2] = { .reg = 60,
+		.div_shift = CLK_SPI2_PLL_DIV_CON_SHIFT,
+		.sel_shift = CLK_SPI2_PLL_SEL_SHIFT, },
+	[3] = { .reg = 60,
+		.div_shift = CLK_SPI4_PLL_DIV_CON_SHIFT,
+		.sel_shift = CLK_SPI4_PLL_SEL_SHIFT, },
+	[4] = { .reg = 58,
+		.div_shift = CLK_SPI5_PLL_DIV_CON_SHIFT,
+		.sel_shift = CLK_SPI5_PLL_SEL_SHIFT, },
+};
+
+static inline u32 extract_bits(u32 val, unsigned width, unsigned shift)
+{
+	return (val >> shift) & ((1 << width) - 1);
+}
+
+static ulong rk3399_spi_get_clk(struct rk3399_cru *cru, ulong clk_id)
+{
+	const struct spi_clkreg *spiclk = NULL;
+	u32 div, val;
+
+	switch (clk_id) {
+	case SCLK_SPI0 ... SCLK_SPI5:
+		spiclk = &spi_clkregs[clk_id - SCLK_SPI0];
+		break;
+
+	default:
+		error("%s: SPI clk-id %ld not supported\n", __func__, clk_id);
+		return -EINVAL;
+	}
+
+	val = readl(&cru->clksel_con[spiclk->reg]);
+	div = extract_bits(val, CLK_SPI_PLL_DIV_CON_WIDTH, spiclk->div_shift);
+
+	return DIV_TO_RATE(GPLL_HZ, div);
+}
+
+static ulong rk3399_spi_set_clk(struct rk3399_cru *cru, ulong clk_id, uint hz)
+{
+	const struct spi_clkreg *spiclk = NULL;
+	int src_clk_div;
+
+	src_clk_div = GPLL_HZ / hz;
+	assert((src_clk_div - 1) < 127);
+
+	switch (clk_id) {
+	case SCLK_SPI1 ... SCLK_SPI5:
+		spiclk = &spi_clkregs[clk_id - SCLK_SPI0];
+		break;
+
+	default:
+		error("%s: SPI clk-id %ld not supported\n", __func__, clk_id);
+		return -EINVAL;
+	}
+
+	rk_clrsetreg(&cru->clksel_con[spiclk->reg],
+		     ((CLK_SPI_PLL_DIV_CON_MASK << spiclk->div_shift) |
+		       (CLK_SPI_PLL_SEL_GPLL << spiclk->sel_shift)),
+		     ((src_clk_div << spiclk->div_shift) |
+		      (CLK_SPI_PLL_SEL_GPLL << spiclk->sel_shift)));
+
+
+	return DIV_TO_RATE(GPLL_HZ, src_clk_div);
+}
+
 static ulong rk3399_vop_set_clk(struct rk3399_cru *cru, ulong clk_id, u32 hz)
 {
 	struct pll_div vpll_config = {0};
@@ -780,6 +874,10 @@  static ulong rk3399_clk_get_rate(struct clk *clk)
 	case SCLK_I2C7:
 		rate = rk3399_i2c_get_clk(priv->cru, clk->id);
 		break;
+	case SCLK_SPI1:
+	case SCLK_SPI5:
+		rate = rk3399_spi_get_clk(priv->cru, clk->id);
+		break;
 	case SCLK_UART0:
 	case SCLK_UART2:
 		return 24000000;
@@ -818,6 +916,10 @@  static ulong rk3399_clk_set_rate(struct clk *clk, ulong rate)
 	case SCLK_I2C7:
 		ret = rk3399_i2c_set_clk(priv->cru, clk->id, rate);
 		break;
+	case SCLK_SPI1:
+	case SCLK_SPI5:
+		ret = rk3399_spi_set_clk(priv->cru, clk->id, rate);
+		break;
 	case DCLK_VOP0:
 	case DCLK_VOP1:
 		ret = rk3399_vop_set_clk(priv->cru, clk->id, rate);