[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