clk: rockchip: rv1126: Add support for gmac

Change-Id: I10ade6acbbfe5dd23e33a250ef601948606bc57e
Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
This commit is contained in:
Finley Xiao 2020-04-23 17:20:19 +08:00 committed by Jianhong Chen
parent b0c9708366
commit 2438a166f4
2 changed files with 175 additions and 0 deletions

View File

@ -337,11 +337,43 @@ enum {
CLK_NANDC_DIV_SHIFT = 0,
CLK_NANDC_DIV_MASK = 0xff,
/* CRU_CLK_SEL61_CON */
CLK_GMAC_OUT_SEL_SHIFT = 15,
CLK_GMAC_OUT_SEL_MASK = 0x1 << CLK_GMAC_OUT_SEL_SHIFT,
CLK_GMAC_OUT_SEL_CPLL = 0,
CLK_GMAC_OUT_SEL_GPLL,
CLK_GMAC_OUT_DIV_SHIFT = 8,
CLK_GMAC_OUT_DIV_MASK = 0x1f << CLK_GMAC_OUT_DIV_SHIFT,
/* CRU_CLK_SEL63_CON */
PCLK_GMAC_DIV_SHIFT = 8,
PCLK_GMAC_DIV_MASK = 0x1f << PCLK_GMAC_DIV_SHIFT,
CLK_GMAC_SRC_SEL_SHIFT = 7,
CLK_GMAC_SRC_SEL_MASK = 0x1 << CLK_GMAC_SRC_SEL_SHIFT,
CLK_GMAC_SRC_SEL_CPLL = 0,
CLK_GMAC_SRC_SEL_GPLL,
CLK_GMAC_SRC_DIV_SHIFT = 0,
CLK_GMAC_SRC_DIV_MASK = 0x1f << CLK_GMAC_SRC_DIV_SHIFT,
/* CRU_GMAC_CON */
GMAC_SRC_M1_SEL_SHIFT = 5,
GMAC_SRC_M1_SEL_MASK = 0x1 << GMAC_SRC_M1_SEL_SHIFT,
GMAC_SRC_M1_SEL_INT = 0,
GMAC_SRC_M1_SEL_EXT,
GMAC_MODE_SEL_SHIFT = 4,
GMAC_MODE_SEL_MASK = 0x1 << GMAC_MODE_SEL_SHIFT,
GMAC_RGMII_MODE = 0,
GMAC_RMII_MODE,
RGMII_CLK_SEL_SHIFT = 2,
RGMII_CLK_SEL_MASK = 0x3 << RGMII_CLK_SEL_SHIFT,
RGMII_CLK_DIV0 = 0,
RGMII_CLK_DIV1,
RGMII_CLK_DIV50,
RGMII_CLK_DIV5,
RMII_CLK_SEL_SHIFT = 1,
RMII_CLK_SEL_MASK = 0x1 << RMII_CLK_SEL_SHIFT,
RMII_CLK_DIV20 = 0,
RMII_CLK_DIV2,
GMAC_SRC_M0_SEL_SHIFT = 0,
GMAC_SRC_M0_SEL_MASK = 0x1,
GMAC_SRC_M0_SEL_INT = 0,

View File

@ -1288,6 +1288,114 @@ static ulong rv1126_scr1_set_clk(struct rv1126_clk_priv *priv, ulong rate)
return rv1126_scr1_get_clk(priv);
}
static ulong rv1126_gmac_src_get_clk(struct rv1126_clk_priv *priv)
{
struct rv1126_cru *cru = priv->cru;
u32 div, sel, con, parent;
con = readl(&cru->clksel_con[63]);
div = (con & CLK_GMAC_SRC_DIV_MASK) >> CLK_GMAC_SRC_DIV_SHIFT;
sel = (con & CLK_GMAC_SRC_SEL_MASK) >> CLK_GMAC_SRC_SEL_SHIFT;
if (sel == CLK_GMAC_SRC_SEL_CPLL)
parent = priv->cpll_hz;
else if (sel == CLK_GMAC_SRC_SEL_GPLL)
parent = priv->gpll_hz;
else
return -ENOENT;
return DIV_TO_RATE(parent, div);
}
static ulong rv1126_gmac_src_set_clk(struct rv1126_clk_priv *priv, ulong rate)
{
struct rv1126_cru *cru = priv->cru;
int src_clk_div;
src_clk_div = DIV_ROUND_UP(priv->cpll_hz, rate);
assert(src_clk_div - 1 <= 31);
rk_clrsetreg(&cru->clksel_con[63],
CLK_GMAC_SRC_SEL_MASK | CLK_GMAC_SRC_DIV_MASK,
CLK_GMAC_SRC_SEL_CPLL << CLK_GMAC_SRC_SEL_SHIFT |
(src_clk_div - 1) << CLK_GMAC_SRC_DIV_SHIFT);
return rv1126_gmac_src_get_clk(priv);
}
static ulong rv1126_gmac_out_get_clk(struct rv1126_clk_priv *priv)
{
struct rv1126_cru *cru = priv->cru;
u32 div, sel, con, parent;
con = readl(&cru->clksel_con[61]);
div = (con & CLK_GMAC_OUT_DIV_MASK) >> CLK_GMAC_OUT_DIV_SHIFT;
sel = (con & CLK_GMAC_OUT_SEL_MASK) >> CLK_GMAC_OUT_SEL_SHIFT;
if (sel == CLK_GMAC_OUT_SEL_CPLL)
parent = priv->cpll_hz;
else if (sel == CLK_GMAC_OUT_SEL_GPLL)
parent = priv->gpll_hz;
else
return -ENOENT;
return DIV_TO_RATE(parent, div);
}
static ulong rv1126_gmac_out_set_clk(struct rv1126_clk_priv *priv, ulong rate)
{
struct rv1126_cru *cru = priv->cru;
int src_clk_div;
src_clk_div = DIV_ROUND_UP(priv->cpll_hz, rate);
assert(src_clk_div - 1 <= 31);
rk_clrsetreg(&cru->clksel_con[61],
CLK_GMAC_OUT_SEL_MASK | CLK_GMAC_OUT_DIV_MASK,
CLK_GMAC_OUT_SEL_CPLL << CLK_GMAC_OUT_SEL_SHIFT |
(src_clk_div - 1) << CLK_GMAC_OUT_DIV_SHIFT);
return rv1126_gmac_out_get_clk(priv);
}
static ulong rv1126_gmac_tx_rx_set_clk(struct rv1126_clk_priv *priv, ulong rate)
{
struct rv1126_cru *cru = priv->cru;
u32 con, sel, div_sel;
con = readl(&cru->gmac_con);
sel = (con & GMAC_MODE_SEL_MASK) >> GMAC_MODE_SEL_SHIFT;
if (sel == GMAC_RGMII_MODE) {
if (rate == 2500000)
div_sel = RGMII_CLK_DIV50;
else if (rate == 25000000)
div_sel = RGMII_CLK_DIV5;
else
div_sel = RGMII_CLK_DIV0;
rk_clrsetreg(&cru->gmac_con, RGMII_CLK_SEL_MASK,
div_sel << RGMII_CLK_SEL_SHIFT);
} else if (sel == GMAC_RMII_MODE) {
if (rate == 2500000)
div_sel = RMII_CLK_DIV20;
else
div_sel = RMII_CLK_DIV2;
rk_clrsetreg(&cru->gmac_con, RMII_CLK_SEL_MASK,
div_sel << RMII_CLK_SEL_SHIFT);
}
return 0;
}
static ulong rv1126_pclk_gmac_get_clk(struct rv1126_clk_priv *priv)
{
struct rv1126_cru *cru = priv->cru;
u32 div, con, parent;
parent = rv1126_pdphp_get_clk(priv, ACLK_PDPHP);
con = readl(&cru->clksel_con[63]);
div = (con & PCLK_GMAC_DIV_MASK) >> PCLK_GMAC_DIV_SHIFT;
return DIV_TO_RATE(parent, div);
}
static ulong rv1126_clk_get_rate(struct clk *clk)
{
struct rv1126_clk_priv *priv = dev_get_priv(clk->dev);
@ -1372,6 +1480,15 @@ static ulong rv1126_clk_get_rate(struct clk *clk)
case CLK_SCR1_CORE:
rate = rv1126_scr1_get_clk(priv);
break;
case CLK_GMAC_SRC:
rate = rv1126_gmac_src_get_clk(priv);
break;
case CLK_GMAC_ETHERNET_OUT:
rate = rv1126_gmac_out_get_clk(priv);
break;
case PCLK_GMAC:
rate = rv1126_pclk_gmac_get_clk(priv);
break;
default:
return -ENOENT;
}
@ -1463,6 +1580,15 @@ static ulong rv1126_clk_set_rate(struct clk *clk, ulong rate)
case CLK_SCR1_CORE:
ret = rv1126_scr1_set_clk(priv, rate);
break;
case CLK_GMAC_SRC:
ret = rv1126_gmac_src_set_clk(priv, rate);
break;
case CLK_GMAC_ETHERNET_OUT:
ret = rv1126_gmac_out_set_clk(priv, rate);
break;
case CLK_GMAC_TX_RX:
ret = rv1126_gmac_tx_rx_set_clk(priv, rate);
break;
default:
return -ENOENT;
}
@ -1643,6 +1769,21 @@ static int rv1126_gmac_src_m1_set_parent(struct clk *clk, struct clk *parent)
return 0;
}
static int rv1126_gmac_tx_rx_set_parent(struct clk *clk, struct clk *parent)
{
struct rv1126_clk_priv *priv = dev_get_priv(clk->dev);
struct rv1126_cru *cru = priv->cru;
if (parent->id == RGMII_MODE_CLK)
rk_clrsetreg(&cru->gmac_con, GMAC_MODE_SEL_MASK,
GMAC_RGMII_MODE << GMAC_MODE_SEL_SHIFT);
else
rk_clrsetreg(&cru->gmac_con, GMAC_MODE_SEL_MASK,
GMAC_RMII_MODE << GMAC_MODE_SEL_SHIFT);
return 0;
}
static int rv1126_clk_set_parent(struct clk *clk, struct clk *parent)
{
switch (clk->id) {
@ -1652,6 +1793,8 @@ static int rv1126_clk_set_parent(struct clk *clk, struct clk *parent)
return rv1126_gmac_src_m0_set_parent(clk, parent);
case CLK_GMAC_SRC_M1:
return rv1126_gmac_src_m1_set_parent(clk, parent);
case CLK_GMAC_TX_RX:
return rv1126_gmac_tx_rx_set_parent(clk, parent);
default:
return -ENOENT;
}