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.toms...@theobroma-systems.com> Tested-by: Jakob Unterwurzacher <jakob.unterwurzac...@theobroma-systems.com> Tested-by: Klaus Goger <klaus.go...@theobroma-systems.com> --- 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 | 69 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/drivers/clk/rockchip/clk_rk3399.c b/drivers/clk/rockchip/clk_rk3399.c index f778ddf..9150183 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; + +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), + SPI_CLK_REG_VALUE(1, src_clk_div)); + break; + case SCLK_SPI5: + rk_clrsetreg(&cru->clksel_con[58], SPI_CLK_REG_MASK(5), + SPI_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 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot