[PATCH 1/9] drivers: clk: dm: Add clock driver for Diamond Mesa
Sean Anderson
seanga2 at gmail.com
Wed Sep 28 19:14:14 CEST 2022
On 9/18/22 08:17, Jit Loon Lim wrote:
> From: Siew Chin Lim <elly.siew.chin.lim at intel.com>
>
> Add clock manager driver for Diamond Mesa. Provides clock
> initialization and get_rate functions.
It appears that you are doing a static configuration of the
clocks (with no provision for later modifying clocks). Can
you add some comments to the commit message regarding rates
for the major clocks and why you chose them?
> Signed-off-by: Siew Chin Lim <elly.siew.chin.lim at intel.com>
> Signed-off-by: Jit Loon Lim <jit.loon.lim at intel.com>
> ---
> drivers/clk/altera/clk-dm.c | 504 +++++++++++++++++++++++++++
> drivers/clk/altera/clk-dm.h | 217 ++++++++++++
> include/dt-bindings/clock/dm-clock.h | 71 ++++
> 3 files changed, 792 insertions(+)
> create mode 100644 drivers/clk/altera/clk-dm.c
> create mode 100644 drivers/clk/altera/clk-dm.h
> create mode 100644 include/dt-bindings/clock/dm-clock.h
Please reconsider the prefix "DM" as it typically means "Driver
Model" in the rest of U-Boot. diamond_? dmesa_? diamesa_?
This commit also needs to add clk-dm.o to drivers/clk/altera/Makefile.
>
> diff --git a/drivers/clk/altera/clk-dm.c b/drivers/clk/altera/clk-dm.c
> new file mode 100644
> index 0000000000..1076240b41
> --- /dev/null
> +++ b/drivers/clk/altera/clk-dm.c
> @@ -0,0 +1,504 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2020 Intel Corporation <www.intel.com>
Is this accurate?
> + */
> +
> +#include <common.h>
> +#include <asm/arch/clock_manager.h>
> +#include <asm/io.h>
> +#include <clk-uclass.h>
This should come after common.h.
> +#include <dm.h>
> +#include <dm/lists.h>
> +#include <dm/util.h>
> +#include <dt-bindings/clock/dm-clock.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +struct socfpga_clk_plat {
> + void __iomem *regs;
> +};
> +
> +/*
> + * function to write the bypass register which requires a poll of the
> + * busy bit
> + */
> +static void clk_write_bypass_mainpll(struct socfpga_clk_plat *plat, u32 val)
> +{
> + CM_REG_WRITEL(plat, val, CLKMGR_MAINPLL_BYPASS);
> + cm_wait_for_fsm();
> +}
> +
> +static void clk_write_bypass_perpll(struct socfpga_clk_plat *plat, u32 val)
> +{
> + CM_REG_WRITEL(plat, val, CLKMGR_PERPLL_BYPASS);
> + cm_wait_for_fsm();
> +}
> +
> +#ifndef CONFIG_TARGET_SOCFPGA_DM
> +/* function to write the ctrl register which requires a poll of the busy bit */
> +static void clk_write_ctrl(struct socfpga_clk_plat *plat, u32 val)
> +{
> + CM_REG_WRITEL(plat, val, CLKMGR_CTRL);
> + cm_wait_for_fsm();
> +}
> +#endif
You can define this unconditionally...
> +
> +/*
> + * Setup clocks while making no assumptions about previous state of the clocks.
> + */
> +static void clk_basic_init(struct udevice *dev,
> + const struct cm_config * const cfg)
> +{
> + struct socfpga_clk_plat *plat = dev_get_plat(dev);
> +
> + if (!cfg)
> + return;
> +
> +#ifndef CONFIG_TARGET_SOCFPGA_DM
> +#ifdef CONFIG_SPL_BUILD
> + /* Always force clock manager into boot mode before any configuration */
> + clk_write_ctrl(plat,
> + CM_REG_READL(plat, CLKMGR_CTRL) | CLKMGR_CTRL_BOOTMODE);
> +#else
> + /* Skip clock configuration in SSBL if it's not in boot mode */
> + if (!(CM_REG_READL(plat, CLKMGR_CTRL) & CLKMGR_CTRL_BOOTMODE))
> + return;
> +#endif
> +#endif
...and then use regular ifs here. e.g.
if (IS_ENABLED(CONFIG_TARGET_SOCFPGA_DM)) {
if (spl_phase() == PHASE_SPL)
...
else
...
}
> +
> + /* Put both PLLs in bypass */
> + clk_write_bypass_mainpll(plat, CLKMGR_BYPASS_MAINPLL_ALL);
> + clk_write_bypass_perpll(plat, CLKMGR_BYPASS_PERPLL_ALL);
> +
> + /* Put both PLLs in Reset */
> + CM_REG_SETBITS(plat, CLKMGR_MAINPLL_PLLCTRL,
> + CLKMGR_PLLCTRL_BYPASS_MASK);
> + CM_REG_SETBITS(plat, CLKMGR_PERPLL_PLLCTRL,
> + CLKMGR_PLLCTRL_BYPASS_MASK);
> +
> +#ifndef CONFIG_TARGET_SOCFPGA_DM
> + /* setup main PLL */
> + CM_REG_WRITEL(plat, cfg->main_pll_pllglob, CLKMGR_MAINPLL_PLLGLOB);
> + CM_REG_WRITEL(plat, cfg->main_pll_plldiv, CLKMGR_MAINPLL_PLLDIV);
> + CM_REG_WRITEL(plat, cfg->main_pll_plloutdiv, CLKMGR_MAINPLL_PLLOUTDIV);
> + CM_REG_WRITEL(plat, cfg->main_pll_mpuclk, CLKMGR_MAINPLL_MPUCLK);
> + CM_REG_WRITEL(plat, cfg->main_pll_nocclk, CLKMGR_MAINPLL_NOCCLK);
> + CM_REG_WRITEL(plat, cfg->main_pll_nocdiv, CLKMGR_MAINPLL_NOCDIV);
> +
> + /* setup peripheral */
> + CM_REG_WRITEL(plat, cfg->per_pll_pllglob, CLKMGR_PERPLL_PLLGLOB);
> + CM_REG_WRITEL(plat, cfg->per_pll_plldiv, CLKMGR_PERPLL_PLLDIV);
> + CM_REG_WRITEL(plat, cfg->per_pll_plloutdiv, CLKMGR_PERPLL_PLLOUTDIV);
> + CM_REG_WRITEL(plat, cfg->per_pll_emacctl, CLKMGR_PERPLL_EMACCTL);
> + CM_REG_WRITEL(plat, cfg->per_pll_gpiodiv, CLKMGR_PERPLL_GPIODIV);
> +#endif
I think you can do the same kind of thing here.
That said, what other target are you planning to support? Can you document
it in the commit message or somewhere in the code?
> +
> + /* Take both PLL out of reset and power up */
> + CM_REG_CLRBITS(plat, CLKMGR_MAINPLL_PLLCTRL,
> + CLKMGR_PLLCTRL_BYPASS_MASK);
> + CM_REG_CLRBITS(plat, CLKMGR_PERPLL_PLLCTRL,
> + CLKMGR_PLLCTRL_BYPASS_MASK);
> +
> + cm_wait_for_lock(CLKMGR_STAT_ALLPLL_LOCKED_MASK);
> +
> +#ifndef CONFIG_TARGET_SOCFPGA_DM
> + CM_REG_WRITEL(plat, cfg->alt_emacactr, CLKMGR_ALTR_EMACACTR);
> + CM_REG_WRITEL(plat, cfg->alt_emacbctr, CLKMGR_ALTR_EMACBCTR);
> + CM_REG_WRITEL(plat, cfg->alt_emacptpctr, CLKMGR_ALTR_EMACPTPCTR);
> + CM_REG_WRITEL(plat, cfg->alt_gpiodbctr, CLKMGR_ALTR_GPIODBCTR);
> + CM_REG_WRITEL(plat, cfg->alt_sdmmcctr, CLKMGR_ALTR_SDMMCCTR);
> + CM_REG_WRITEL(plat, cfg->alt_s2fuser0ctr, CLKMGR_ALTR_S2FUSER0CTR);
> + CM_REG_WRITEL(plat, cfg->alt_s2fuser1ctr, CLKMGR_ALTR_S2FUSER1CTR);
> + CM_REG_WRITEL(plat, cfg->alt_psirefctr, CLKMGR_ALTR_PSIREFCTR);
> +#endif
> +
> + /* Configure ping pong counters in altera group */
> + CM_REG_WRITEL(plat, CLKMGR_LOSTLOCK_SET_MASK, CLKMGR_MAINPLL_LOSTLOCK);
> + CM_REG_WRITEL(plat, CLKMGR_LOSTLOCK_SET_MASK, CLKMGR_PERPLL_LOSTLOCK);
> +
> + CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_MAINPLL_PLLGLOB) |
> + CLKMGR_PLLGLOB_CLR_LOSTLOCK_BYPASS_MASK,
> + CLKMGR_MAINPLL_PLLGLOB);
> + CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_PERPLL_PLLGLOB) |
> + CLKMGR_PLLGLOB_CLR_LOSTLOCK_BYPASS_MASK,
> + CLKMGR_PERPLL_PLLGLOB);
> +
> + /* Take all PLLs out of bypass */
> + clk_write_bypass_mainpll(plat, 0);
> + clk_write_bypass_perpll(plat, 0);
> +
> + /* Clear the loss of lock bits (write 1 to clear) */
> + CM_REG_CLRBITS(plat, CLKMGR_INTRCLR,
> + CLKMGR_INTER_PERPLLLOST_MASK |
> + CLKMGR_INTER_MAINPLLLOST_MASK);
> +
> + /* Take all ping pong counters out of reset */
> + CM_REG_CLRBITS(plat, CLKMGR_ALTR_EXTCNTRST,
> + CLKMGR_ALT_EXTCNTRST_ALLCNTRST_MASK);
> +
> +#ifndef CONFIG_TARGET_SOCFPGA_DM
> + /* Out of boot mode */
> + clk_write_ctrl(plat,
> + CM_REG_READL(plat, CLKMGR_CTRL) & ~CLKMGR_CTRL_BOOTMODE);
> +#endif
> +}
> +
> +static u32 clk_get_5_1_clk_src(struct socfpga_clk_plat *plat, u32 reg)
> +{
> + u32 clksrc = CM_REG_READL(plat, reg);
> +
> + return (clksrc & CLKMGR_CLKSRC_MASK) >> CLKMGR_CLKSRC_OFFSET;
> +}
> +
> +static u64 clk_get_pll_output_hz(struct socfpga_clk_plat *plat,
> + u32 pllglob_reg, u32 plldiv_reg)
As a general note, I would expect this to be named something like
dm_pll_get_rate()
(using your existing dm_ prefix), since it is implicit that all rates are in Hz.
> +{
> + u64 clock = 0;
> + u32 clklsrc, divf, divr, divq, power = 1;
> +
> + /* Get input clock frequency */
> + clklsrc = (CM_REG_READL(plat, pllglob_reg) &
> + CLKMGR_PLLGLOB_VCO_PSRC_MASK) >>
> + CLKMGR_PLLGLOB_VCO_PSRC_OFFSET;
> +
> + switch (clklsrc) {
> + case CLKMGR_VCO_PSRC_EOSC1:
> + clock = cm_get_osc_clk_hz();
> + break;
> + case CLKMGR_VCO_PSRC_INTOSC:
> + clock = cm_get_intosc_clk_hz();
> + break;
> + case CLKMGR_VCO_PSRC_F2S:
> + clock = cm_get_fpga_clk_hz();
> + break;
> + }
> +
> + /* Calculate pll out clock frequency */
> + divf = (CM_REG_READL(plat, plldiv_reg) &
> + CLKMGR_PLLDIV_FDIV_MASK) >>
> + CLKMGR_PLLDIV_FDIV_OFFSET;
> +
> + divr = (CM_REG_READL(plat, plldiv_reg) &
> + CLKMGR_PLLDIV_REFCLKDIV_MASK) >>
> + CLKMGR_PLLDIV_REFCLKDIV_OFFSET;
> +
> + divq = (CM_REG_READL(plat, plldiv_reg) &
> + CLKMGR_PLLDIV_OUTDIV_QDIV_MASK) >>
> + CLKMGR_PLLDIV_OUTDIV_QDIV_OFFSET;
> +
> + while (divq) {
> + power *= 2;
> + divq--;
> + }
> +
> + return ((clock * 2 * (divf + 1)) / ((divr + 1) * power));
> +}
> +
> +static u64 clk_get_clksrc_hz(struct socfpga_clk_plat *plat, u32 clksrc_reg,
> + u32 main_div, u32 per_div)
> +{
> + u64 clock = 0;
> + u32 clklsrc = clk_get_5_1_clk_src(plat, clksrc_reg);
> +
> + switch (clklsrc) {
> + case CLKMGR_CLKSRC_MAIN:
> + clock = clk_get_pll_output_hz(plat,
> + CLKMGR_MAINPLL_PLLGLOB,
> + CLKMGR_MAINPLL_PLLDIV);
> + clock /= 1 + main_div;
> + break;
> +
> + case CLKMGR_CLKSRC_PER:
> + clock = clk_get_pll_output_hz(plat,
> + CLKMGR_PERPLL_PLLGLOB,
> + CLKMGR_PERPLL_PLLDIV);
> + clock /= 1 + per_div;
> + break;
> +
> + case CLKMGR_CLKSRC_OSC1:
> + clock = cm_get_osc_clk_hz();
> + break;
> +
> + case CLKMGR_CLKSRC_INTOSC:
> + clock = cm_get_intosc_clk_hz();
> + break;
> +
> + case CLKMGR_CLKSRC_FPGA:
> + clock = cm_get_fpga_clk_hz();
> + break;
> + default:
> + return 0;
> + }
> +
> + return clock;
> +}
> +
> +static u64 clk_get_mpu_clk_hz(struct socfpga_clk_plat *plat)
> +{
> + u32 mainpll_c0cnt = (CM_REG_READL(plat, CLKMGR_MAINPLL_PLLOUTDIV) &
> + CLKMGR_PLLOUTDIV_C0CNT_MASK) >>
> + CLKMGR_PLLOUTDIV_C0CNT_OFFSET;
> +
> + u32 perpll_c0cnt = (CM_REG_READL(plat, CLKMGR_PERPLL_PLLOUTDIV) &
> + CLKMGR_PLLOUTDIV_C0CNT_MASK) >>
> + CLKMGR_PLLOUTDIV_C0CNT_OFFSET;
> +
> + u64 clock = clk_get_clksrc_hz(plat, CLKMGR_MAINPLL_MPUCLK,
> + mainpll_c0cnt, perpll_c0cnt);
> +
> + clock /= 1 + (CM_REG_READL(plat, CLKMGR_MAINPLL_MPUCLK) &
> + CLKMGR_CLKCNT_MSK);
> +
> + return clock;
> +}
> +
> +static u32 clk_get_l3_main_clk_hz(struct socfpga_clk_plat *plat)
> +{
> + u32 mainpll_c1cnt = (CM_REG_READL(plat, CLKMGR_MAINPLL_PLLOUTDIV) &
> + CLKMGR_PLLOUTDIV_C1CNT_MASK) >>
> + CLKMGR_PLLOUTDIV_C1CNT_OFFSET;
> +
> + u32 perpll_c1cnt = (CM_REG_READL(plat, CLKMGR_PERPLL_PLLOUTDIV) &
> + CLKMGR_PLLOUTDIV_C1CNT_MASK) >>
> + CLKMGR_PLLOUTDIV_C1CNT_OFFSET;
> +
> + return clk_get_clksrc_hz(plat, CLKMGR_MAINPLL_NOCCLK,
> + mainpll_c1cnt, perpll_c1cnt);
> +}
> +
> +static u32 clk_get_l4_main_clk_hz(struct socfpga_clk_plat *plat)
> +{
> + u64 clock = clk_get_l3_main_clk_hz(plat);
> +
> + clock /= BIT((CM_REG_READL(plat, CLKMGR_MAINPLL_NOCDIV) >>
> + CLKMGR_NOCDIV_L4MAIN_OFFSET) &
> + CLKMGR_NOCDIV_DIVIDER_MASK);
> +
> + return clock;
> +}
> +
> +static u32 clk_get_sdmmc_clk_hz(struct socfpga_clk_plat *plat)
> +{
> + u32 mainpll_c3cnt = (CM_REG_READL(plat, CLKMGR_MAINPLL_PLLOUTDIV) &
> + CLKMGR_PLLOUTDIV_C3CNT_MASK) >>
> + CLKMGR_PLLOUTDIV_C3CNT_OFFSET;
> +
> + u32 perpll_c3cnt = (CM_REG_READL(plat, CLKMGR_PERPLL_PLLOUTDIV) &
> + CLKMGR_PLLOUTDIV_C3CNT_MASK) >>
> + CLKMGR_PLLOUTDIV_C3CNT_OFFSET;
> +
> + u64 clock = clk_get_clksrc_hz(plat, CLKMGR_ALTR_SDMMCCTR,
> + mainpll_c3cnt, perpll_c3cnt);
> +
> + clock /= 1 + (CM_REG_READL(plat, CLKMGR_ALTR_SDMMCCTR) &
> + CLKMGR_CLKCNT_MSK);
> +
> + return clock / 4;
> +}
> +
> +#ifndef CONFIG_TARGET_SOCFPGA_DM
> +static u32 clk_get_l4_sp_clk_hz(struct socfpga_clk_plat *plat)
> +{
> + u64 clock = clk_get_l3_main_clk_hz(plat);
> +
> + clock /= BIT((CM_REG_READL(plat, CLKMGR_MAINPLL_NOCDIV) >>
> + CLKMGR_NOCDIV_L4SPCLK_OFFSET) &
> + CLKMGR_NOCDIV_DIVIDER_MASK);
> +
> + return clock;
> +}
> +#endif
> +
> +static u32 clk_get_l4_mp_clk_hz(struct socfpga_clk_plat *plat)
> +{
> + u64 clock = clk_get_l3_main_clk_hz(plat);
> +
> + clock /= BIT((CM_REG_READL(plat, CLKMGR_MAINPLL_NOCDIV) >>
> + CLKMGR_NOCDIV_L4MPCLK_OFFSET) &
> + CLKMGR_NOCDIV_DIVIDER_MASK);
> +
> + return clock;
> +}
> +
> +static u32 clk_get_l4_sys_free_clk_hz(struct socfpga_clk_plat *plat)
> +{
> + if (CM_REG_READL(plat, CLKMGR_STAT) & CLKMGR_STAT_BOOTMODE)
> + return clk_get_l3_main_clk_hz(plat) / 2;
> +
> + return clk_get_l3_main_clk_hz(plat) / 4;
> +}
> +
> +static u32 clk_get_emac_clk_hz(struct socfpga_clk_plat *plat, u32 emac_id)
> +{
> + bool emacsel_a;
> + u32 ctl;
> + u32 ctr_reg;
> + u32 clock;
> + u32 div;
> + u32 reg;
> +
> + /* Get EMAC clock source */
> + ctl = CM_REG_READL(plat, CLKMGR_PERPLL_EMACCTL);
> + if (emac_id == DM_EMAC0_CLK)
> + ctl = (ctl >> CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_OFFSET) &
> + CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_MASK;
> + else if (emac_id == DM_EMAC1_CLK)
> + ctl = (ctl >> CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_OFFSET) &
> + CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_MASK;
> + else if (emac_id == DM_EMAC2_CLK)
> + ctl = (ctl >> CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_OFFSET) &
> + CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_MASK;
> + else
> + return 0;
> +
> + if (ctl) {
> + /* EMAC B source */
> + emacsel_a = false;
> + ctr_reg = CLKMGR_ALTR_EMACBCTR;
> + } else {
> + /* EMAC A source */
> + emacsel_a = true;
> + ctr_reg = CLKMGR_ALTR_EMACACTR;
> + }
> +
> + reg = CM_REG_READL(plat, ctr_reg);
> + clock = (reg & CLKMGR_ALT_EMACCTR_SRC_MASK)
> + >> CLKMGR_ALT_EMACCTR_SRC_OFFSET;
> + div = (reg & CLKMGR_ALT_EMACCTR_CNT_MASK)
> + >> CLKMGR_ALT_EMACCTR_CNT_OFFSET;
> +
> + switch (clock) {
> + case CLKMGR_CLKSRC_MAIN:
> + clock = clk_get_pll_output_hz(plat,
> + CLKMGR_MAINPLL_PLLGLOB,
> + CLKMGR_MAINPLL_PLLDIV);
> +
> + if (emacsel_a) {
> + clock /= 1 + ((CM_REG_READL(plat,
> + CLKMGR_MAINPLL_PLLOUTDIV) &
> + CLKMGR_PLLOUTDIV_C2CNT_MASK) >>
> + CLKMGR_PLLOUTDIV_C2CNT_OFFSET);
> + } else {
> + clock /= 1 + ((CM_REG_READL(plat,
> + CLKMGR_MAINPLL_PLLOUTDIV) &
> + CLKMGR_PLLOUTDIV_C3CNT_MASK) >>
> + CLKMGR_PLLOUTDIV_C3CNT_OFFSET);
> + }
> + break;
> +
> + case CLKMGR_CLKSRC_PER:
> + clock = clk_get_pll_output_hz(plat,
> + CLKMGR_PERPLL_PLLGLOB,
> + CLKMGR_PERPLL_PLLDIV);
> + if (emacsel_a) {
> + clock /= 1 + ((CM_REG_READL(plat,
> + CLKMGR_PERPLL_PLLOUTDIV) &
> + CLKMGR_PLLOUTDIV_C2CNT_MASK) >>
> + CLKMGR_PLLOUTDIV_C2CNT_OFFSET);
> + } else {
> + clock /= 1 + ((CM_REG_READL(plat,
> + CLKMGR_PERPLL_PLLOUTDIV) &
> + CLKMGR_PLLOUTDIV_C3CNT_MASK >>
> + CLKMGR_PLLOUTDIV_C3CNT_OFFSET));
> + }
> + break;
> +
> + case CLKMGR_CLKSRC_OSC1:
> + clock = cm_get_osc_clk_hz();
> + break;
> +
> + case CLKMGR_CLKSRC_INTOSC:
> + clock = cm_get_intosc_clk_hz();
> + break;
> +
> + case CLKMGR_CLKSRC_FPGA:
> + clock = cm_get_fpga_clk_hz();
> + break;
> + }
> +
> + clock /= 1 + div;
> +
> + return clock;
> +}
> +
> +static ulong socfpga_clk_get_rate(struct clk *clk)
> +{
> + struct socfpga_clk_plat *plat = dev_get_plat(clk->dev);
> +
> + switch (clk->id) {
> + case DM_MPU_CLK:
> + return clk_get_mpu_clk_hz(plat);
> + case DM_L4_MAIN_CLK:
> + return clk_get_l4_main_clk_hz(plat);
> + case DM_L4_SYS_FREE_CLK:
> + return clk_get_l4_sys_free_clk_hz(plat);
> + case DM_L4_MP_CLK:
> + return clk_get_l4_mp_clk_hz(plat);
> + case DM_L4_SP_CLK:
> +#ifndef CONFIG_TARGET_SOCFPGA_DM
> + return clk_get_l4_sp_clk_hz(plat);
> +#else
> + return 76800;
> +#endif
> + case DM_SDMMC_CLK:
> + return clk_get_sdmmc_clk_hz(plat);
> + case DM_EMAC0_CLK:
> + case DM_EMAC1_CLK:
> + case DM_EMAC2_CLK:
> + return clk_get_emac_clk_hz(plat, clk->id);
> + case DM_USB_CLK:
> + case DM_NAND_X_CLK:
> + return clk_get_l4_mp_clk_hz(plat);
> + case DM_NAND_CLK:
> + return clk_get_l4_mp_clk_hz(plat) / 4;
> + default:
> + return -ENXIO;
ENOENT please
> + }
> +}
> +
> +static int socfpga_clk_enable(struct clk *clk)
> +{
> + return 0;
> +}
> +
> +static int socfpga_clk_probe(struct udevice *dev)
> +{
> + const struct cm_config *cm_default_cfg = cm_get_default_config();
> +
> + clk_basic_init(dev, cm_default_cfg);
> +
> + return 0;
> +}
> +
> +static int socfpga_clk_of_to_plat(struct udevice *dev)
> +{
> + struct socfpga_clk_plat *plat = dev_get_plat(dev);
> + fdt_addr_t addr;
> +
> + addr = devfdt_get_addr(dev);
> + if (addr == FDT_ADDR_T_NONE)
> + return -EINVAL;
> + plat->regs = (void __iomem *)addr;
> +
> + return 0;
> +}
> +
> +static struct clk_ops socfpga_clk_ops = {
> + .enable = socfpga_clk_enable,
> + .get_rate = socfpga_clk_get_rate,
> +};
> +
> +static const struct udevice_id socfpga_clk_match[] = {
> + { .compatible = "intel,dm-clkmgr" },
> + {}
> +};
> +
> +U_BOOT_DRIVER(socfpga_dm_clk) = {
> + .name = "clk-dm",
> + .id = UCLASS_CLK,
> + .of_match = socfpga_clk_match,
> + .ops = &socfpga_clk_ops,
> + .probe = socfpga_clk_probe,
> + .of_to_plat = socfpga_clk_of_to_plat,
> + .plat_auto = sizeof(struct socfpga_clk_plat),
> +};
> diff --git a/drivers/clk/altera/clk-dm.h b/drivers/clk/altera/clk-dm.h
> new file mode 100644
> index 0000000000..89d3a92a34
> --- /dev/null
> +++ b/drivers/clk/altera/clk-dm.h
> @@ -0,0 +1,217 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (C) 2020 Intel Corporation <www.intel.com>
> + */
> +
> +#ifndef _CLK_DM_
> +#define _CLK_DM_
> +
> +#ifndef __ASSEMBLY__
> +#include <linux/bitops.h>
> +#endif
> +
> +#define CM_REG_READL(plat, reg) \
> + readl((plat)->regs + (reg))
> +
> +#define CM_REG_WRITEL(plat, data, reg) \
> + writel(data, (plat)->regs + (reg))
> +
> +#define CM_REG_CLRBITS(plat, reg, clear) \
> + clrbits_le32((plat)->regs + (reg), (clear))
> +
> +#define CM_REG_SETBITS(plat, reg, set) \
> + setbits_le32((plat)->regs + (reg), (set))
Can you use inline functions here instead?
> +struct cm_config {
> + /* main group */
> + u32 main_pll_mpuclk;
> + u32 main_pll_nocclk;
> + u32 main_pll_nocdiv;
> + u32 main_pll_pllglob;
> + u32 main_pll_plldiv;
> + u32 main_pll_plloutdiv;
> + u32 spare_1[4];
Are these reserved fields? If so, please name them as such.
> +
> + /* peripheral group */
> + u32 per_pll_emacctl;
> + u32 per_pll_gpiodiv;
> + u32 per_pll_pllglob;
> + u32 per_pll_plldiv;
> + u32 per_pll_plloutdiv;
> + u32 spare_2[4];
> +
> + /* altera group */
> + u32 alt_emacactr;
> + u32 alt_emacbctr;
> + u32 alt_emacptpctr;
> + u32 alt_gpiodbctr;
> + u32 alt_sdmmcctr;
> + u32 alt_s2fuser0ctr;
> + u32 alt_s2fuser1ctr;
> + u32 alt_psirefctr;
> +
> + /* incoming clock */
> + u32 hps_osc_clk_hz;
> + u32 fpga_clk_hz;
> + u32 spare_3[3];
> +
> + /* memory clock group */
> + u32 mem_memdiv;
> + u32 mem_pllglob;
> + u32 mem_plldiv;
> + u32 mem_plloutdiv;
> + u32 spare_4[4];
> +};
> +
> +/* Clock Manager registers */
> +#define CLKMGR_CTRL 0
> +#define CLKMGR_STAT 4
> +#define CLKMGR_TESTIOCTRL 8
> +#define CLKMGR_INTRGEN 0x0c
> +#define CLKMGR_INTRMSK 0x10
> +#define CLKMGR_INTRCLR 0x14
> +#define CLKMGR_INTRSTS 0x18
> +#define CLKMGR_INTRSTK 0x1c
> +#define CLKMGR_INTRRAW 0x20
> +
> +/* Clock Manager Main PPL group registers */
> +#define CLKMGR_MAINPLL_EN 0x24
> +#define CLKMGR_MAINPLL_ENS 0x28
> +#define CLKMGR_MAINPLL_ENR 0x2c
> +#define CLKMGR_MAINPLL_BYPASS 0x30
> +#define CLKMGR_MAINPLL_BYPASSS 0x34
> +#define CLKMGR_MAINPLL_BYPASSR 0x38
> +#define CLKMGR_MAINPLL_MPUCLK 0x3c
> +#define CLKMGR_MAINPLL_NOCCLK 0x40
> +#define CLKMGR_MAINPLL_NOCDIV 0x44
> +#define CLKMGR_MAINPLL_PLLGLOB 0x48
> +#define CLKMGR_MAINPLL_PLLCTRL 0x4c
> +#define CLKMGR_MAINPLL_PLLDIV 0x50
> +#define CLKMGR_MAINPLL_PLLOUTDIV 0x54
> +#define CLKMGR_MAINPLL_LOSTLOCK 0x58
> +
> +/* Clock Manager Peripheral PPL group registers */
> +#define CLKMGR_PERPLL_EN 0x7c
> +#define CLKMGR_PERPLL_ENS 0x80
> +#define CLKMGR_PERPLL_ENR 0x84
> +#define CLKMGR_PERPLL_BYPASS 0x88
> +#define CLKMGR_PERPLL_BYPASSS 0x8c
> +#define CLKMGR_PERPLL_BYPASSR 0x90
> +#define CLKMGR_PERPLL_EMACCTL 0x94
> +#define CLKMGR_PERPLL_GPIODIV 0x98
> +#define CLKMGR_PERPLL_PLLGLOB 0x9c
> +#define CLKMGR_PERPLL_PLLCTRL 0xa0
> +#define CLKMGR_PERPLL_PLLDIV 0xa4
> +#define CLKMGR_PERPLL_PLLOUTDIV 0xa8
> +#define CLKMGR_PERPLL_LOSTLOCK 0xac
> +
> +/* Clock Manager Altera group registers */
> +#define CLKMGR_ALTR_EMACACTR 0xd4
> +#define CLKMGR_ALTR_EMACBCTR 0xd8
> +#define CLKMGR_ALTR_EMACPTPCTR 0xdc
> +#define CLKMGR_ALTR_GPIODBCTR 0xe0
> +#define CLKMGR_ALTR_SDMMCCTR 0xe4
> +#define CLKMGR_ALTR_S2FUSER0CTR 0xe8
> +#define CLKMGR_ALTR_S2FUSER1CTR 0xec
> +#define CLKMGR_ALTR_PSIREFCTR 0xf0
> +#define CLKMGR_ALTR_EXTCNTRST 0xf4
> +
> +#define CLKMGR_CTRL_BOOTMODE BIT(0)
> +
> +#define CLKMGR_STAT_BUSY BIT(0)
> +#define CLKMGR_STAT_MAINPLL_LOCKED BIT(8)
> +#define CLKMGR_STAT_MAIN_TRANS BIT(9)
> +#define CLKMGR_STAT_PERPLL_LOCKED BIT(16)
> +#define CLKMGR_STAT_PERF_TRANS BIT(17)
> +#define CLKMGR_STAT_BOOTMODE BIT(24)
> +#define CLKMGR_STAT_BOOTCLKSRC BIT(25)
> +
> +#define CLKMGR_STAT_ALLPLL_LOCKED_MASK \
> + (CLKMGR_STAT_MAINPLL_LOCKED | CLKMGR_STAT_PERPLL_LOCKED)
> +
> +#define CLKMGR_INTER_MAINPLLLOCKED_MASK 0x00000001
> +#define CLKMGR_INTER_PERPLLLOCKED_MASK 0x00000002
> +#define CLKMGR_INTER_MAINPLLLOST_MASK 0x00000004
> +#define CLKMGR_INTER_PERPLLLOST_MASK 0x00000008
BIT()?
> +#define CLKMGR_CLKSRC_MASK GENMASK(18, 16)
> +#define CLKMGR_CLKSRC_OFFSET 16
> +#define CLKMGR_CLKSRC_MAIN 0
> +#define CLKMGR_CLKSRC_PER 1
> +#define CLKMGR_CLKSRC_OSC1 2
> +#define CLKMGR_CLKSRC_INTOSC 3
> +#define CLKMGR_CLKSRC_FPGA 4
> +#define CLKMGR_CLKCNT_MSK GENMASK(10, 0)
> +
> +#define CLKMGR_BYPASS_MAINPLL_ALL 0x7
> +#define CLKMGR_BYPASS_PERPLL_ALL 0x7f
GENMASK()?
> +#define CLKMGR_NOCDIV_L4MAIN_OFFSET 0
> +#define CLKMGR_NOCDIV_L4MPCLK_OFFSET 8
> +#define CLKMGR_NOCDIV_L4SPCLK_OFFSET 16
> +#define CLKMGR_NOCDIV_CSATCLK_OFFSET 24
> +#define CLKMGR_NOCDIV_CSTRACECLK_OFFSET 26
> +#define CLKMGR_NOCDIV_CSPDBGCLK_OFFSET 28
> +#define CLKMGR_NOCDIV_DIVIDER_MASK 0x3
> +
> +#define CLKMGR_PLLGLOB_VCO_PSRC_MASK GENMASK(17, 16)
> +#define CLKMGR_PLLGLOB_VCO_PSRC_OFFSET 16
> +#define CLKMGR_PLLGLOB_LOSTLOCK_BYPASS_EN_MASK BIT(28)
> +#define CLKMGR_PLLGLOB_CLR_LOSTLOCK_BYPASS_MASK BIT(29)
> +
> +#define CLKMGR_VCO_PSRC_EOSC1 0
> +#define CLKMGR_VCO_PSRC_INTOSC 1
> +#define CLKMGR_VCO_PSRC_F2S 2
> +
> +#define CLKMGR_PLLCTRL_BYPASS_MASK BIT(0)
> +#define CLKMGR_PLLCTRL_RST_N_MASK BIT(1)
> +
> +#define CLKMGR_PLLDIV_REFCLKDIV_MASK GENMASK(5, 0)
> +#define CLKMGR_PLLDIV_FDIV_MASK GENMASK(16, 8)
> +#define CLKMGR_PLLDIV_OUTDIV_QDIV_MASK GENMASK(26, 24)
> +#define CLKMGR_PLLDIV_RANGE_MASK GENMASK(30, 28)
> +
> +#define CLKMGR_PLLDIV_REFCLKDIV_OFFSET 0
> +#define CLKMGR_PLLDIV_FDIV_OFFSET 8
> +#define CLKMGR_PLLDIV_OUTDIV_QDIV_OFFSET 24
> +#define CLKMGR_PLLDIV_RANGE_OFFSET 28
> +
> +#define CLKMGR_PLLOUTDIV_C0CNT_MASK GENMASK(4, 0)
> +#define CLKMGR_PLLOUTDIV_C1CNT_MASK GENMASK(12, 8)
> +#define CLKMGR_PLLOUTDIV_C2CNT_MASK GENMASK(20, 16)
> +#define CLKMGR_PLLOUTDIV_C3CNT_MASK GENMASK(28, 24)
> +
> +#define CLKMGR_PLLOUTDIV_C0CNT_OFFSET 0
> +#define CLKMGR_PLLOUTDIV_C1CNT_OFFSET 8
> +#define CLKMGR_PLLOUTDIV_C2CNT_OFFSET 16
> +#define CLKMGR_PLLOUTDIV_C3CNT_OFFSET 24
> +
> +#define CLKMGR_PLLCX_EN_SET_MSK BIT(27)
> +#define CLKMGR_PLLCX_MUTE_SET_MSK BIT(28)
> +
> +#define CLKMGR_VCOCALIB_MSCNT_MASK GENMASK(23, 16)
> +#define CLKMGR_VCOCALIB_MSCNT_OFFSET 16
> +#define CLKMGR_VCOCALIB_HSCNT_MASK GENMASK(9, 0)
> +#define CLKMGR_VCOCALIB_MSCNT_CONST 100
> +#define CLKMGR_VCOCALIB_HSCNT_CONST 4
> +
> +#define CLKMGR_PLLM_MDIV_MASK GENMASK(9, 0)
> +
> +#define CLKMGR_LOSTLOCK_SET_MASK BIT(0)
> +
> +#define CLKMGR_PERPLLGRP_EN_SDMMCCLK_MASK BIT(5)
> +#define CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_OFFSET 26
> +#define CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_MASK BIT(26)
> +#define CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_OFFSET 27
> +#define CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_MASK BIT(27)
> +#define CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_OFFSET 28
> +#define CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_MASK BIT(28)
> +
> +#define CLKMGR_ALT_EMACCTR_SRC_OFFSET 16
> +#define CLKMGR_ALT_EMACCTR_SRC_MASK GENMASK(18, 16)
> +#define CLKMGR_ALT_EMACCTR_CNT_OFFSET 0
> +#define CLKMGR_ALT_EMACCTR_CNT_MASK GENMASK(10, 0)
> +
> +#define CLKMGR_ALT_EXTCNTRST_ALLCNTRST_MASK GENMASK(15, 0)
> +
> +#endif /* _CLK_DM_ */
> diff --git a/include/dt-bindings/clock/dm-clock.h b/include/dt-bindings/clock/dm-clock.h
> new file mode 100644
> index 0000000000..d624ac723c
> --- /dev/null
> +++ b/include/dt-bindings/clock/dm-clock.h
> @@ -0,0 +1,71 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (C) 2020, Intel Corporation
> + */
> +
> +#ifndef __DM_CLOCK_H
> +#define __DM_CLOCK_H
> +
> +/* fixed rate clocks */
> +#define DM_OSC1 0
> +#define DM_CB_INTOSC_HS_DIV2_CLK 1
> +#define DM_CB_INTOSC_LS_CLK 2
> +#define DM_L4_SYS_FREE_CLK 3
> +#define DM_F2S_FREE_CLK 4
> +
> +/* PLL clocks */
> +#define DM_MAIN_PLL_CLK 5
> +#define DM_MAIN_PLL_C0_CLK 6
> +#define DM_MAIN_PLL_C1_CLK 7
> +#define DM_MAIN_PLL_C2_CLK 8
> +#define DM_MAIN_PLL_C3_CLK 9
> +#define DM_PERIPH_PLL_CLK 10
> +#define DM_PERIPH_PLL_C0_CLK 11
> +#define DM_PERIPH_PLL_C1_CLK 12
> +#define DM_PERIPH_PLL_C2_CLK 13
> +#define DM_PERIPH_PLL_C3_CLK 14
> +#define DM_MPU_FREE_CLK 15
> +#define DM_MPU_CCU_CLK 16
> +#define DM_BOOT_CLK 17
> +
> +/* fixed factor clocks */
> +#define DM_L3_MAIN_FREE_CLK 18
> +#define DM_NOC_FREE_CLK 19
> +#define DM_S2F_USR0_CLK 20
> +#define DM_NOC_CLK 21
> +#define DM_EMAC_A_FREE_CLK 22
> +#define DM_EMAC_B_FREE_CLK 23
> +#define DM_EMAC_PTP_FREE_CLK 24
> +#define DM_GPIO_DB_FREE_CLK 25
> +#define DM_SDMMC_FREE_CLK 26
> +#define DM_S2F_USER0_FREE_CLK 27
> +#define DM_S2F_USER1_FREE_CLK 28
> +#define DM_PSI_REF_FREE_CLK 29
> +
> +/* Gate clocks */
> +#define DM_MPU_CLK 30
> +#define DM_MPU_PERIPH_CLK 31
> +#define DM_L4_MAIN_CLK 32
> +#define DM_L4_MP_CLK 33
> +#define DM_L4_SP_CLK 34
> +#define DM_CS_AT_CLK 35
> +#define DM_CS_TRACE_CLK 36
> +#define DM_CS_PDBG_CLK 37
> +#define DM_CS_TIMER_CLK 38
> +#define DM_S2F_USER0_CLK 39
> +#define DM_EMAC0_CLK 40
> +#define DM_EMAC1_CLK 41
> +#define DM_EMAC2_CLK 42
> +#define DM_EMAC_PTP_CLK 43
> +#define DM_GPIO_DB_CLK 44
> +#define DM_NAND_CLK 45
> +#define DM_PSI_REF_CLK 46
> +#define DM_S2F_USER1_CLK 47
> +#define DM_SDMMC_CLK 48
> +#define DM_SPI_M_CLK 49
> +#define DM_USB_CLK 50
> +#define DM_NAND_X_CLK 51
> +#define DM_NAND_ECC_CLK 52
> +#define DM_NUM_CLKS 53
> +
> +#endif /* __DM_CLOCK_H */
More information about the U-Boot
mailing list