[PATCH] drivers: clk: n5x: Add support for enable/disable API
Chee, Tien Fong
tien.fong.chee at altera.com
Mon Jun 8 04:30:39 CEST 2026
On 7/5/2026 5:03 pm, Chen Huei Lok wrote:
> From: Alif Zakuan Yuslaimi <alif.zakuan.yuslaimi at altera.com>
>
> Update N5X clock driver to support enabling or disabling
> the peripheral clocks via clock driver model APIs.
>
> The caller will pass the clock ID to this driver and the driver
> will then proceed to manipulate the desired bit in the N5X clock
> manager peripheral PLL register based on the given clock ID.
>
> N5X_L4_SYS_FREE_CLK is a free-running clock with no gate control in
> hardware, therefore attempting to enable or disable it is not applicable.
> Return -EOPNOTSUPP for this clock ID and treat it as a no-op in
> socfpga_clk_enable() and socfpga_clk_disable().
>
> Signed-off-by: Alif Zakuan Yuslaimi <alif.zakuan.yuslaimi at altera.com>
> Signed-off-by: Chen Huei Lok <chen.huei.lok at altera.com>
> ---
> drivers/clk/altera/clk-n5x.c | 129 +++++++++++++++++++++++++++++++++++
> drivers/clk/altera/clk-n5x.h | 19 ++++++
> 2 files changed, 148 insertions(+)
>
> diff --git a/drivers/clk/altera/clk-n5x.c b/drivers/clk/altera/clk-n5x.c
> index 185c9028a78..5d7b5f1e885 100644
> --- a/drivers/clk/altera/clk-n5x.c
> +++ b/drivers/clk/altera/clk-n5x.c
> @@ -13,6 +13,8 @@
>
> struct socfpga_clk_plat {
> void __iomem *regs;
> + int pllgrp;
> + int bitmask;
> };
>
> /*
> @@ -437,8 +439,134 @@ static ulong socfpga_clk_get_rate(struct clk *clk)
> }
> }
>
> +static int bitmask_from_clk_id(struct clk *clk)
> +{
> + struct socfpga_clk_plat *plat = dev_get_plat(clk->dev);
> +
> + switch (clk->id) {
> + case N5X_MPU_CLK:
> + plat->pllgrp = CLKMGR_MAINPLL_EN;
> + plat->bitmask = CLKMGR_MAINPLLGRP_EN_MPUCLK_MASK;
> + break;
> + case N5X_L4_MAIN_CLK:
> + plat->pllgrp = CLKMGR_MAINPLL_EN;
> + plat->bitmask = CLKMGR_MAINPLLGRP_EN_L4MAINCLK_MASK;
> + break;
> + case N5X_L4_MP_CLK:
> + case N5X_NAND_X_CLK:
> + plat->pllgrp = CLKMGR_MAINPLL_EN;
> + plat->bitmask = CLKMGR_MAINPLLGRP_EN_L4MPCLK_MASK;
> + break;
> + case N5X_L4_SP_CLK:
> + plat->pllgrp = CLKMGR_MAINPLL_EN;
> + plat->bitmask = CLKMGR_MAINPLLGRP_EN_L4SPCLK_MASK;
> + break;
> + case N5X_CS_AT_CLK:
> + plat->pllgrp = CLKMGR_MAINPLL_EN;
> + plat->bitmask = CLKMGR_MAINPLLGRP_EN_CSCLK_MASK;
> + break;
> + case N5X_CS_TRACE_CLK:
> + plat->pllgrp = CLKMGR_MAINPLL_EN;
> + plat->bitmask = CLKMGR_MAINPLLGRP_EN_CSCLK_MASK;
> + break;
> + case N5X_CS_PDBG_CLK:
> + plat->pllgrp = CLKMGR_MAINPLL_EN;
> + plat->bitmask = CLKMGR_MAINPLLGRP_EN_CSCLK_MASK;
> + break;
> + case N5X_CS_TIMER_CLK:
> + plat->pllgrp = CLKMGR_MAINPLL_EN;
> + plat->bitmask = CLKMGR_MAINPLLGRP_EN_CSTIMERCLK_MASK;
> + break;
> + case N5X_S2F_USER0_CLK:
> + plat->pllgrp = CLKMGR_MAINPLL_EN;
> + plat->bitmask = CLKMGR_MAINPLLGRP_EN_S2FUSER0CLK_MASK;
> + break;
> + case N5X_EMAC0_CLK:
> + plat->pllgrp = CLKMGR_PERPLL_EN;
> + plat->bitmask = CLKMGR_PERPLLGRP_EN_EMAC0CLK_MASK;
> + break;
> + case N5X_EMAC1_CLK:
> + plat->pllgrp = CLKMGR_PERPLL_EN;
> + plat->bitmask = CLKMGR_PERPLLGRP_EN_EMAC1CLK_MASK;
> + break;
> + case N5X_EMAC2_CLK:
> + plat->pllgrp = CLKMGR_PERPLL_EN;
> + plat->bitmask = CLKMGR_PERPLLGRP_EN_EMAC2CLK_MASK;
> + break;
> + case N5X_EMAC_PTP_CLK:
> + plat->pllgrp = CLKMGR_PERPLL_EN;
> + plat->bitmask = CLKMGR_PERPLLGRP_EN_EMACPTPCLK_MASK;
> + break;
> + case N5X_GPIO_DB_CLK:
> + plat->pllgrp = CLKMGR_PERPLL_EN;
> + plat->bitmask = CLKMGR_PERPLLGRP_EN_GPIODBCLK_MASK;
> + break;
> + case N5X_SDMMC_CLK:
> + plat->pllgrp = CLKMGR_PERPLL_EN;
> + plat->bitmask = CLKMGR_PERPLLGRP_EN_SDMMCCLK_MASK;
> + break;
> + case N5X_S2F_USER1_CLK:
> + plat->pllgrp = CLKMGR_PERPLL_EN;
> + plat->bitmask = CLKMGR_PERPLLGRP_EN_S2FUSER1CLK_MASK;
> + break;
> + case N5X_PSI_REF_CLK:
> + plat->pllgrp = CLKMGR_PERPLL_EN;
> + plat->bitmask = CLKMGR_PERPLLGRP_EN_PSIREFCLK_MASK;
> + break;
> + case N5X_USB_CLK:
> + plat->pllgrp = CLKMGR_PERPLL_EN;
> + plat->bitmask = CLKMGR_PERPLLGRP_EN_USBCLK_MASK;
> + break;
> + case N5X_SPI_M_CLK:
> + plat->pllgrp = CLKMGR_PERPLL_EN;
> + plat->bitmask = CLKMGR_PERPLLGRP_EN_SPIMCLK_MASK;
> + break;
> + case N5X_NAND_CLK:
> + plat->pllgrp = CLKMGR_PERPLL_EN;
> + plat->bitmask = CLKMGR_PERPLLGRP_EN_NANDCLK_MASK;
> + break;
> + case N5X_L4_SYS_FREE_CLK:
> + return -EOPNOTSUPP;
> + default:
> + return -ENXIO;
> + }
> +
> + return 0;
> +}
> +
> static int socfpga_clk_enable(struct clk *clk)
> {
> + struct socfpga_clk_plat *plat = dev_get_plat(clk->dev);
> + uintptr_t base_addr = (uintptr_t)plat->regs;
> + int ret;
> +
> + ret = bitmask_from_clk_id(clk);
> + if (ret == -EOPNOTSUPP)
> + return 0;
> +
> + if (ret)
> + return ret;
> +
> + setbits_le32(base_addr + plat->pllgrp, plat->bitmask);
> +
> + return 0;
> +}
> +
> +static int socfpga_clk_disable(struct clk *clk)
> +{
> + struct socfpga_clk_plat *plat = dev_get_plat(clk->dev);
> + uintptr_t base_addr = (uintptr_t)plat->regs;
> + int ret;
> +
> + ret = bitmask_from_clk_id(clk);
> + if (ret == -EOPNOTSUPP)
> + return 0;
> +
> + if (ret)
> + return ret;
> +
> + clrbits_le32(base_addr + plat->pllgrp, plat->bitmask);
> +
> return 0;
> }
>
> @@ -466,6 +594,7 @@ static int socfpga_clk_of_to_plat(struct udevice *dev)
>
> static struct clk_ops socfpga_clk_ops = {
> .enable = socfpga_clk_enable,
> + .disable = socfpga_clk_disable,
> .get_rate = socfpga_clk_get_rate,
> };
>
> diff --git a/drivers/clk/altera/clk-n5x.h b/drivers/clk/altera/clk-n5x.h
> index f6a9f0a7947..87849d35e50 100644
> --- a/drivers/clk/altera/clk-n5x.h
> +++ b/drivers/clk/altera/clk-n5x.h
> @@ -199,7 +199,26 @@ struct cm_config {
>
> #define CLKMGR_LOSTLOCK_SET_MASK BIT(0)
>
> +#define CLKMGR_MAINPLLGRP_EN_MPUCLK_MASK BIT(0)
> +#define CLKMGR_MAINPLLGRP_EN_L4MAINCLK_MASK BIT(1)
> +#define CLKMGR_MAINPLLGRP_EN_L4MPCLK_MASK BIT(2)
> +#define CLKMGR_MAINPLLGRP_EN_L4SPCLK_MASK BIT(3)
> +#define CLKMGR_MAINPLLGRP_EN_CSCLK_MASK BIT(4)
> +#define CLKMGR_MAINPLLGRP_EN_CSTIMERCLK_MASK BIT(5)
> +#define CLKMGR_MAINPLLGRP_EN_S2FUSER0CLK_MASK BIT(6)
> +
> +#define CLKMGR_PERPLLGRP_EN_EMAC0CLK_MASK BIT(0)
> +#define CLKMGR_PERPLLGRP_EN_EMAC1CLK_MASK BIT(1)
> +#define CLKMGR_PERPLLGRP_EN_EMAC2CLK_MASK BIT(2)
> +#define CLKMGR_PERPLLGRP_EN_EMACPTPCLK_MASK BIT(3)
> +#define CLKMGR_PERPLLGRP_EN_GPIODBCLK_MASK BIT(4)
> #define CLKMGR_PERPLLGRP_EN_SDMMCCLK_MASK BIT(5)
> +#define CLKMGR_PERPLLGRP_EN_S2FUSER1CLK_MASK BIT(6)
> +#define CLKMGR_PERPLLGRP_EN_PSIREFCLK_MASK BIT(7)
> +#define CLKMGR_PERPLLGRP_EN_USBCLK_MASK BIT(8)
> +#define CLKMGR_PERPLLGRP_EN_SPIMCLK_MASK BIT(9)
> +#define CLKMGR_PERPLLGRP_EN_NANDCLK_MASK BIT(10)
> +
> #define CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_OFFSET 26
> #define CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_MASK BIT(26)
> #define CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_OFFSET 27
Reviewed-by: Tien Fong Chee <tien.fong.chee at altera.com>
Best regards,
Tien Fong
More information about the U-Boot
mailing list