diff options
author | Jagan Teki <jagan@edgeble.ai> | 2024-01-17 13:21:46 +0530 |
---|---|---|
committer | Anatolij Gustschin <agust@denx.de> | 2024-04-21 09:07:00 +0200 |
commit | 92edae779f8c94a49d2f3e215b1ca0adf1241d53 (patch) | |
tree | 872f96e8c9bfde71fe482b1c844fa7ce6de6d4c2 | |
parent | 7cebb300ae87e0226b9ad1b75a4f3c9730dad5cf (diff) | |
download | u-boot-92edae779f8c94a49d2f3e215b1ca0adf1241d53.tar.gz u-boot-92edae779f8c94a49d2f3e215b1ca0adf1241d53.tar.bz2 u-boot-92edae779f8c94a49d2f3e215b1ca0adf1241d53.zip |
clk: rockchip: rk3328: Add VOP clk support
VOP get and set clock would needed for VOP drivers.
Add support for it.
Signed-off-by: Jagan Teki <jagan@edgeble.ai>
-rw-r--r-- | arch/arm/include/asm/arch-rockchip/cru_rk3328.h | 34 | ||||
-rw-r--r-- | 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 cfec1d974a..df6076e4dc 100644 --- a/drivers/clk/rockchip/clk_rk3328.c +++ b/drivers/clk/rockchip/clk_rk3328.c @@ -580,6 +580,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); @@ -648,7 +728,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: @@ -663,11 +749,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: |