[v3,1/6] clk: rk3399: Add enable/disable clks

Message ID 20200509165624.20791-2-jagan@amarulasolutions.com
State New
Headers show
Series
  • rockchip: Add PCIe host support
Related show

Commit Message

Jagan Teki May 9, 2020, 4:56 p.m. UTC
Yes, most of the high speed peripheral clocks
in rk3399 enabled by default.

But it would be better to handle them via clk
enable/disable API for handling proper reset
conditions like 'usb reset' over command line.

So, enable USB, GMAC clock via enable/disable ops.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
Changes for v3:
- Update USB clock registers

 drivers/clk/rockchip/clk_rk3399.c | 148 ++++++++++++++++++++++++++++++
 1 file changed, 148 insertions(+)

Comments

Suniel Mahesh May 10, 2020, 8:22 p.m. UTC | #1
On Sat, May 9, 2020 at 10:26 PM Jagan Teki <jagan@amarulasolutions.com>
wrote:

> Yes, most of the high speed peripheral clocks
> in rk3399 enabled by default.
>
> But it would be better to handle them via clk
> enable/disable API for handling proper reset
> conditions like 'usb reset' over command line.
>
> So, enable USB, GMAC clock via enable/disable ops.
>
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> ---
> Changes for v3:
> - Update USB clock registers
>
>  drivers/clk/rockchip/clk_rk3399.c | 148 ++++++++++++++++++++++++++++++
>  1 file changed, 148 insertions(+)
>
> diff --git a/drivers/clk/rockchip/clk_rk3399.c
> b/drivers/clk/rockchip/clk_rk3399.c
> index d822acace1..5d2bdb42c7 100644
> --- a/drivers/clk/rockchip/clk_rk3399.c
> +++ b/drivers/clk/rockchip/clk_rk3399.c
> @@ -1071,12 +1071,160 @@ static int __maybe_unused
> rk3399_clk_set_parent(struct clk *clk,
>         return -ENOENT;
>  }
>
> +static int rk3399_clk_enable(struct clk *clk)
> +{
> +       struct rk3399_clk_priv *priv = dev_get_priv(clk->dev);
> +
> +       switch (clk->id) {
> +       case SCLK_MAC:
> +               rk_clrreg(&priv->cru->clkgate_con[5], BIT(5));
> +               break;
> +       case SCLK_MAC_RX:
> +               rk_clrreg(&priv->cru->clkgate_con[5], BIT(8));
> +               break;
> +       case SCLK_MAC_TX:
> +               rk_clrreg(&priv->cru->clkgate_con[5], BIT(9));
> +               break;
> +       case SCLK_MACREF:
> +               rk_clrreg(&priv->cru->clkgate_con[5], BIT(7));
> +               break;
> +       case SCLK_MACREF_OUT:
> +               rk_clrreg(&priv->cru->clkgate_con[5], BIT(6));
> +               break;
> +       case ACLK_GMAC:
> +               rk_clrreg(&priv->cru->clkgate_con[32], BIT(0));
> +               break;
> +       case PCLK_GMAC:
> +               rk_clrreg(&priv->cru->clkgate_con[32], BIT(2));
> +               break;
> +       case SCLK_USB3OTG0_REF:
> +               rk_clrreg(&priv->cru->clkgate_con[12], BIT(1));
> +               break;
> +       case SCLK_USB3OTG1_REF:
> +               rk_clrreg(&priv->cru->clkgate_con[12], BIT(2));
> +               break;
> +       case SCLK_USB3OTG0_SUSPEND:
> +               rk_clrreg(&priv->cru->clkgate_con[12], BIT(3));
> +               break;
> +       case SCLK_USB3OTG1_SUSPEND:
> +               rk_clrreg(&priv->cru->clkgate_con[12], BIT(4));
> +               break;
> +       case ACLK_USB3OTG0:
> +               rk_clrreg(&priv->cru->clkgate_con[30], BIT(1));
> +               break;
> +       case ACLK_USB3OTG1:
> +               rk_clrreg(&priv->cru->clkgate_con[30], BIT(2));
> +               break;
> +       case ACLK_USB3_RKSOC_AXI_PERF:
> +               rk_clrreg(&priv->cru->clkgate_con[30], BIT(3));
> +               break;
> +       case ACLK_USB3:
> +               rk_clrreg(&priv->cru->clkgate_con[12], BIT(0));
> +               break;
> +       case ACLK_USB3_GRF:
> +               rk_clrreg(&priv->cru->clkgate_con[30], BIT(4));
> +               break;
> +       case HCLK_HOST0:
> +               rk_clrreg(&priv->cru->clksel_con[20], BIT(5));
> +               break;
> +       case HCLK_HOST0_ARB:
> +               rk_clrreg(&priv->cru->clksel_con[20], BIT(6));
> +               break;
> +       case HCLK_HOST1:
> +               rk_clrreg(&priv->cru->clksel_con[20], BIT(7));
> +               break;
> +       case HCLK_HOST1_ARB:
> +               rk_clrreg(&priv->cru->clksel_con[20], BIT(8));
> +               break;
> +       default:
> +               debug("%s: unsupported clk %ld\n", __func__, clk->id);
> +               return -ENOENT;
> +       }
> +
> +       return 0;
> +}
> +
> +static int rk3399_clk_disable(struct clk *clk)
> +{
> +       struct rk3399_clk_priv *priv = dev_get_priv(clk->dev);
> +
> +       switch (clk->id) {
> +       case SCLK_MAC:
> +               rk_setreg(&priv->cru->clkgate_con[5], BIT(5));
> +               break;
> +       case SCLK_MAC_RX:
> +               rk_setreg(&priv->cru->clkgate_con[5], BIT(8));
> +               break;
> +       case SCLK_MAC_TX:
> +               rk_setreg(&priv->cru->clkgate_con[5], BIT(9));
> +               break;
> +       case SCLK_MACREF:
> +               rk_setreg(&priv->cru->clkgate_con[5], BIT(7));
> +               break;
> +       case SCLK_MACREF_OUT:
> +               rk_setreg(&priv->cru->clkgate_con[5], BIT(6));
> +               break;
> +       case ACLK_GMAC:
> +               rk_setreg(&priv->cru->clkgate_con[32], BIT(0));
> +               break;
> +       case PCLK_GMAC:
> +               rk_setreg(&priv->cru->clkgate_con[32], BIT(2));
> +               break;
> +       case SCLK_USB3OTG0_REF:
> +               rk_setreg(&priv->cru->clkgate_con[12], BIT(1));
> +               break;
> +       case SCLK_USB3OTG1_REF:
> +               rk_setreg(&priv->cru->clkgate_con[12], BIT(2));
> +               break;
> +       case SCLK_USB3OTG0_SUSPEND:
> +               rk_setreg(&priv->cru->clkgate_con[12], BIT(3));
> +               break;
> +       case SCLK_USB3OTG1_SUSPEND:
> +               rk_setreg(&priv->cru->clkgate_con[12], BIT(4));
> +               break;
> +       case ACLK_USB3OTG0:
> +               rk_setreg(&priv->cru->clkgate_con[30], BIT(1));
> +               break;
> +       case ACLK_USB3OTG1:
> +               rk_setreg(&priv->cru->clkgate_con[30], BIT(2));
> +               break;
> +       case ACLK_USB3_RKSOC_AXI_PERF:
> +               rk_setreg(&priv->cru->clkgate_con[30], BIT(3));
> +               break;
> +       case ACLK_USB3:
> +               rk_setreg(&priv->cru->clkgate_con[12], BIT(0));
> +               break;
> +       case ACLK_USB3_GRF:
> +               rk_setreg(&priv->cru->clkgate_con[30], BIT(4));
> +               break;
> +       case HCLK_HOST0:
> +               rk_setreg(&priv->cru->clksel_con[20], BIT(5));
> +               break;
> +       case HCLK_HOST0_ARB:
> +               rk_setreg(&priv->cru->clksel_con[20], BIT(6));
> +               break;
> +       case HCLK_HOST1:
> +               rk_setreg(&priv->cru->clksel_con[20], BIT(7));
> +               break;
> +       case HCLK_HOST1_ARB:
> +               rk_setreg(&priv->cru->clksel_con[20], BIT(8));
> +               break;
> +       default:
> +               debug("%s: unsupported clk %ld\n", __func__, clk->id);
> +               return -ENOENT;
> +       }
> +
> +       return 0;
> +}
> +
>  static struct clk_ops rk3399_clk_ops = {
>         .get_rate = rk3399_clk_get_rate,
>         .set_rate = rk3399_clk_set_rate,
>  #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
>         .set_parent = rk3399_clk_set_parent,
>  #endif
> +       .enable = rk3399_clk_enable,
> +       .disable = rk3399_clk_disable,
>  };
>
>  #ifdef CONFIG_SPL_BUILD
> --
> 2.17.1
>

Tested-by: Suniel Mahesh <sunil.m@amarulasolutions.com> # roc-rk3399-pc
Suniel Mahesh May 10, 2020, 8:32 p.m. UTC | #2
On Sat, May 9, 2020 at 10:26 PM Jagan Teki <jagan@amarulasolutions.com>
wrote:

> Yes, most of the high speed peripheral clocks
> in rk3399 enabled by default.
>
> But it would be better to handle them via clk
> enable/disable API for handling proper reset
> conditions like 'usb reset' over command line.
>
> So, enable USB, GMAC clock via enable/disable ops.
>
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> ---
> Changes for v3:
> - Update USB clock registers
>
>  drivers/clk/rockchip/clk_rk3399.c | 148 ++++++++++++++++++++++++++++++
>  1 file changed, 148 insertions(+)
>
> diff --git a/drivers/clk/rockchip/clk_rk3399.c
> b/drivers/clk/rockchip/clk_rk3399.c
> index d822acace1..5d2bdb42c7 100644
> --- a/drivers/clk/rockchip/clk_rk3399.c
> +++ b/drivers/clk/rockchip/clk_rk3399.c
> @@ -1071,12 +1071,160 @@ static int __maybe_unused
> rk3399_clk_set_parent(struct clk *clk,
>         return -ENOENT;
>  }
>
> +static int rk3399_clk_enable(struct clk *clk)
> +{
> +       struct rk3399_clk_priv *priv = dev_get_priv(clk->dev);
> +
> +       switch (clk->id) {
> +       case SCLK_MAC:
> +               rk_clrreg(&priv->cru->clkgate_con[5], BIT(5));
> +               break;
> +       case SCLK_MAC_RX:
> +               rk_clrreg(&priv->cru->clkgate_con[5], BIT(8));
> +               break;
> +       case SCLK_MAC_TX:
> +               rk_clrreg(&priv->cru->clkgate_con[5], BIT(9));
> +               break;
> +       case SCLK_MACREF:
> +               rk_clrreg(&priv->cru->clkgate_con[5], BIT(7));
> +               break;
> +       case SCLK_MACREF_OUT:
> +               rk_clrreg(&priv->cru->clkgate_con[5], BIT(6));
> +               break;
> +       case ACLK_GMAC:
> +               rk_clrreg(&priv->cru->clkgate_con[32], BIT(0));
> +               break;
> +       case PCLK_GMAC:
> +               rk_clrreg(&priv->cru->clkgate_con[32], BIT(2));
> +               break;
> +       case SCLK_USB3OTG0_REF:
> +               rk_clrreg(&priv->cru->clkgate_con[12], BIT(1));
> +               break;
> +       case SCLK_USB3OTG1_REF:
> +               rk_clrreg(&priv->cru->clkgate_con[12], BIT(2));
> +               break;
> +       case SCLK_USB3OTG0_SUSPEND:
> +               rk_clrreg(&priv->cru->clkgate_con[12], BIT(3));
> +               break;
> +       case SCLK_USB3OTG1_SUSPEND:
> +               rk_clrreg(&priv->cru->clkgate_con[12], BIT(4));
> +               break;
> +       case ACLK_USB3OTG0:
> +               rk_clrreg(&priv->cru->clkgate_con[30], BIT(1));
> +               break;
> +       case ACLK_USB3OTG1:
> +               rk_clrreg(&priv->cru->clkgate_con[30], BIT(2));
> +               break;
> +       case ACLK_USB3_RKSOC_AXI_PERF:
> +               rk_clrreg(&priv->cru->clkgate_con[30], BIT(3));
> +               break;
> +       case ACLK_USB3:
> +               rk_clrreg(&priv->cru->clkgate_con[12], BIT(0));
> +               break;
> +       case ACLK_USB3_GRF:
> +               rk_clrreg(&priv->cru->clkgate_con[30], BIT(4));
> +               break;
> +       case HCLK_HOST0:
> +               rk_clrreg(&priv->cru->clksel_con[20], BIT(5));
> +               break;
> +       case HCLK_HOST0_ARB:
> +               rk_clrreg(&priv->cru->clksel_con[20], BIT(6));
> +               break;
> +       case HCLK_HOST1:
> +               rk_clrreg(&priv->cru->clksel_con[20], BIT(7));
> +               break;
> +       case HCLK_HOST1_ARB:
> +               rk_clrreg(&priv->cru->clksel_con[20], BIT(8));
> +               break;
> +       default:
> +               debug("%s: unsupported clk %ld\n", __func__, clk->id);
> +               return -ENOENT;
> +       }
> +
> +       return 0;
> +}
> +
> +static int rk3399_clk_disable(struct clk *clk)
> +{
> +       struct rk3399_clk_priv *priv = dev_get_priv(clk->dev);
> +
> +       switch (clk->id) {
> +       case SCLK_MAC:
> +               rk_setreg(&priv->cru->clkgate_con[5], BIT(5));
> +               break;
> +       case SCLK_MAC_RX:
> +               rk_setreg(&priv->cru->clkgate_con[5], BIT(8));
> +               break;
> +       case SCLK_MAC_TX:
> +               rk_setreg(&priv->cru->clkgate_con[5], BIT(9));
> +               break;
> +       case SCLK_MACREF:
> +               rk_setreg(&priv->cru->clkgate_con[5], BIT(7));
> +               break;
> +       case SCLK_MACREF_OUT:
> +               rk_setreg(&priv->cru->clkgate_con[5], BIT(6));
> +               break;
> +       case ACLK_GMAC:
> +               rk_setreg(&priv->cru->clkgate_con[32], BIT(0));
> +               break;
> +       case PCLK_GMAC:
> +               rk_setreg(&priv->cru->clkgate_con[32], BIT(2));
> +               break;
> +       case SCLK_USB3OTG0_REF:
> +               rk_setreg(&priv->cru->clkgate_con[12], BIT(1));
> +               break;
> +       case SCLK_USB3OTG1_REF:
> +               rk_setreg(&priv->cru->clkgate_con[12], BIT(2));
> +               break;
> +       case SCLK_USB3OTG0_SUSPEND:
> +               rk_setreg(&priv->cru->clkgate_con[12], BIT(3));
> +               break;
> +       case SCLK_USB3OTG1_SUSPEND:
> +               rk_setreg(&priv->cru->clkgate_con[12], BIT(4));
> +               break;
> +       case ACLK_USB3OTG0:
> +               rk_setreg(&priv->cru->clkgate_con[30], BIT(1));
> +               break;
> +       case ACLK_USB3OTG1:
> +               rk_setreg(&priv->cru->clkgate_con[30], BIT(2));
> +               break;
> +       case ACLK_USB3_RKSOC_AXI_PERF:
> +               rk_setreg(&priv->cru->clkgate_con[30], BIT(3));
> +               break;
> +       case ACLK_USB3:
> +               rk_setreg(&priv->cru->clkgate_con[12], BIT(0));
> +               break;
> +       case ACLK_USB3_GRF:
> +               rk_setreg(&priv->cru->clkgate_con[30], BIT(4));
> +               break;
> +       case HCLK_HOST0:
> +               rk_setreg(&priv->cru->clksel_con[20], BIT(5));
> +               break;
> +       case HCLK_HOST0_ARB:
> +               rk_setreg(&priv->cru->clksel_con[20], BIT(6));
> +               break;
> +       case HCLK_HOST1:
> +               rk_setreg(&priv->cru->clksel_con[20], BIT(7));
> +               break;
> +       case HCLK_HOST1_ARB:
> +               rk_setreg(&priv->cru->clksel_con[20], BIT(8));
> +               break;
> +       default:
> +               debug("%s: unsupported clk %ld\n", __func__, clk->id);
> +               return -ENOENT;
> +       }
> +
> +       return 0;
> +}
> +
>  static struct clk_ops rk3399_clk_ops = {
>         .get_rate = rk3399_clk_get_rate,
>         .set_rate = rk3399_clk_set_rate,
>  #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
>         .set_parent = rk3399_clk_set_parent,
>  #endif
> +       .enable = rk3399_clk_enable,
> +       .disable = rk3399_clk_disable,
>  };
>
>  #ifdef CONFIG_SPL_BUILD
> --
> 2.17.1
>

Tested-by: Suniel Mahesh <sunil@amarulasolutions.com> #roc-rk3399-pc
Kever Yang May 15, 2020, 2:52 a.m. UTC | #3
On 2020/5/10 上午12:56, Jagan Teki wrote:
> Yes, most of the high speed peripheral clocks
> in rk3399 enabled by default.
>
> But it would be better to handle them via clk
> enable/disable API for handling proper reset
> conditions like 'usb reset' over command line.
>
> So, enable USB, GMAC clock via enable/disable ops.
>
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>

Reviewed-by: Kever Yang <kever.yang@rock-chips.com>

Thanks,
- Kever
> ---
> Changes for v3:
> - Update USB clock registers
>
>   drivers/clk/rockchip/clk_rk3399.c | 148 ++++++++++++++++++++++++++++++
>   1 file changed, 148 insertions(+)
>
> diff --git a/drivers/clk/rockchip/clk_rk3399.c b/drivers/clk/rockchip/clk_rk3399.c
> index d822acace1..5d2bdb42c7 100644
> --- a/drivers/clk/rockchip/clk_rk3399.c
> +++ b/drivers/clk/rockchip/clk_rk3399.c
> @@ -1071,12 +1071,160 @@ static int __maybe_unused rk3399_clk_set_parent(struct clk *clk,
>   	return -ENOENT;
>   }
>   
> +static int rk3399_clk_enable(struct clk *clk)
> +{
> +	struct rk3399_clk_priv *priv = dev_get_priv(clk->dev);
> +
> +	switch (clk->id) {
> +	case SCLK_MAC:
> +		rk_clrreg(&priv->cru->clkgate_con[5], BIT(5));
> +		break;
> +	case SCLK_MAC_RX:
> +		rk_clrreg(&priv->cru->clkgate_con[5], BIT(8));
> +		break;
> +	case SCLK_MAC_TX:
> +		rk_clrreg(&priv->cru->clkgate_con[5], BIT(9));
> +		break;
> +	case SCLK_MACREF:
> +		rk_clrreg(&priv->cru->clkgate_con[5], BIT(7));
> +		break;
> +	case SCLK_MACREF_OUT:
> +		rk_clrreg(&priv->cru->clkgate_con[5], BIT(6));
> +		break;
> +	case ACLK_GMAC:
> +		rk_clrreg(&priv->cru->clkgate_con[32], BIT(0));
> +		break;
> +	case PCLK_GMAC:
> +		rk_clrreg(&priv->cru->clkgate_con[32], BIT(2));
> +		break;
> +	case SCLK_USB3OTG0_REF:
> +		rk_clrreg(&priv->cru->clkgate_con[12], BIT(1));
> +		break;
> +	case SCLK_USB3OTG1_REF:
> +		rk_clrreg(&priv->cru->clkgate_con[12], BIT(2));
> +		break;
> +	case SCLK_USB3OTG0_SUSPEND:
> +		rk_clrreg(&priv->cru->clkgate_con[12], BIT(3));
> +		break;
> +	case SCLK_USB3OTG1_SUSPEND:
> +		rk_clrreg(&priv->cru->clkgate_con[12], BIT(4));
> +		break;
> +	case ACLK_USB3OTG0:
> +		rk_clrreg(&priv->cru->clkgate_con[30], BIT(1));
> +		break;
> +	case ACLK_USB3OTG1:
> +		rk_clrreg(&priv->cru->clkgate_con[30], BIT(2));
> +		break;
> +	case ACLK_USB3_RKSOC_AXI_PERF:
> +		rk_clrreg(&priv->cru->clkgate_con[30], BIT(3));
> +		break;
> +	case ACLK_USB3:
> +		rk_clrreg(&priv->cru->clkgate_con[12], BIT(0));
> +		break;
> +	case ACLK_USB3_GRF:
> +		rk_clrreg(&priv->cru->clkgate_con[30], BIT(4));
> +		break;
> +	case HCLK_HOST0:
> +		rk_clrreg(&priv->cru->clksel_con[20], BIT(5));
> +		break;
> +	case HCLK_HOST0_ARB:
> +		rk_clrreg(&priv->cru->clksel_con[20], BIT(6));
> +		break;
> +	case HCLK_HOST1:
> +		rk_clrreg(&priv->cru->clksel_con[20], BIT(7));
> +		break;
> +	case HCLK_HOST1_ARB:
> +		rk_clrreg(&priv->cru->clksel_con[20], BIT(8));
> +		break;
> +	default:
> +		debug("%s: unsupported clk %ld\n", __func__, clk->id);
> +		return -ENOENT;
> +	}
> +
> +	return 0;
> +}
> +
> +static int rk3399_clk_disable(struct clk *clk)
> +{
> +	struct rk3399_clk_priv *priv = dev_get_priv(clk->dev);
> +
> +	switch (clk->id) {
> +	case SCLK_MAC:
> +		rk_setreg(&priv->cru->clkgate_con[5], BIT(5));
> +		break;
> +	case SCLK_MAC_RX:
> +		rk_setreg(&priv->cru->clkgate_con[5], BIT(8));
> +		break;
> +	case SCLK_MAC_TX:
> +		rk_setreg(&priv->cru->clkgate_con[5], BIT(9));
> +		break;
> +	case SCLK_MACREF:
> +		rk_setreg(&priv->cru->clkgate_con[5], BIT(7));
> +		break;
> +	case SCLK_MACREF_OUT:
> +		rk_setreg(&priv->cru->clkgate_con[5], BIT(6));
> +		break;
> +	case ACLK_GMAC:
> +		rk_setreg(&priv->cru->clkgate_con[32], BIT(0));
> +		break;
> +	case PCLK_GMAC:
> +		rk_setreg(&priv->cru->clkgate_con[32], BIT(2));
> +		break;
> +	case SCLK_USB3OTG0_REF:
> +		rk_setreg(&priv->cru->clkgate_con[12], BIT(1));
> +		break;
> +	case SCLK_USB3OTG1_REF:
> +		rk_setreg(&priv->cru->clkgate_con[12], BIT(2));
> +		break;
> +	case SCLK_USB3OTG0_SUSPEND:
> +		rk_setreg(&priv->cru->clkgate_con[12], BIT(3));
> +		break;
> +	case SCLK_USB3OTG1_SUSPEND:
> +		rk_setreg(&priv->cru->clkgate_con[12], BIT(4));
> +		break;
> +	case ACLK_USB3OTG0:
> +		rk_setreg(&priv->cru->clkgate_con[30], BIT(1));
> +		break;
> +	case ACLK_USB3OTG1:
> +		rk_setreg(&priv->cru->clkgate_con[30], BIT(2));
> +		break;
> +	case ACLK_USB3_RKSOC_AXI_PERF:
> +		rk_setreg(&priv->cru->clkgate_con[30], BIT(3));
> +		break;
> +	case ACLK_USB3:
> +		rk_setreg(&priv->cru->clkgate_con[12], BIT(0));
> +		break;
> +	case ACLK_USB3_GRF:
> +		rk_setreg(&priv->cru->clkgate_con[30], BIT(4));
> +		break;
> +	case HCLK_HOST0:
> +		rk_setreg(&priv->cru->clksel_con[20], BIT(5));
> +		break;
> +	case HCLK_HOST0_ARB:
> +		rk_setreg(&priv->cru->clksel_con[20], BIT(6));
> +		break;
> +	case HCLK_HOST1:
> +		rk_setreg(&priv->cru->clksel_con[20], BIT(7));
> +		break;
> +	case HCLK_HOST1_ARB:
> +		rk_setreg(&priv->cru->clksel_con[20], BIT(8));
> +		break;
> +	default:
> +		debug("%s: unsupported clk %ld\n", __func__, clk->id);
> +		return -ENOENT;
> +	}
> +
> +	return 0;
> +}
> +
>   static struct clk_ops rk3399_clk_ops = {
>   	.get_rate = rk3399_clk_get_rate,
>   	.set_rate = rk3399_clk_set_rate,
>   #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
>   	.set_parent = rk3399_clk_set_parent,
>   #endif
> +	.enable = rk3399_clk_enable,
> +	.disable = rk3399_clk_disable,
>   };
>   
>   #ifdef CONFIG_SPL_BUILD

Patch

diff --git a/drivers/clk/rockchip/clk_rk3399.c b/drivers/clk/rockchip/clk_rk3399.c
index d822acace1..5d2bdb42c7 100644
--- a/drivers/clk/rockchip/clk_rk3399.c
+++ b/drivers/clk/rockchip/clk_rk3399.c
@@ -1071,12 +1071,160 @@  static int __maybe_unused rk3399_clk_set_parent(struct clk *clk,
 	return -ENOENT;
 }
 
+static int rk3399_clk_enable(struct clk *clk)
+{
+	struct rk3399_clk_priv *priv = dev_get_priv(clk->dev);
+
+	switch (clk->id) {
+	case SCLK_MAC:
+		rk_clrreg(&priv->cru->clkgate_con[5], BIT(5));
+		break;
+	case SCLK_MAC_RX:
+		rk_clrreg(&priv->cru->clkgate_con[5], BIT(8));
+		break;
+	case SCLK_MAC_TX:
+		rk_clrreg(&priv->cru->clkgate_con[5], BIT(9));
+		break;
+	case SCLK_MACREF:
+		rk_clrreg(&priv->cru->clkgate_con[5], BIT(7));
+		break;
+	case SCLK_MACREF_OUT:
+		rk_clrreg(&priv->cru->clkgate_con[5], BIT(6));
+		break;
+	case ACLK_GMAC:
+		rk_clrreg(&priv->cru->clkgate_con[32], BIT(0));
+		break;
+	case PCLK_GMAC:
+		rk_clrreg(&priv->cru->clkgate_con[32], BIT(2));
+		break;
+	case SCLK_USB3OTG0_REF:
+		rk_clrreg(&priv->cru->clkgate_con[12], BIT(1));
+		break;
+	case SCLK_USB3OTG1_REF:
+		rk_clrreg(&priv->cru->clkgate_con[12], BIT(2));
+		break;
+	case SCLK_USB3OTG0_SUSPEND:
+		rk_clrreg(&priv->cru->clkgate_con[12], BIT(3));
+		break;
+	case SCLK_USB3OTG1_SUSPEND:
+		rk_clrreg(&priv->cru->clkgate_con[12], BIT(4));
+		break;
+	case ACLK_USB3OTG0:
+		rk_clrreg(&priv->cru->clkgate_con[30], BIT(1));
+		break;
+	case ACLK_USB3OTG1:
+		rk_clrreg(&priv->cru->clkgate_con[30], BIT(2));
+		break;
+	case ACLK_USB3_RKSOC_AXI_PERF:
+		rk_clrreg(&priv->cru->clkgate_con[30], BIT(3));
+		break;
+	case ACLK_USB3:
+		rk_clrreg(&priv->cru->clkgate_con[12], BIT(0));
+		break;
+	case ACLK_USB3_GRF:
+		rk_clrreg(&priv->cru->clkgate_con[30], BIT(4));
+		break;
+	case HCLK_HOST0:
+		rk_clrreg(&priv->cru->clksel_con[20], BIT(5));
+		break;
+	case HCLK_HOST0_ARB:
+		rk_clrreg(&priv->cru->clksel_con[20], BIT(6));
+		break;
+	case HCLK_HOST1:
+		rk_clrreg(&priv->cru->clksel_con[20], BIT(7));
+		break;
+	case HCLK_HOST1_ARB:
+		rk_clrreg(&priv->cru->clksel_con[20], BIT(8));
+		break;
+	default:
+		debug("%s: unsupported clk %ld\n", __func__, clk->id);
+		return -ENOENT;
+	}
+
+	return 0;
+}
+
+static int rk3399_clk_disable(struct clk *clk)
+{
+	struct rk3399_clk_priv *priv = dev_get_priv(clk->dev);
+
+	switch (clk->id) {
+	case SCLK_MAC:
+		rk_setreg(&priv->cru->clkgate_con[5], BIT(5));
+		break;
+	case SCLK_MAC_RX:
+		rk_setreg(&priv->cru->clkgate_con[5], BIT(8));
+		break;
+	case SCLK_MAC_TX:
+		rk_setreg(&priv->cru->clkgate_con[5], BIT(9));
+		break;
+	case SCLK_MACREF:
+		rk_setreg(&priv->cru->clkgate_con[5], BIT(7));
+		break;
+	case SCLK_MACREF_OUT:
+		rk_setreg(&priv->cru->clkgate_con[5], BIT(6));
+		break;
+	case ACLK_GMAC:
+		rk_setreg(&priv->cru->clkgate_con[32], BIT(0));
+		break;
+	case PCLK_GMAC:
+		rk_setreg(&priv->cru->clkgate_con[32], BIT(2));
+		break;
+	case SCLK_USB3OTG0_REF:
+		rk_setreg(&priv->cru->clkgate_con[12], BIT(1));
+		break;
+	case SCLK_USB3OTG1_REF:
+		rk_setreg(&priv->cru->clkgate_con[12], BIT(2));
+		break;
+	case SCLK_USB3OTG0_SUSPEND:
+		rk_setreg(&priv->cru->clkgate_con[12], BIT(3));
+		break;
+	case SCLK_USB3OTG1_SUSPEND:
+		rk_setreg(&priv->cru->clkgate_con[12], BIT(4));
+		break;
+	case ACLK_USB3OTG0:
+		rk_setreg(&priv->cru->clkgate_con[30], BIT(1));
+		break;
+	case ACLK_USB3OTG1:
+		rk_setreg(&priv->cru->clkgate_con[30], BIT(2));
+		break;
+	case ACLK_USB3_RKSOC_AXI_PERF:
+		rk_setreg(&priv->cru->clkgate_con[30], BIT(3));
+		break;
+	case ACLK_USB3:
+		rk_setreg(&priv->cru->clkgate_con[12], BIT(0));
+		break;
+	case ACLK_USB3_GRF:
+		rk_setreg(&priv->cru->clkgate_con[30], BIT(4));
+		break;
+	case HCLK_HOST0:
+		rk_setreg(&priv->cru->clksel_con[20], BIT(5));
+		break;
+	case HCLK_HOST0_ARB:
+		rk_setreg(&priv->cru->clksel_con[20], BIT(6));
+		break;
+	case HCLK_HOST1:
+		rk_setreg(&priv->cru->clksel_con[20], BIT(7));
+		break;
+	case HCLK_HOST1_ARB:
+		rk_setreg(&priv->cru->clksel_con[20], BIT(8));
+		break;
+	default:
+		debug("%s: unsupported clk %ld\n", __func__, clk->id);
+		return -ENOENT;
+	}
+
+	return 0;
+}
+
 static struct clk_ops rk3399_clk_ops = {
 	.get_rate = rk3399_clk_get_rate,
 	.set_rate = rk3399_clk_set_rate,
 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
 	.set_parent = rk3399_clk_set_parent,
 #endif
+	.enable = rk3399_clk_enable,
+	.disable = rk3399_clk_disable,
 };
 
 #ifdef CONFIG_SPL_BUILD