[PATCH v1 2/7] clk: rockchip: rk3568: add i2s3 clk
Kever Yang
kever.yang at rock-chips.com
Wed Oct 11 02:34:48 CEST 2023
Hi Elaine,
Please add commit message, and remove the change id.
same for other patches.
Thanks,
- Kever
On 2023/10/10 16:51, Elaine Zhang wrote:
> Change-Id: If20fe16260d2b584d4216d1dbabffcb25478fb1d
> Signed-off-by: Elaine Zhang <zhangqing at rock-chips.com>
> ---
> .../include/asm/arch-rockchip/cru_rk3568.h | 36 +++
> drivers/clk/rockchip/clk_rk3568.c | 218 ++++++++++++++++++
> 2 files changed, 254 insertions(+)
>
> diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3568.h b/arch/arm/include/asm/arch-rockchip/cru_rk3568.h
> index 9c7ddd751f72..0306ce57e369 100644
> --- a/arch/arm/include/asm/arch-rockchip/cru_rk3568.h
> +++ b/arch/arm/include/asm/arch-rockchip/cru_rk3568.h
> @@ -211,6 +211,31 @@ enum {
> ACLK_PERIMID_SEL_100M,
> ACLK_PERIMID_SEL_24M,
>
> + /* CRU_CLK_SEL21_CON */
> + I2S3_MCLKOUT_TX_SEL_SHIFT = 15,
> + I2S3_MCLKOUT_TX_SEL_MASK = 1 << I2S3_MCLKOUT_TX_SEL_SHIFT,
> + I2S3_MCLKOUT_TX_SEL_MCLK = 0,
> + I2S3_MCLKOUT_TX_SEL_12M,
> + CLK_I2S3_SEL_SHIFT = 10,
> + CLK_I2S3_SEL_MASK = 0x3 << CLK_I2S3_SEL_SHIFT,
> + CLK_I2S3_SEL_SRC = 0,
> + CLK_I2S3_SEL_FRAC,
> + CLK_I2S3_SEL_CLKIN,
> + CLK_I2S3_SEL_XIN12M,
> + CLK_I2S3_SRC_SEL_SHIFT = 8,
> + CLK_I2S3_SRC_SEL_MASK = 0x3 << CLK_I2S3_SRC_SEL_SHIFT,
> + CLK_I2S3_SRC_SEL_GPLL = 0,
> + CLK_I2S3_SRC_SEL_CPLL,
> + CLK_I2S3_SRC_SEL_NPLL,
> + CLK_I2S3_SRC_DIV_SHIFT = 0,
> + CLK_I2S3_SRC_DIV_MASK = 0x7f << CLK_I2S3_SRC_DIV_SHIFT,
> +
> + /* CRU_CLK_SEL22_CON */
> + CLK_I2S3_FRAC_NUMERATOR_SHIFT = 16,
> + CLK_I2S3_FRAC_NUMERATOR_MASK = 0xffff << 16,
> + CLK_I2S3_FRAC_DENOMINATOR_SHIFT = 0,
> + CLK_I2S3_FRAC_DENOMINATOR_MASK = 0xffff,
> +
> /* CRU_CLK_SEL27_CON */
> CLK_CRYPTO_PKA_SEL_SHIFT = 6,
> CLK_CRYPTO_PKA_SEL_MASK = 3 << CLK_CRYPTO_PKA_SEL_SHIFT,
> @@ -502,5 +527,16 @@ enum {
> /* CRU_CLK_SEL82_CON */
> CPLL_100M_DIV_SHIFT = 0,
> CPLL_100M_DIV_MASK = 0x1f << CPLL_100M_DIV_SHIFT,
> +
> + /* GRF_SOC_CON2 */
> + I2S3_MCLKOUT_SEL_SHIFT = 15,
> + I2S3_MCLKOUT_SEL_MASK = 0x1 << I2S3_MCLKOUT_SEL_SHIFT,
> + I2S3_MCLKOUT_SEL_RX = 0,
> + I2S3_MCLKOUT_SEL_TX,
> + I2S3_MCLK_IOE_SEL_SHIFT = 3,
> + I2S3_MCLK_IOE_SEL_MASK = 0x1 << I2S3_MCLK_IOE_SEL_SHIFT,
> + I2S3_MCLK_IOE_SEL_CLKIN = 0,
> + I2S3_MCLK_IOE_SEL_CLKOUT,
> +
> };
> #endif
> diff --git a/drivers/clk/rockchip/clk_rk3568.c b/drivers/clk/rockchip/clk_rk3568.c
> index 599b7b130eb9..469014439be4 100644
> --- a/drivers/clk/rockchip/clk_rk3568.c
> +++ b/drivers/clk/rockchip/clk_rk3568.c
> @@ -13,6 +13,7 @@
> #include <asm/arch-rockchip/cru_rk3568.h>
> #include <asm/arch-rockchip/clock.h>
> #include <asm/arch-rockchip/hardware.h>
> +#include <asm/arch-rockchip/grf_rk3568.h>
> #include <asm/io.h>
> #include <dm/device-internal.h>
> #include <dm/lists.h>
> @@ -2326,6 +2327,170 @@ static ulong rk3568_uart_set_rate(struct rk3568_clk_priv *priv,
> return rk3568_uart_get_rate(priv, clk_id);
> }
>
> +#ifndef CONFIG_SPL_BUILD
> +static ulong rk3568_i2s3_get_rate(struct rk3568_clk_priv *priv, ulong clk_id)
> +{
> + struct rk3568_cru *cru = priv->cru;
> + struct rk3568_grf *grf = priv->grf;
> + u32 con, div, src, p_rate;
> + u32 reg, fracdiv, p_src;
> + unsigned long m, n;
> +
> + switch (clk_id) {
> + case I2S3_MCLKOUT_TX:
> + con = readl(&cru->clksel_con[21]);
> + src = (con & I2S3_MCLKOUT_TX_SEL_MASK) >>
> + I2S3_MCLKOUT_TX_SEL_SHIFT;
> + if (src == I2S3_MCLKOUT_TX_SEL_12M)
> + p_rate = 12000000;
> + else
> + p_rate = rk3568_i2s3_get_rate(priv, MCLK_I2S3_2CH_TX);
> + return p_rate;
> + case I2S3_MCLKOUT_RX:
> + con = readl(&cru->clksel_con[83]);
> + src = (con & I2S3_MCLKOUT_TX_SEL_MASK) >>
> + I2S3_MCLKOUT_TX_SEL_SHIFT;
> + if (src == I2S3_MCLKOUT_TX_SEL_12M)
> + p_rate = 12000000;
> + else
> + p_rate = rk3568_i2s3_get_rate(priv, MCLK_I2S3_2CH_RX);
> + return p_rate;
> + case I2S3_MCLKOUT:
> + con = readl(&grf->soc_con2);
> + src = (con & I2S3_MCLKOUT_SEL_MASK)
> + >> I2S3_MCLKOUT_SEL_SHIFT;
> + if (src == I2S3_MCLKOUT_SEL_RX)
> + p_rate = rk3568_i2s3_get_rate(priv, I2S3_MCLKOUT_RX);
> + else
> + p_rate = rk3568_i2s3_get_rate(priv, I2S3_MCLKOUT_TX);
> + return p_rate;
> + case MCLK_I2S3_2CH_RX:
> + reg = 83;
> + break;
> + case MCLK_I2S3_2CH_TX:
> + reg = 21;
> + break;
> + default:
> + return -ENOENT;
> + }
> +
> + con = readl(&cru->clksel_con[reg]);
> + src = (con & CLK_I2S3_SEL_MASK) >> CLK_I2S3_SEL_SHIFT;
> + div = (con & CLK_I2S3_SRC_DIV_MASK) >> CLK_I2S3_SRC_DIV_SHIFT;
> + p_src = (con & CLK_I2S3_SRC_SEL_MASK) >> CLK_I2S3_SRC_SEL_SHIFT;
> + if (p_src == CLK_I2S3_SRC_SEL_GPLL)
> + p_rate = priv->gpll_hz;
> + else if (p_src == CLK_I2S3_SRC_SEL_CPLL)
> + p_rate = priv->cpll_hz;
> + else
> + p_rate = priv->npll_hz;
> + if (src == CLK_I2S3_SEL_SRC) {
> + return DIV_TO_RATE(p_rate, div);
> + } else if (src == CLK_I2S3_SEL_FRAC) {
> + fracdiv = readl(&cru->clksel_con[reg + 1]);
> + n = fracdiv & CLK_I2S3_FRAC_NUMERATOR_MASK;
> + n >>= CLK_I2S3_FRAC_NUMERATOR_SHIFT;
> + m = fracdiv & CLK_I2S3_FRAC_DENOMINATOR_MASK;
> + m >>= CLK_I2S3_FRAC_DENOMINATOR_SHIFT;
> + return DIV_TO_RATE(p_rate, div) * n / m;
> + } else {
> + return OSC_HZ / 2;
> + }
> +}
> +
> +static ulong rk3568_i2s3_set_rate(struct rk3568_clk_priv *priv,
> + ulong clk_id, ulong rate)
> +{
> + struct rk3568_cru *cru = priv->cru;
> + struct rk3568_grf *grf = priv->grf;
> + u32 reg, con, clk_src, i2s_src, div;
> + unsigned long m = 0, n = 0, val;
> +
> + if (priv->gpll_hz % rate == 0) {
> + clk_src = CLK_I2S3_SRC_SEL_GPLL;
> + i2s_src = CLK_I2S3_SEL_SRC;
> + div = DIV_ROUND_UP(priv->gpll_hz, rate);
> + } else if (priv->cpll_hz % rate == 0) {
> + clk_src = CLK_I2S3_SRC_SEL_CPLL;
> + i2s_src = CLK_I2S3_SEL_SRC;
> + div = DIV_ROUND_UP(priv->gpll_hz, rate);
> + } else if (rate == OSC_HZ / 2) {
> + clk_src = CLK_I2S3_SRC_SEL_GPLL;
> + i2s_src = CLK_I2S3_SEL_XIN12M;
> + div = 1;
> + } else {
> + clk_src = CLK_I2S3_SRC_SEL_GPLL;
> + i2s_src = CLK_I2S3_SEL_FRAC;
> + div = 1;
> + rational_best_approximation(rate, priv->gpll_hz / div,
> + GENMASK(16 - 1, 0),
> + GENMASK(16 - 1, 0),
> + &m, &n);
> + }
> +
> + switch (clk_id) {
> + case I2S3_MCLKOUT_TX:
> + if (rate == 12000000) {
> + rk_clrsetreg(&cru->clksel_con[21],
> + I2S3_MCLKOUT_TX_SEL_MASK,
> + I2S3_MCLKOUT_TX_SEL_12M <<
> + I2S3_MCLKOUT_TX_SEL_SHIFT);
> + } else {
> + rk3568_i2s3_set_rate(priv, MCLK_I2S3_2CH_TX, rate),
> + rk_clrsetreg(&cru->clksel_con[21],
> + I2S3_MCLKOUT_TX_SEL_MASK,
> + I2S3_MCLKOUT_TX_SEL_MCLK <<
> + I2S3_MCLKOUT_TX_SEL_SHIFT);
> + }
> + return rk3568_i2s3_get_rate(priv, clk_id);
> + case I2S3_MCLKOUT_RX:
> + if (rate == 12000000) {
> + rk_clrsetreg(&cru->clksel_con[83],
> + I2S3_MCLKOUT_TX_SEL_MASK,
> + I2S3_MCLKOUT_TX_SEL_12M <<
> + I2S3_MCLKOUT_TX_SEL_SHIFT);
> + } else {
> + rk3568_i2s3_set_rate(priv, MCLK_I2S3_2CH_RX, rate),
> + rk_clrsetreg(&cru->clksel_con[21],
> + I2S3_MCLKOUT_TX_SEL_MASK,
> + I2S3_MCLKOUT_TX_SEL_MCLK <<
> + I2S3_MCLKOUT_TX_SEL_SHIFT);
> + }
> + return rk3568_i2s3_get_rate(priv, clk_id);
> + case I2S3_MCLKOUT:
> + con = readl(&grf->soc_con2);
> + clk_src = (con & I2S3_MCLKOUT_SEL_MASK)
> + >> I2S3_MCLKOUT_SEL_SHIFT;
> + if (clk_src == I2S3_MCLKOUT_SEL_RX)
> + rk3568_i2s3_set_rate(priv, I2S3_MCLKOUT_RX, rate);
> + else
> + rk3568_i2s3_set_rate(priv, I2S3_MCLKOUT_TX, rate);
> + return rk3568_i2s3_get_rate(priv, clk_id);
> + case MCLK_I2S3_2CH_RX:
> + reg = 83;
> + break;
> + case MCLK_I2S3_2CH_TX:
> + reg = 21;
> + break;
> + default:
> + return -ENOENT;
> + }
> +
> + rk_clrsetreg(&cru->clksel_con[reg],
> + CLK_I2S3_SEL_MASK | CLK_I2S3_SRC_SEL_MASK |
> + CLK_I2S3_SRC_DIV_MASK,
> + (clk_src << CLK_I2S3_SRC_SEL_SHIFT) |
> + (i2s_src << CLK_I2S3_SEL_SHIFT) |
> + ((div - 1) << CLK_I2S3_SRC_DIV_SHIFT));
> + if (m && n) {
> + val = m << CLK_I2S3_FRAC_NUMERATOR_SHIFT | n;
> + writel(val, &cru->clksel_con[reg + 1]);
> + }
> + return rk3568_i2s3_get_rate(priv, clk_id);
> +}
> +
> +#endif
> +
> static ulong rk3568_clk_get_rate(struct clk *clk)
> {
> struct rk3568_clk_priv *priv = dev_get_priv(clk->dev);
> @@ -2463,6 +2628,13 @@ static ulong rk3568_clk_get_rate(struct clk *clk)
> case TCLK_WDT_NS:
> rate = OSC_HZ;
> break;
> + case I2S3_MCLKOUT_RX:
> + case I2S3_MCLKOUT_TX:
> + case MCLK_I2S3_2CH_RX:
> + case MCLK_I2S3_2CH_TX:
> + case I2S3_MCLKOUT:
> + rate = rk3568_i2s3_get_rate(priv, clk->id);
> + break;
> #endif
> case SCLK_UART1:
> case SCLK_UART2:
> @@ -2648,6 +2820,13 @@ static ulong rk3568_clk_set_rate(struct clk *clk, ulong rate)
> case TCLK_WDT_NS:
> ret = OSC_HZ;
> break;
> + case I2S3_MCLKOUT_RX:
> + case I2S3_MCLKOUT_TX:
> + case MCLK_I2S3_2CH_RX:
> + case MCLK_I2S3_2CH_TX:
> + case I2S3_MCLKOUT:
> + ret = rk3568_i2s3_set_rate(priv, clk->id, rate);
> + break;
> #endif
> case SCLK_UART1:
> case SCLK_UART2:
> @@ -2824,6 +3003,42 @@ static int rk3568_rkvdec_set_parent(struct clk *clk, struct clk *parent)
> return 0;
> }
>
> +static int __maybe_unused rk3568_i2s3_set_parent(struct clk *clk,
> + struct clk *parent)
> +{
> + struct rk3568_clk_priv *priv = dev_get_priv(clk->dev);
> + struct rk3568_grf *grf = priv->grf;
> +
> + switch (clk->id) {
> + case I2S3_MCLK_IOE:
> + if (parent->id == I2S3_MCLKOUT) {
> + rk_clrsetreg(&grf->soc_con2, I2S3_MCLK_IOE_SEL_MASK,
> + I2S3_MCLK_IOE_SEL_CLKOUT <<
> + I2S3_MCLK_IOE_SEL_SHIFT);
> + } else {
> + rk_clrsetreg(&grf->soc_con2, I2S3_MCLK_IOE_SEL_MASK,
> + I2S3_MCLK_IOE_SEL_CLKIN <<
> + I2S3_MCLK_IOE_SEL_SHIFT);
> + }
> + break;
> + case I2S3_MCLKOUT:
> + if (parent->id == I2S3_MCLKOUT_RX) {
> + rk_clrsetreg(&grf->soc_con2, I2S3_MCLKOUT_SEL_MASK,
> + I2S3_MCLKOUT_SEL_RX <<
> + I2S3_MCLKOUT_SEL_SHIFT);
> + } else {
> + rk_clrsetreg(&grf->soc_con2, I2S3_MCLKOUT_SEL_MASK,
> + I2S3_MCLKOUT_SEL_TX <<
> + I2S3_MCLKOUT_SEL_SHIFT);
> + }
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> static int rk3568_clk_set_parent(struct clk *clk, struct clk *parent)
> {
> switch (clk->id) {
> @@ -2848,6 +3063,9 @@ static int rk3568_clk_set_parent(struct clk *clk, struct clk *parent)
> case SCLK_GMAC1_RGMII_SPEED:
> case SCLK_GMAC1_RMII_SPEED:
> break;
> + case I2S3_MCLK_IOE:
> + case I2S3_MCLKOUT:
> + return rk3568_i2s3_set_parent(clk, parent);
> default:
> return -ENOENT;
> }
More information about the U-Boot
mailing list