uboot/arch/arm/mach-socfpga/clock_manager_s10.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (C) 2016-2018 Intel Corporation <www.intel.com>
   4 *
   5 */
   6
   7#include <common.h>
   8#include <asm/io.h>
   9#include <asm/arch/clock_manager.h>
  10#include <asm/arch/handoff_s10.h>
  11#include <asm/arch/system_manager.h>
  12
  13DECLARE_GLOBAL_DATA_PTR;
  14
  15static const struct socfpga_clock_manager *clock_manager_base =
  16        (struct socfpga_clock_manager *)SOCFPGA_CLKMGR_ADDRESS;
  17static const struct socfpga_system_manager *sysmgr_regs =
  18                (struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS;
  19
  20/*
  21 * function to write the bypass register which requires a poll of the
  22 * busy bit
  23 */
  24static void cm_write_bypass_mainpll(u32 val)
  25{
  26        writel(val, &clock_manager_base->main_pll.bypass);
  27        cm_wait_for_fsm();
  28}
  29
  30static void cm_write_bypass_perpll(u32 val)
  31{
  32        writel(val, &clock_manager_base->per_pll.bypass);
  33        cm_wait_for_fsm();
  34}
  35
  36/* function to write the ctrl register which requires a poll of the busy bit */
  37static void cm_write_ctrl(u32 val)
  38{
  39        writel(val, &clock_manager_base->ctrl);
  40        cm_wait_for_fsm();
  41}
  42
  43/*
  44 * Setup clocks while making no assumptions about previous state of the clocks.
  45 */
  46void cm_basic_init(const struct cm_config * const cfg)
  47{
  48        u32 mdiv, refclkdiv, mscnt, hscnt, vcocalib;
  49
  50        if (cfg == 0)
  51                return;
  52
  53        /* Put all plls in bypass */
  54        cm_write_bypass_mainpll(CLKMGR_BYPASS_MAINPLL_ALL);
  55        cm_write_bypass_perpll(CLKMGR_BYPASS_PERPLL_ALL);
  56
  57        /* setup main PLL dividers where calculate the vcocalib value */
  58        mdiv = (cfg->main_pll_fdbck >> CLKMGR_FDBCK_MDIV_OFFSET) &
  59                CLKMGR_FDBCK_MDIV_MASK;
  60        refclkdiv = (cfg->main_pll_pllglob >> CLKMGR_PLLGLOB_REFCLKDIV_OFFSET) &
  61                     CLKMGR_PLLGLOB_REFCLKDIV_MASK;
  62        mscnt = CLKMGR_MSCNT_CONST / (CLKMGR_MDIV_CONST + mdiv) / refclkdiv;
  63        hscnt = (mdiv + CLKMGR_MDIV_CONST) * mscnt / refclkdiv -
  64                CLKMGR_HSCNT_CONST;
  65        vcocalib = (hscnt & CLKMGR_VCOCALIB_HSCNT_MASK) |
  66                   ((mscnt & CLKMGR_VCOCALIB_MSCNT_MASK) <<
  67                   CLKMGR_VCOCALIB_MSCNT_OFFSET);
  68
  69        writel((cfg->main_pll_pllglob & ~CLKMGR_PLLGLOB_PD_MASK &
  70                ~CLKMGR_PLLGLOB_RST_MASK),
  71                &clock_manager_base->main_pll.pllglob);
  72        writel(cfg->main_pll_fdbck, &clock_manager_base->main_pll.fdbck);
  73        writel(vcocalib, &clock_manager_base->main_pll.vcocalib);
  74        writel(cfg->main_pll_pllc0, &clock_manager_base->main_pll.pllc0);
  75        writel(cfg->main_pll_pllc1, &clock_manager_base->main_pll.pllc1);
  76        writel(cfg->main_pll_nocdiv, &clock_manager_base->main_pll.nocdiv);
  77
  78        /* setup peripheral PLL dividers */
  79        /* calculate the vcocalib value */
  80        mdiv = (cfg->per_pll_fdbck >> CLKMGR_FDBCK_MDIV_OFFSET) &
  81                CLKMGR_FDBCK_MDIV_MASK;
  82        refclkdiv = (cfg->per_pll_pllglob >> CLKMGR_PLLGLOB_REFCLKDIV_OFFSET) &
  83                     CLKMGR_PLLGLOB_REFCLKDIV_MASK;
  84        mscnt = CLKMGR_MSCNT_CONST / (CLKMGR_MDIV_CONST + mdiv) / refclkdiv;
  85        hscnt = (mdiv + CLKMGR_MDIV_CONST) * mscnt / refclkdiv -
  86                CLKMGR_HSCNT_CONST;
  87        vcocalib = (hscnt & CLKMGR_VCOCALIB_HSCNT_MASK) |
  88                   ((mscnt & CLKMGR_VCOCALIB_MSCNT_MASK) <<
  89                   CLKMGR_VCOCALIB_MSCNT_OFFSET);
  90
  91        writel((cfg->per_pll_pllglob & ~CLKMGR_PLLGLOB_PD_MASK &
  92                ~CLKMGR_PLLGLOB_RST_MASK),
  93                &clock_manager_base->per_pll.pllglob);
  94        writel(cfg->per_pll_fdbck, &clock_manager_base->per_pll.fdbck);
  95        writel(vcocalib, &clock_manager_base->per_pll.vcocalib);
  96        writel(cfg->per_pll_pllc0, &clock_manager_base->per_pll.pllc0);
  97        writel(cfg->per_pll_pllc1, &clock_manager_base->per_pll.pllc1);
  98        writel(cfg->per_pll_emacctl, &clock_manager_base->per_pll.emacctl);
  99        writel(cfg->per_pll_gpiodiv, &clock_manager_base->per_pll.gpiodiv);
 100
 101        /* Take both PLL out of reset and power up */
 102        setbits_le32(&clock_manager_base->main_pll.pllglob,
 103                     CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK);
 104        setbits_le32(&clock_manager_base->per_pll.pllglob,
 105                     CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK);
 106
 107#define LOCKED_MASK \
 108        (CLKMGR_STAT_MAINPLL_LOCKED | \
 109        CLKMGR_STAT_PERPLL_LOCKED)
 110
 111        cm_wait_for_lock(LOCKED_MASK);
 112
 113        /*
 114         * Dividers for C2 to C9 only init after PLLs are lock. As dividers
 115         * only take effect upon value change, we shall set a maximum value as
 116         * default value.
 117         */
 118        writel(0xff, &clock_manager_base->main_pll.mpuclk);
 119        writel(0xff, &clock_manager_base->main_pll.nocclk);
 120        writel(0xff, &clock_manager_base->main_pll.cntr2clk);
 121        writel(0xff, &clock_manager_base->main_pll.cntr3clk);
 122        writel(0xff, &clock_manager_base->main_pll.cntr4clk);
 123        writel(0xff, &clock_manager_base->main_pll.cntr5clk);
 124        writel(0xff, &clock_manager_base->main_pll.cntr6clk);
 125        writel(0xff, &clock_manager_base->main_pll.cntr7clk);
 126        writel(0xff, &clock_manager_base->main_pll.cntr8clk);
 127        writel(0xff, &clock_manager_base->main_pll.cntr9clk);
 128        writel(0xff, &clock_manager_base->per_pll.cntr2clk);
 129        writel(0xff, &clock_manager_base->per_pll.cntr3clk);
 130        writel(0xff, &clock_manager_base->per_pll.cntr4clk);
 131        writel(0xff, &clock_manager_base->per_pll.cntr5clk);
 132        writel(0xff, &clock_manager_base->per_pll.cntr6clk);
 133        writel(0xff, &clock_manager_base->per_pll.cntr7clk);
 134        writel(0xff, &clock_manager_base->per_pll.cntr8clk);
 135        writel(0xff, &clock_manager_base->per_pll.cntr9clk);
 136
 137        writel(cfg->main_pll_mpuclk, &clock_manager_base->main_pll.mpuclk);
 138        writel(cfg->main_pll_nocclk, &clock_manager_base->main_pll.nocclk);
 139        writel(cfg->main_pll_cntr2clk, &clock_manager_base->main_pll.cntr2clk);
 140        writel(cfg->main_pll_cntr3clk, &clock_manager_base->main_pll.cntr3clk);
 141        writel(cfg->main_pll_cntr4clk, &clock_manager_base->main_pll.cntr4clk);
 142        writel(cfg->main_pll_cntr5clk, &clock_manager_base->main_pll.cntr5clk);
 143        writel(cfg->main_pll_cntr6clk, &clock_manager_base->main_pll.cntr6clk);
 144        writel(cfg->main_pll_cntr7clk, &clock_manager_base->main_pll.cntr7clk);
 145        writel(cfg->main_pll_cntr8clk, &clock_manager_base->main_pll.cntr8clk);
 146        writel(cfg->main_pll_cntr9clk, &clock_manager_base->main_pll.cntr9clk);
 147        writel(cfg->per_pll_cntr2clk, &clock_manager_base->per_pll.cntr2clk);
 148        writel(cfg->per_pll_cntr3clk, &clock_manager_base->per_pll.cntr3clk);
 149        writel(cfg->per_pll_cntr4clk, &clock_manager_base->per_pll.cntr4clk);
 150        writel(cfg->per_pll_cntr5clk, &clock_manager_base->per_pll.cntr5clk);
 151        writel(cfg->per_pll_cntr6clk, &clock_manager_base->per_pll.cntr6clk);
 152        writel(cfg->per_pll_cntr7clk, &clock_manager_base->per_pll.cntr7clk);
 153        writel(cfg->per_pll_cntr8clk, &clock_manager_base->per_pll.cntr8clk);
 154        writel(cfg->per_pll_cntr9clk, &clock_manager_base->per_pll.cntr9clk);
 155
 156        /* Take all PLLs out of bypass */
 157        cm_write_bypass_mainpll(0);
 158        cm_write_bypass_perpll(0);
 159
 160        /* clear safe mode / out of boot mode */
 161        cm_write_ctrl(readl(&clock_manager_base->ctrl)
 162                        & ~(CLKMGR_CTRL_SAFEMODE));
 163
 164        /* Now ungate non-hw-managed clocks */
 165        writel(~0, &clock_manager_base->main_pll.en);
 166        writel(~0, &clock_manager_base->per_pll.en);
 167
 168        /* Clear the loss of lock bits (write 1 to clear) */
 169        writel(CLKMGR_INTER_PERPLLLOST_MASK | CLKMGR_INTER_MAINPLLLOST_MASK,
 170               &clock_manager_base->intrclr);
 171}
 172
 173static unsigned long cm_get_main_vco_clk_hz(void)
 174{
 175         unsigned long fref, refdiv, mdiv, reg, vco;
 176
 177        reg = readl(&clock_manager_base->main_pll.pllglob);
 178
 179        fref = (reg >> CLKMGR_PLLGLOB_VCO_PSRC_OFFSET) &
 180                CLKMGR_PLLGLOB_VCO_PSRC_MASK;
 181        switch (fref) {
 182        case CLKMGR_VCO_PSRC_EOSC1:
 183                fref = cm_get_osc_clk_hz();
 184                break;
 185        case CLKMGR_VCO_PSRC_INTOSC:
 186                fref = cm_get_intosc_clk_hz();
 187                break;
 188        case CLKMGR_VCO_PSRC_F2S:
 189                fref = cm_get_fpga_clk_hz();
 190                break;
 191        }
 192
 193        refdiv = (reg >> CLKMGR_PLLGLOB_REFCLKDIV_OFFSET) &
 194                  CLKMGR_PLLGLOB_REFCLKDIV_MASK;
 195
 196        reg = readl(&clock_manager_base->main_pll.fdbck);
 197        mdiv = (reg >> CLKMGR_FDBCK_MDIV_OFFSET) & CLKMGR_FDBCK_MDIV_MASK;
 198
 199        vco = fref / refdiv;
 200        vco = vco * (CLKMGR_MDIV_CONST + mdiv);
 201        return vco;
 202}
 203
 204static unsigned long cm_get_per_vco_clk_hz(void)
 205{
 206        unsigned long fref, refdiv, mdiv, reg, vco;
 207
 208        reg = readl(&clock_manager_base->per_pll.pllglob);
 209
 210        fref = (reg >> CLKMGR_PLLGLOB_VCO_PSRC_OFFSET) &
 211                CLKMGR_PLLGLOB_VCO_PSRC_MASK;
 212        switch (fref) {
 213        case CLKMGR_VCO_PSRC_EOSC1:
 214                fref = cm_get_osc_clk_hz();
 215                break;
 216        case CLKMGR_VCO_PSRC_INTOSC:
 217                fref = cm_get_intosc_clk_hz();
 218                break;
 219        case CLKMGR_VCO_PSRC_F2S:
 220                fref = cm_get_fpga_clk_hz();
 221                break;
 222        }
 223
 224        refdiv = (reg >> CLKMGR_PLLGLOB_REFCLKDIV_OFFSET) &
 225                  CLKMGR_PLLGLOB_REFCLKDIV_MASK;
 226
 227        reg = readl(&clock_manager_base->per_pll.fdbck);
 228        mdiv = (reg >> CLKMGR_FDBCK_MDIV_OFFSET) & CLKMGR_FDBCK_MDIV_MASK;
 229
 230        vco = fref / refdiv;
 231        vco = vco * (CLKMGR_MDIV_CONST + mdiv);
 232        return vco;
 233}
 234
 235unsigned long cm_get_mpu_clk_hz(void)
 236{
 237        unsigned long clock = readl(&clock_manager_base->main_pll.mpuclk);
 238
 239        clock = (clock >> CLKMGR_CLKSRC_OFFSET) & CLKMGR_CLKSRC_MASK;
 240
 241        switch (clock) {
 242        case CLKMGR_CLKSRC_MAIN:
 243                clock = cm_get_main_vco_clk_hz();
 244                clock /= (readl(&clock_manager_base->main_pll.pllc0) &
 245                          CLKMGR_PLLC0_DIV_MASK);
 246                break;
 247
 248        case CLKMGR_CLKSRC_PER:
 249                clock = cm_get_per_vco_clk_hz();
 250                clock /= (readl(&clock_manager_base->per_pll.pllc0) &
 251                          CLKMGR_CLKCNT_MSK);
 252                break;
 253
 254        case CLKMGR_CLKSRC_OSC1:
 255                clock = cm_get_osc_clk_hz();
 256                break;
 257
 258        case CLKMGR_CLKSRC_INTOSC:
 259                clock = cm_get_intosc_clk_hz();
 260                break;
 261
 262        case CLKMGR_CLKSRC_FPGA:
 263                clock = cm_get_fpga_clk_hz();
 264                break;
 265        }
 266
 267        clock /= 1 + (readl(&clock_manager_base->main_pll.mpuclk) &
 268                CLKMGR_CLKCNT_MSK);
 269        return clock;
 270}
 271
 272unsigned int cm_get_l3_main_clk_hz(void)
 273{
 274        u32 clock = readl(&clock_manager_base->main_pll.nocclk);
 275
 276        clock = (clock >> CLKMGR_CLKSRC_OFFSET) & CLKMGR_CLKSRC_MASK;
 277
 278        switch (clock) {
 279        case CLKMGR_CLKSRC_MAIN:
 280                clock = cm_get_main_vco_clk_hz();
 281                clock /= (readl(&clock_manager_base->main_pll.pllc1) &
 282                          CLKMGR_PLLC0_DIV_MASK);
 283                break;
 284
 285        case CLKMGR_CLKSRC_PER:
 286                clock = cm_get_per_vco_clk_hz();
 287                clock /= (readl(&clock_manager_base->per_pll.pllc1) &
 288                          CLKMGR_CLKCNT_MSK);
 289                break;
 290
 291        case CLKMGR_CLKSRC_OSC1:
 292                clock = cm_get_osc_clk_hz();
 293                break;
 294
 295        case CLKMGR_CLKSRC_INTOSC:
 296                clock = cm_get_intosc_clk_hz();
 297                break;
 298
 299        case CLKMGR_CLKSRC_FPGA:
 300                clock = cm_get_fpga_clk_hz();
 301                break;
 302        }
 303
 304        clock /= 1 + (readl(&clock_manager_base->main_pll.nocclk) &
 305                CLKMGR_CLKCNT_MSK);
 306        return clock;
 307}
 308
 309unsigned int cm_get_mmc_controller_clk_hz(void)
 310{
 311        u32 clock = readl(&clock_manager_base->per_pll.cntr6clk);
 312
 313        clock = (clock >> CLKMGR_CLKSRC_OFFSET) & CLKMGR_CLKSRC_MASK;
 314
 315        switch (clock) {
 316        case CLKMGR_CLKSRC_MAIN:
 317                clock = cm_get_l3_main_clk_hz();
 318                clock /= 1 + (readl(&clock_manager_base->main_pll.cntr6clk) &
 319                        CLKMGR_CLKCNT_MSK);
 320                break;
 321
 322        case CLKMGR_CLKSRC_PER:
 323                clock = cm_get_l3_main_clk_hz();
 324                clock /= 1 + (readl(&clock_manager_base->per_pll.cntr6clk) &
 325                        CLKMGR_CLKCNT_MSK);
 326                break;
 327
 328        case CLKMGR_CLKSRC_OSC1:
 329                clock = cm_get_osc_clk_hz();
 330                break;
 331
 332        case CLKMGR_CLKSRC_INTOSC:
 333                clock = cm_get_intosc_clk_hz();
 334                break;
 335
 336        case CLKMGR_CLKSRC_FPGA:
 337                clock = cm_get_fpga_clk_hz();
 338                break;
 339        }
 340        return clock / 4;
 341}
 342
 343unsigned int cm_get_l4_sp_clk_hz(void)
 344{
 345        u32 clock = cm_get_l3_main_clk_hz();
 346
 347        clock /= (1 << ((readl(&clock_manager_base->main_pll.nocdiv) >>
 348                  CLKMGR_NOCDIV_L4SPCLK_OFFSET) & CLKMGR_CLKCNT_MSK));
 349        return clock;
 350}
 351
 352unsigned int cm_get_qspi_controller_clk_hz(void)
 353{
 354        return readl(&sysmgr_regs->boot_scratch_cold0);
 355}
 356
 357unsigned int cm_get_spi_controller_clk_hz(void)
 358{
 359        u32 clock = cm_get_l3_main_clk_hz();
 360
 361        clock /= (1 << ((readl(&clock_manager_base->main_pll.nocdiv) >>
 362                  CLKMGR_NOCDIV_L4MAIN_OFFSET) & CLKMGR_CLKCNT_MSK));
 363        return clock;
 364}
 365
 366unsigned int cm_get_l4_sys_free_clk_hz(void)
 367{
 368        return cm_get_l3_main_clk_hz() / 4;
 369}
 370
 371void cm_print_clock_quick_summary(void)
 372{
 373        printf("MPU         %d kHz\n", (u32)(cm_get_mpu_clk_hz() / 1000));
 374        printf("L3 main     %d kHz\n", cm_get_l3_main_clk_hz() / 1000);
 375        printf("Main VCO    %d kHz\n", (u32)(cm_get_main_vco_clk_hz() / 1000));
 376        printf("Per VCO     %d kHz\n", (u32)(cm_get_per_vco_clk_hz() / 1000));
 377        printf("EOSC1       %d kHz\n", cm_get_osc_clk_hz() / 1000);
 378        printf("HPS MMC     %d kHz\n", cm_get_mmc_controller_clk_hz() / 1000);
 379        printf("UART        %d kHz\n", cm_get_l4_sp_clk_hz() / 1000);
 380}
 381