clk: rockchip: rk1808: add mac clk interface

support mac clk set rate and set parent.

Change-Id: I3b4626fd3fcc5ffdf3c58add9c1bc002bb56429a
Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
This commit is contained in:
Elaine Zhang 2019-03-14 09:37:37 +08:00 committed by Jianhong Chen
parent 6078abbb1f
commit b9f5972251
2 changed files with 125 additions and 0 deletions

View File

@ -181,6 +181,19 @@ enum {
EMMC_DIV50_SHIFT = 0,
EMMC_DIV50_MASK = 0xff << EMMC_DIV_SHIFT,
/* CRU_CLKSEL26_CON */
GMAC_PLL_SEL_SHIFT = 14,
GMAC_PLL_SEL_MASK = 3 << GMAC_PLL_SEL_SHIFT,
GMAC_PLL_SEL_CPLL = 0,
GMAC_PLL_SEL_NPLL,
GMAC_PLL_SEL_PPLL,
CLK_GMAC_DIV_SHIFT = 8,
CLK_GMAC_DIV_MASK = 0x1f << CLK_GMAC_DIV_SHIFT,
SFC_PLL_SEL_SHIFT = 7,
SFC_PLL_SEL_MASK = 1 << SFC_PLL_SEL_SHIFT,
SFC_DIV_CON_SHIFT = 0,
SFC_DIV_CON_MASK = 0x7f,
/* CRU_CLK_SEL27_CON */
CLK_BUS_PLL_SEL_GPLL = 0,
CLK_BUS_PLL_SEL_CPLL = 1,
@ -188,6 +201,17 @@ enum {
CLK_BUS_PLL_SEL_MASK = 1 << CLK_BUS_PLL_SEL_SHIFT,
HSCLK_BUS_DIV_CON_SHIFT = 8,
HSCLK_BUS_DIV_CON_MASK = 0x1f << HSCLK_BUS_DIV_CON_SHIFT,
RGMII_CLK_SEL_SHIFT = 2,
RGMII_CLK_SEL_MASK = 3 << RGMII_CLK_SEL_SHIFT,
RGMII_CLK_SEL_125M = 0,
RGMII_CLK_SEL_2M = 2,
RGMIIC_CLK_SEL_25M = 3,
RMII_CLK_SEL_SHIFT = 1,
RMII_CLK_SEL_MASK = 1 << RMII_CLK_SEL_SHIFT,
RMII_EXTCLK_SEL_SHIFT = 0,
RMII_EXTCLK_SEL_MASK = 1 << RMII_EXTCLK_SEL_SHIFT,
RMII_EXTCLK_SEL_INT = 0,
RMII_EXTCLK_SEL_EXT,
/* CRU_CLK_SEL28_CON */
MSCLK_BUS_DIV_CON_SHIFT = 8,

View File

@ -564,6 +564,67 @@ static ulong rk1808_vop_set_clk(struct rk1808_clk_priv *priv,
return rk1808_vop_get_clk(priv, clk_id);
}
static ulong rk1808_mac_set_clk(struct clk *clk, uint hz)
{
struct rk1808_clk_priv *priv = dev_get_priv(clk->dev);
struct rk1808_cru *cru = priv->cru;
u32 con = readl(&cru->clksel_con[26]);
ulong pll_rate;
u8 div;
if ((con >> GMAC_PLL_SEL_SHIFT) & GMAC_PLL_SEL_NPLL)
pll_rate = rockchip_pll_get_rate(&rk1808_pll_clks[NPLL],
priv->cru, NPLL);
else if ((con >> GMAC_PLL_SEL_SHIFT) & GMAC_PLL_SEL_PPLL)
pll_rate = rockchip_pll_get_rate(&rk1808_pll_clks[PPLL],
priv->cru, PPLL);
else
pll_rate = rockchip_pll_get_rate(&rk1808_pll_clks[CPLL],
priv->cru, CPLL);
/*default set 50MHZ for gmac*/
if (!hz)
hz = 50000000;
div = DIV_ROUND_UP(pll_rate, hz) - 1;
assert(div < 32);
rk_clrsetreg(&cru->clksel_con[26], CLK_GMAC_DIV_MASK,
div << CLK_GMAC_DIV_SHIFT);
return DIV_TO_RATE(pll_rate, div);
}
static int rk1808_mac_set_speed_clk(struct clk *clk, ulong clk_id, uint hz)
{
struct rk1808_clk_priv *priv = dev_get_priv(clk->dev);
struct rk1808_cru *cru = priv->cru;
u32 sel;
switch (clk_id) {
case SCLK_GMAC_RGMII_SPEED:
if (hz == 125000000)
sel = 0;
else if (hz == 2500000)
sel = 2;
else
sel = 3;
rk_clrsetreg(&cru->clksel_con[27], RGMII_CLK_SEL_MASK,
sel << RGMII_CLK_SEL_SHIFT);
break;
case SCLK_GMAC_RMII_SPEED:
if (hz == 2500000)
sel = 0;
else
sel = 1;
rk_clrsetreg(&cru->clksel_con[27], RMII_CLK_SEL_MASK,
sel << RMII_CLK_SEL_SHIFT);
break;
default:
return -ENOENT;
}
return 0;
}
#endif
static ulong rk1808_bus_get_clk(struct rk1808_clk_priv *priv, ulong clk_id)
@ -916,6 +977,14 @@ static ulong rk1808_clk_set_rate(struct clk *clk, ulong rate)
case DCLK_VOPLITE:
ret = rk1808_vop_set_clk(priv, clk->id, rate);
break;
case SCLK_GMAC:
case SCLK_GMAC_SRC:
ret = rk1808_mac_set_clk(clk, rate);
break;
case SCLK_GMAC_RMII_SPEED:
case SCLK_GMAC_RGMII_SPEED:
ret = rk1808_mac_set_speed_clk(clk, clk->id, rate);
break;
#endif
case HSCLK_BUS_PRE:
case MSCLK_BUS_PRE:
@ -1062,11 +1131,43 @@ static int rk1808_clk_set_phase(struct clk *clk, int degrees)
return ret;
}
#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
static int rk1808_gmac_set_parent(struct clk *clk, struct clk *parent)
{
struct rk1808_clk_priv *priv = dev_get_priv(clk->dev);
struct rk1808_cru *cru = priv->cru;
if (parent->id == SCLK_GMAC_SRC) {
debug("%s: switching GAMC to SCLK_GMAC_SRC\n", __func__);
rk_clrsetreg(&cru->clksel_con[27], RMII_EXTCLK_SEL_MASK,
RMII_EXTCLK_SEL_INT << RMII_EXTCLK_SEL_SHIFT);
} else {
debug("%s: switching GMAC to external clock\n", __func__);
rk_clrsetreg(&cru->clksel_con[27], RMII_EXTCLK_SEL_MASK,
RMII_EXTCLK_SEL_EXT << RMII_EXTCLK_SEL_SHIFT);
}
return 0;
}
static int rk1808_clk_set_parent(struct clk *clk, struct clk *parent)
{
switch (clk->id) {
case SCLK_GMAC:
return rk1808_gmac_set_parent(clk, parent);
default:
return -ENOENT;
}
}
#endif
static struct clk_ops rk1808_clk_ops = {
.get_rate = rk1808_clk_get_rate,
.set_rate = rk1808_clk_set_rate,
.get_phase = rk1808_clk_get_phase,
.set_phase = rk1808_clk_set_phase,
#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
.set_parent = rk1808_clk_set_parent,
#endif
};
static int rk1808_clk_probe(struct udevice *dev)