clk: rockchip: rk3399: Improve support for SCLK_PCIEPHY_REF clock

rk3399-nanopi-4.dtsi try to set parent of and set rate to 100 MHz of the
SCLK_PCIEPHY_REF clock.

The existing enable/disable ops for SCLK_PCIEPHY_REF currently force
use of 24 MHz parent and rate.

Add improved support for setting parent and rate of the pciephy refclk
to driver to better support assign-clock props for pciephy refclk in DT.

This limited implementation only support setting 24 or 100 MHz rate,
and expect npll and clk_pciephy_ref100m divider to use default values.

Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Reviewed-by: Kever Yang <kever.yang@rock-chips.com>
This commit is contained in:
Jonas Karlman 2024-05-01 16:22:20 +00:00 committed by Kever Yang
parent 24463b1583
commit e801d05bea

View File

@ -926,6 +926,26 @@ static ulong rk3399_saradc_set_clk(struct rockchip_cru *cru, uint hz)
return rk3399_saradc_get_clk(cru); return rk3399_saradc_get_clk(cru);
} }
static ulong rk3399_pciephy_get_clk(struct rockchip_cru *cru)
{
if (readl(&cru->clksel_con[18]) & BIT(10))
return 100 * MHz;
else
return OSC_HZ;
}
static ulong rk3399_pciephy_set_clk(struct rockchip_cru *cru, uint hz)
{
if (hz == 100 * MHz)
rk_setreg(&cru->clksel_con[18], BIT(10));
else if (hz == OSC_HZ)
rk_clrreg(&cru->clksel_con[18], BIT(10));
else
return -EINVAL;
return rk3399_pciephy_get_clk(cru);
}
static ulong rk3399_clk_get_rate(struct clk *clk) static ulong rk3399_clk_get_rate(struct clk *clk)
{ {
struct rk3399_clk_priv *priv = dev_get_priv(clk->dev); struct rk3399_clk_priv *priv = dev_get_priv(clk->dev);
@ -967,6 +987,9 @@ static ulong rk3399_clk_get_rate(struct clk *clk)
case SCLK_SARADC: case SCLK_SARADC:
rate = rk3399_saradc_get_clk(priv->cru); rate = rk3399_saradc_get_clk(priv->cru);
break; break;
case SCLK_PCIEPHY_REF:
rate = rk3399_pciephy_get_clk(priv->cru);
break;
case ACLK_VIO: case ACLK_VIO:
case ACLK_HDCP: case ACLK_HDCP:
case ACLK_GIC_PRE: case ACLK_GIC_PRE:
@ -1058,6 +1081,9 @@ static ulong rk3399_clk_set_rate(struct clk *clk, ulong rate)
case SCLK_SARADC: case SCLK_SARADC:
ret = rk3399_saradc_set_clk(priv->cru, rate); ret = rk3399_saradc_set_clk(priv->cru, rate);
break; break;
case SCLK_PCIEPHY_REF:
ret = rk3399_pciephy_set_clk(priv->cru, rate);
break;
case ACLK_VIO: case ACLK_VIO:
case ACLK_HDCP: case ACLK_HDCP:
case ACLK_GIC_PRE: case ACLK_GIC_PRE:
@ -1108,12 +1134,39 @@ static int __maybe_unused rk3399_gmac_set_parent(struct clk *clk,
return -EINVAL; return -EINVAL;
} }
static int __maybe_unused rk3399_pciephy_set_parent(struct clk *clk,
struct clk *parent)
{
struct rk3399_clk_priv *priv = dev_get_priv(clk->dev);
const char *clock_output_name;
int ret;
if (parent->dev == clk->dev && parent->id == SCLK_PCIEPHY_REF100M) {
rk_setreg(&priv->cru->clksel_con[18], BIT(10));
return 0;
}
ret = dev_read_string_index(parent->dev, "clock-output-names",
parent->id, &clock_output_name);
if (ret < 0)
return -ENODATA;
if (!strcmp(clock_output_name, "xin24m")) {
rk_clrreg(&priv->cru->clksel_con[18], BIT(10));
return 0;
}
return -EINVAL;
}
static int __maybe_unused rk3399_clk_set_parent(struct clk *clk, static int __maybe_unused rk3399_clk_set_parent(struct clk *clk,
struct clk *parent) struct clk *parent)
{ {
switch (clk->id) { switch (clk->id) {
case SCLK_RMII_SRC: case SCLK_RMII_SRC:
return rk3399_gmac_set_parent(clk, parent); return rk3399_gmac_set_parent(clk, parent);
case SCLK_PCIEPHY_REF:
return rk3399_pciephy_set_parent(clk, parent);
} }
debug("%s: unsupported clk %ld\n", __func__, clk->id); debug("%s: unsupported clk %ld\n", __func__, clk->id);
@ -1204,7 +1257,8 @@ static int rk3399_clk_enable(struct clk *clk)
rk_clrreg(&priv->cru->clkgate_con[13], BIT(7)); rk_clrreg(&priv->cru->clkgate_con[13], BIT(7));
break; break;
case SCLK_PCIEPHY_REF: case SCLK_PCIEPHY_REF:
rk_clrreg(&priv->cru->clksel_con[18], BIT(10)); if (readl(&priv->cru->clksel_con[18]) & BIT(10))
rk_clrreg(&priv->cru->clkgate_con[12], BIT(6));
break; break;
default: default:
debug("%s: unsupported clk %ld\n", __func__, clk->id); debug("%s: unsupported clk %ld\n", __func__, clk->id);
@ -1298,7 +1352,8 @@ static int rk3399_clk_disable(struct clk *clk)
rk_setreg(&priv->cru->clkgate_con[13], BIT(7)); rk_setreg(&priv->cru->clkgate_con[13], BIT(7));
break; break;
case SCLK_PCIEPHY_REF: case SCLK_PCIEPHY_REF:
rk_clrreg(&priv->cru->clksel_con[18], BIT(10)); if (readl(&priv->cru->clksel_con[18]) & BIT(10))
rk_setreg(&priv->cru->clkgate_con[12], BIT(6));
break; break;
default: default:
debug("%s: unsupported clk %ld\n", __func__, clk->id); debug("%s: unsupported clk %ld\n", __func__, clk->id);