diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3576.h b/arch/arm/include/asm/arch-rockchip/cru_rk3576.h index c51750beff2..fb77fbd7307 100644 --- a/arch/arm/include/asm/arch-rockchip/cru_rk3576.h +++ b/arch/arm/include/asm/arch-rockchip/cru_rk3576.h @@ -222,6 +222,20 @@ enum { REF_CLK0_OUT_PLL_DIV_SHIFT = 0, REF_CLK0_OUT_PLL_DIV_MASK = 0xff << REF_CLK0_OUT_PLL_DIV_SHIFT, + /* CRU_CLK_SEL36_CON */ + CLK_REFCLKO25M_GMAC0_DIV_SHIFT = 0, + CLK_REFCLKO25M_GMAC0_DIV_MASK = 0x7f << CLK_REFCLKO25M_GMAC0_DIV_SHIFT, + CLK_REFCLKO25M_GMAC0_SEL_SHIFT = 7, + CLK_REFCLKO25M_GMAC0_SEL_MASK = 1 << CLK_REFCLKO25M_GMAC0_SEL_SHIFT, + CLK_REFCLKO25M_GMAC0_SEL_GPLL = 0, + CLK_REFCLKO25M_GMAC0_SEL_CPLL = 1, + CLK_REFCLKO25M_GMAC1_DIV_SHIFT = 8, + CLK_REFCLKO25M_GMAC1_DIV_MASK = 0x7f << CLK_REFCLKO25M_GMAC1_DIV_SHIFT, + CLK_REFCLKO25M_GMAC1_SEL_SHIFT = 15, + CLK_REFCLKO25M_GMAC1_SEL_MASK = 1 << CLK_REFCLKO25M_GMAC1_SEL_SHIFT, + CLK_REFCLKO25M_GMAC1_SEL_GPLL = 0, + CLK_REFCLKO25M_GMAC1_SEL_CPLL = 1, + /* CRU_CLK_SEL55_CON */ ACLK_BUS_ROOT_SEL_SHIFT = 9, ACLK_BUS_ROOT_SEL_MASK = 1 << ACLK_BUS_ROOT_SEL_SHIFT, diff --git a/drivers/clk/rockchip/clk_rk3576.c b/drivers/clk/rockchip/clk_rk3576.c index dd8b59356ef..db8ce25852f 100644 --- a/drivers/clk/rockchip/clk_rk3576.c +++ b/drivers/clk/rockchip/clk_rk3576.c @@ -1549,6 +1549,24 @@ static ulong rk3576_gmac_get_clk(struct rk3576_clk_priv *priv, ulong clk_id) con = readl(&cru->clksel_con[31]); div = (con & CLK_GMAC1_125M_DIV_MASK) >> CLK_GMAC1_125M_DIV_SHIFT; return DIV_TO_RATE(priv->cpll_hz, div); + case REFCLKO25M_GMAC0_OUT: + con = readl(&cru->clksel_con[36]); + div = (con & CLK_REFCLKO25M_GMAC0_DIV_MASK) >> CLK_REFCLKO25M_GMAC0_DIV_SHIFT; + src = (con & CLK_REFCLKO25M_GMAC0_SEL_MASK) >> CLK_REFCLKO25M_GMAC0_SEL_SHIFT; + if (src == CLK_REFCLKO25M_GMAC0_SEL_CPLL) + p_rate = priv->cpll_hz; + else + p_rate = priv->gpll_hz; + return DIV_TO_RATE(p_rate, div); + case REFCLKO25M_GMAC1_OUT: + con = readl(&cru->clksel_con[36]); + div = (con & CLK_REFCLKO25M_GMAC1_DIV_MASK) >> CLK_REFCLKO25M_GMAC1_DIV_SHIFT; + src = (con & CLK_REFCLKO25M_GMAC1_SEL_MASK) >> CLK_REFCLKO25M_GMAC1_SEL_SHIFT; + if (src == CLK_REFCLKO25M_GMAC1_SEL_CPLL) + p_rate = priv->cpll_hz; + else + p_rate = priv->gpll_hz; + return DIV_TO_RATE(p_rate, div); default: return -ENOENT; } @@ -1608,6 +1626,34 @@ static ulong rk3576_gmac_set_clk(struct rk3576_clk_priv *priv, CLK_GMAC1_125M_DIV_MASK, (div - 1) << CLK_GMAC1_125M_DIV_SHIFT); break; + case REFCLKO25M_GMAC0_OUT: + if (!(priv->gpll_hz % rate)) { + src = CLK_REFCLKO25M_GMAC0_SEL_GPLL; + div = priv->gpll_hz / rate; + } else { + src = CLK_REFCLKO25M_GMAC0_SEL_CPLL; + div = priv->cpll_hz / rate; + } + rk_clrsetreg(&cru->clksel_con[36], + CLK_REFCLKO25M_GMAC0_SEL_MASK | + CLK_REFCLKO25M_GMAC0_DIV_MASK, + src << CLK_REFCLKO25M_GMAC0_SEL_SHIFT | + (div - 1) << CLK_REFCLKO25M_GMAC0_DIV_SHIFT); + break; + case REFCLKO25M_GMAC1_OUT: + if (!(priv->gpll_hz % rate)) { + src = CLK_REFCLKO25M_GMAC1_SEL_GPLL; + div = priv->gpll_hz / rate; + } else { + src = CLK_REFCLKO25M_GMAC1_SEL_CPLL; + div = priv->cpll_hz / rate; + } + rk_clrsetreg(&cru->clksel_con[36], + CLK_REFCLKO25M_GMAC1_SEL_MASK | + CLK_REFCLKO25M_GMAC1_DIV_MASK, + src << CLK_REFCLKO25M_GMAC1_SEL_SHIFT | + (div - 1) << CLK_REFCLKO25M_GMAC1_DIV_SHIFT); + break; default: return -ENOENT; } @@ -2016,6 +2062,8 @@ static ulong rk3576_clk_get_rate(struct clk *clk) case CLK_GMAC1_PTP_REF: case CLK_GMAC0_125M_SRC: case CLK_GMAC1_125M_SRC: + case REFCLKO25M_GMAC0_OUT: + case REFCLKO25M_GMAC1_OUT: rate = rk3576_gmac_get_clk(priv, clk->id); break; case CLK_UART_FRAC_0: @@ -2197,6 +2245,8 @@ static ulong rk3576_clk_set_rate(struct clk *clk, ulong rate) case CLK_GMAC1_PTP_REF: case CLK_GMAC0_125M_SRC: case CLK_GMAC1_125M_SRC: + case REFCLKO25M_GMAC0_OUT: + case REFCLKO25M_GMAC1_OUT: ret = rk3576_gmac_set_clk(priv, clk->id, rate); break; case CLK_UART_FRAC_0: