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

Reply via email to