]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
rockchip: clk: clk_rk3576: Add support for RK3576 GMAC 25MHz clock output
authorAlexey Charkov <alchark@flipper.net>
Mon, 4 May 2026 13:45:08 +0000 (17:45 +0400)
committerKever <kever@KeverdeMacBook-Pro.local>
Tue, 9 Jun 2026 16:19:05 +0000 (00:19 +0800)
Rockchip RK3576 SoC has two built-in GMACs which connect to external PHYs
via RGMII interface. The RGMII link can be clocked by either the PHY or
the SoC. When the SoC is the master, as is the case on the RK3576 EVB1,
the output clock needs to be configured in the CRU.

Add the respective logic for getting and setting the RGMII reference clock
output for both GMAC0 and GMAC1.

Signed-off-by: Alexey Charkov <alchark@flipper.net>
Reviewed-by: Quentin Schulz <quentin.schulz@cherry.de>
Reviewed-by: Kever Yang <kever.yang@rock-chips.com>
arch/arm/include/asm/arch-rockchip/cru_rk3576.h
drivers/clk/rockchip/clk_rk3576.c

index c51750beff28ae08126e92d4c96bf06fac858e50..fb77fbd7307a9b37501c603f493d8ca22e85ea51 100644 (file)
@@ -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,
index dd8b59356ef812882b95a9bee719dd5bb65546a4..db8ce25852fd32c4b4ea8f82f75959392f3f4cc2 100644 (file)
@@ -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: