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:
parent
6078abbb1f
commit
b9f5972251
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue