
Hi Philipp,
On 28 March 2017 at 02:58, 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
drivers/clk/rockchip/clk_rk3399.c | 69 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+)
diff --git a/drivers/clk/rockchip/clk_rk3399.c b/drivers/clk/rockchip/clk_rk3399.c index f778ddf..b7c5a35 100644 --- a/drivers/clk/rockchip/clk_rk3399.c +++ b/drivers/clk/rockchip/clk_rk3399.c @@ -605,6 +605,67 @@ static ulong rk3399_i2c_set_clk(struct rk3399_cru *cru, ulong clk_id, uint hz) return DIV_TO_RATE(GPLL_HZ, src_clk_div); }
+#define SPI_CLK_REG_MASK(bus) \
(CLK_SPI_PLL_DIV_CON_MASK << \
CLK_SPI ##bus## _PLL_DIV_CON_SHIFT | \
CLK_SPI_PLL_SEL_MASK << \
CLK_SPI ##bus## _PLL_SEL_SHIFT)
+#define SPI_CLK_REG_VALUE(bus, clk_div) \
((clk_div - 1) << \
CLK_SPI ##bus## _PLL_DIV_CON_SHIFT | \
CLK_SPI_PLL_SEL_GPLL << \
CLK_SPI ##bus## _PLL_SEL_SHIFT)
+#define SPI_CLK_DIV_VALUE(con, bus) \
(con >> CLK_SPI ##bus## _PLL_DIV_CON_SHIFT) & \
CLK_SPI_PLL_DIV_CON_MASK;
I'm really not keen on this macro pasting as it makes it hard to find things.
Can we instead have something like:
static const u8 spi_shift[] = { CLK_SPI0_PLL_SEL_SHIFT, CLK_SPI1_PLL_SEL_SHIFT, ... };
and then read it from the array? Since there are multiple pieces you might want:
struct spi_reg_layout { u8 sel_shift; u8 div_shift; u8 sel_mask; u8 div_mask; };
static const struct spi_reg_layout spi_reg_layout[] = { { ... }, { ... },
This is how Tegra does things, for example.
+static ulong rk3399_spi_get_clk(struct rk3399_cru *cru, ulong clk_id) +{
u32 div, con;
switch (clk_id) {
case SCLK_SPI1:
con = readl(&cru->clksel_con[59]);
div = SPI_CLK_DIV_VALUE(con, 1);
break;
case SCLK_SPI5:
con = readl(&cru->clksel_con[58]);
div = SPI_CLK_DIV_VALUE(con, 5);
break;
default:
error("%s: SPI clk-id %ld not supported\n", __func__, clk_id);
return -EINVAL;
}
return DIV_TO_RATE(GPLL_HZ, div);
+}
+static ulong rk3399_spi_set_clk(struct rk3399_cru *cru, ulong clk_id, uint hz) +{
int src_clk_div;
src_clk_div = GPLL_HZ / hz;
assert((src_clk_div - 1) < 127);
switch (clk_id) {
case SCLK_SPI1:
rk_clrsetreg(&cru->clksel_con[59], SPI_CLK_REG_MASK(1),
I2C_CLK_REG_VALUE(1, src_clk_div));
break;
case SCLK_SPI5:
rk_clrsetreg(&cru->clksel_con[58], I2C_CLK_REG_MASK(5),
I2C_CLK_REG_VALUE(5, src_clk_div));
break;
default:
error("%s: SPI clk-id %ld not supported\n", __func__, clk_id);
return -EINVAL;
}
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 +841,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 +883,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);
-- 1.9.1
Regards, Simon