From: Jagan Teki <ja...@edgeble.ai>

VOP get and set clock would needed for VOP drivers.

Add support for it.

Signed-off-by: Jagan Teki <ja...@edgeble.ai>
---
Changes for v3:
- none
Changes for v2:
- Add DCLK get rate

 .../include/asm/arch-rockchip/cru_rk3328.h    | 34 +++++++
 drivers/clk/rockchip/clk_rk3328.c             | 88 ++++++++++++++++++-
 2 files changed, 120 insertions(+), 2 deletions(-)

diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3328.h 
b/arch/arm/include/asm/arch-rockchip/cru_rk3328.h
index 226744d67d..4ad1d33e05 100644
--- a/arch/arm/include/asm/arch-rockchip/cru_rk3328.h
+++ b/arch/arm/include/asm/arch-rockchip/cru_rk3328.h
@@ -62,6 +62,40 @@ check_member(rk3328_cru, sdmmc_ext_con[1], 0x39c);
 enum apll_frequencies {
        APLL_816_MHZ,
        APLL_600_MHZ,
+
+       /* CRU_CLK_SEL37_CON */
+       ACLK_VIO_PLL_SEL_CPLL           = 0,
+       ACLK_VIO_PLL_SEL_GPLL           = 1,
+       ACLK_VIO_PLL_SEL_HDMIPHY        = 2,
+       ACLK_VIO_PLL_SEL_USB480M        = 3,
+       ACLK_VIO_PLL_SEL_SHIFT          = 6,
+       ACLK_VIO_PLL_SEL_MASK           = 3 << ACLK_VIO_PLL_SEL_SHIFT,
+       ACLK_VIO_DIV_CON_SHIFT          = 0,
+       ACLK_VIO_DIV_CON_MASK           = 0x1f << ACLK_VIO_DIV_CON_SHIFT,
+       HCLK_VIO_DIV_CON_SHIFT          = 8,
+       HCLK_VIO_DIV_CON_MASK           = 0x1f << HCLK_VIO_DIV_CON_SHIFT,
+
+       /* CRU_CLK_SEL39_CON */
+       ACLK_VOP_PLL_SEL_CPLL           = 0,
+       ACLK_VOP_PLL_SEL_GPLL           = 1,
+       ACLK_VOP_PLL_SEL_HDMIPHY        = 2,
+       ACLK_VOP_PLL_SEL_USB480M        = 3,
+       ACLK_VOP_PLL_SEL_SHIFT          = 6,
+       ACLK_VOP_PLL_SEL_MASK           = 3 << ACLK_VOP_PLL_SEL_SHIFT,
+       ACLK_VOP_DIV_CON_SHIFT          = 0,
+       ACLK_VOP_DIV_CON_MASK           = 0x1f << ACLK_VOP_DIV_CON_SHIFT,
+
+       /* CRU_CLK_SEL40_CON */
+       DCLK_LCDC_PLL_SEL_GPLL          = 0,
+       DCLK_LCDC_PLL_SEL_CPLL          = 1,
+       DCLK_LCDC_PLL_SEL_SHIFT         = 0,
+       DCLK_LCDC_PLL_SEL_MASK          = 1 << DCLK_LCDC_PLL_SEL_SHIFT,
+       DCLK_LCDC_SEL_HDMIPHY           = 0,
+       DCLK_LCDC_SEL_PLL               = 1,
+       DCLK_LCDC_SEL_SHIFT             = 1,
+       DCLK_LCDC_SEL_MASK              = 1 << DCLK_LCDC_SEL_SHIFT,
+       DCLK_LCDC_DIV_CON_SHIFT         = 8,
+       DCLK_LCDC_DIV_CON_MASK          = 0xFf << DCLK_LCDC_DIV_CON_SHIFT,
 };
 
 void rk3328_configure_cpu(struct rk3328_cru *cru,
diff --git a/drivers/clk/rockchip/clk_rk3328.c 
b/drivers/clk/rockchip/clk_rk3328.c
index ef97381f0e..ee7edb9d10 100644
--- a/drivers/clk/rockchip/clk_rk3328.c
+++ b/drivers/clk/rockchip/clk_rk3328.c
@@ -581,6 +581,86 @@ static ulong rk3328_spi_set_clk(struct rk3328_cru *cru, 
uint hz)
        return rk3328_spi_get_clk(cru);
 }
 
+#ifndef CONFIG_SPL_BUILD
+static ulong rk3328_vop_get_clk(struct rk3328_clk_priv *priv, ulong clk_id)
+{
+       struct rk3328_cru *cru = priv->cru;
+       u32 div, con, parent;
+
+       switch (clk_id) {
+       case ACLK_VOP_PRE:
+               con = readl(&cru->clksel_con[39]);
+               div = (con & ACLK_VOP_DIV_CON_MASK) >> ACLK_VOP_DIV_CON_SHIFT;
+               parent = GPLL_HZ;
+               break;
+       case ACLK_VIO_PRE:
+               con = readl(&cru->clksel_con[37]);
+               div = (con & ACLK_VIO_DIV_CON_MASK) >> ACLK_VIO_DIV_CON_SHIFT;
+               parent = GPLL_HZ;
+               break;
+       case DCLK_LCDC:
+               con = readl(&cru->clksel_con[40]);
+               div = (con & DCLK_LCDC_DIV_CON_MASK) >> DCLK_LCDC_DIV_CON_SHIFT;
+               parent = GPLL_HZ;
+               break;
+       default:
+               printf("%s: Unsupported vop get clk#%ld\n", __func__, clk_id);
+               return -ENOENT;
+       }
+
+       return DIV_TO_RATE(parent, div);
+}
+
+static ulong rk3328_vop_set_clk(struct rk3328_clk_priv *priv,
+                               ulong clk_id, uint hz)
+{
+       struct rk3328_cru *cru = priv->cru;
+       int src_clk_div;
+       u32 con, parent;
+
+       src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz);
+       assert(src_clk_div - 1 < 31);
+
+       switch (clk_id) {
+       case ACLK_VOP_PRE:
+               rk_clrsetreg(&cru->clksel_con[39],
+                            ACLK_VOP_PLL_SEL_MASK | ACLK_VOP_DIV_CON_MASK,
+                            ACLK_VOP_PLL_SEL_CPLL << ACLK_VOP_PLL_SEL_SHIFT |
+                            (src_clk_div - 1) << ACLK_VOP_DIV_CON_SHIFT);
+               break;
+       case ACLK_VIO_PRE:
+               rk_clrsetreg(&cru->clksel_con[37],
+                            ACLK_VIO_PLL_SEL_MASK | ACLK_VIO_DIV_CON_MASK,
+                            ACLK_VIO_PLL_SEL_CPLL << ACLK_VIO_PLL_SEL_SHIFT |
+                            (src_clk_div - 1) << ACLK_VIO_DIV_CON_SHIFT);
+               break;
+       case DCLK_LCDC:
+               con = readl(&cru->clksel_con[40]);
+               con = (con & DCLK_LCDC_SEL_MASK) >> DCLK_LCDC_SEL_SHIFT;
+               if (con) {
+                       parent = readl(&cru->clksel_con[40]);
+                       parent = (parent & DCLK_LCDC_PLL_SEL_MASK) >>
+                                DCLK_LCDC_PLL_SEL_SHIFT;
+                       if (parent)
+                               src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz);
+                       else
+                               src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz);
+
+                       rk_clrsetreg(&cru->clksel_con[40],
+                                    DCLK_LCDC_DIV_CON_MASK,
+                                    (src_clk_div - 1) <<
+                                    DCLK_LCDC_DIV_CON_SHIFT);
+               }
+               break;
+       default:
+               printf("%s: Unable to set vop clk#%ld\n", __func__, clk_id);
+               return -EINVAL;
+       }
+
+       return rk3328_vop_get_clk(priv, clk_id);
+}
+#endif
+
 static ulong rk3328_clk_get_rate(struct clk *clk)
 {
        struct rk3328_clk_priv *priv = dev_get_priv(clk->dev);
@@ -649,7 +729,13 @@ static ulong rk3328_clk_set_rate(struct clk *clk, ulong 
rate)
        case SCLK_SPI:
                ret = rk3328_spi_set_clk(priv->cru, rate);
                break;
+#ifndef CONFIG_SPL_BUILD
        case DCLK_LCDC:
+       case ACLK_VOP_PRE:
+       case ACLK_VIO_PRE:
+               rate = rk3328_vop_set_clk(priv, clk->id, rate);
+               break;
+#endif
        case SCLK_PDM:
        case SCLK_RTC32K:
        case SCLK_UART0:
@@ -664,11 +750,9 @@ static ulong rk3328_clk_set_rate(struct clk *clk, ulong 
rate)
        case ACLK_PERI_PRE:
        case HCLK_PERI:
        case PCLK_PERI:
-       case ACLK_VIO_PRE:
        case HCLK_VIO_PRE:
        case ACLK_RGA_PRE:
        case SCLK_RGA:
-       case ACLK_VOP_PRE:
        case ACLK_RKVDEC_PRE:
        case ACLK_RKVENC:
        case ACLK_VPU_PRE:
-- 
2.25.1

Reply via email to