uboot/arch/arm/mach-omap2/am33xx/clock_am33xx.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * clock_am33xx.c
   4 *
   5 * clocks for AM33XX based boards
   6 *
   7 * Copyright (C) 2013, Texas Instruments, Incorporated - http://www.ti.com/
   8 */
   9
  10#include <common.h>
  11#include <asm/arch/cpu.h>
  12#include <asm/arch/sys_proto.h>
  13#include <asm/arch/clock.h>
  14#include <asm/arch/hardware.h>
  15#include <asm/io.h>
  16
  17#define OSC     (V_OSCK/1000000)
  18
  19struct cm_perpll *const cmper = (struct cm_perpll *)CM_PER;
  20struct cm_wkuppll *const cmwkup = (struct cm_wkuppll *)CM_WKUP;
  21struct cm_dpll *const cmdpll = (struct cm_dpll *)CM_DPLL;
  22struct cm_rtc *const cmrtc = (struct cm_rtc *)CM_RTC;
  23
  24const struct dpll_regs dpll_mpu_regs = {
  25        .cm_clkmode_dpll        = CM_WKUP + 0x88,
  26        .cm_idlest_dpll         = CM_WKUP + 0x20,
  27        .cm_clksel_dpll         = CM_WKUP + 0x2C,
  28        .cm_div_m2_dpll         = CM_WKUP + 0xA8,
  29};
  30
  31const struct dpll_regs dpll_core_regs = {
  32        .cm_clkmode_dpll        = CM_WKUP + 0x90,
  33        .cm_idlest_dpll         = CM_WKUP + 0x5C,
  34        .cm_clksel_dpll         = CM_WKUP + 0x68,
  35        .cm_div_m4_dpll         = CM_WKUP + 0x80,
  36        .cm_div_m5_dpll         = CM_WKUP + 0x84,
  37        .cm_div_m6_dpll         = CM_WKUP + 0xD8,
  38};
  39
  40const struct dpll_regs dpll_per_regs = {
  41        .cm_clkmode_dpll        = CM_WKUP + 0x8C,
  42        .cm_idlest_dpll         = CM_WKUP + 0x70,
  43        .cm_clksel_dpll         = CM_WKUP + 0x9C,
  44        .cm_div_m2_dpll         = CM_WKUP + 0xAC,
  45};
  46
  47const struct dpll_regs dpll_ddr_regs = {
  48        .cm_clkmode_dpll        = CM_WKUP + 0x94,
  49        .cm_idlest_dpll         = CM_WKUP + 0x34,
  50        .cm_clksel_dpll         = CM_WKUP + 0x40,
  51        .cm_div_m2_dpll         = CM_WKUP + 0xA0,
  52};
  53
  54const struct dpll_regs dpll_disp_regs = {
  55        .cm_clkmode_dpll        = CM_WKUP + 0x98,
  56        .cm_idlest_dpll         = CM_WKUP + 0x48,
  57        .cm_clksel_dpll         = CM_WKUP + 0x54,
  58        .cm_div_m2_dpll         = CM_WKUP + 0xA4,
  59};
  60
  61struct dpll_params dpll_mpu_opp100 = {
  62                CONFIG_SYS_MPUCLK, OSC-1, 1, -1, -1, -1, -1};
  63const struct dpll_params dpll_core_opp100 = {
  64                1000, OSC-1, -1, -1, 10, 8, 4};
  65
  66const struct dpll_params dpll_mpu_opp[NUM_CRYSTAL_FREQ][NUM_OPPS] = {
  67        {       /* 19.2 MHz */
  68                {125, 3, 2, -1, -1, -1, -1},    /* OPP 50 */
  69                {-1, -1, -1, -1, -1, -1, -1},   /* OPP RESERVED */
  70                {125, 3, 1, -1, -1, -1, -1},    /* OPP 100 */
  71                {150, 3, 1, -1, -1, -1, -1},    /* OPP 120 */
  72                {125, 2, 1, -1, -1, -1, -1},    /* OPP TB */
  73                {625, 11, 1, -1, -1, -1, -1}    /* OPP NT */
  74        },
  75        {       /* 24 MHz */
  76                {25, 0, 2, -1, -1, -1, -1},     /* OPP 50 */
  77                {-1, -1, -1, -1, -1, -1, -1},   /* OPP RESERVED */
  78                {25, 0, 1, -1, -1, -1, -1},     /* OPP 100 */
  79                {30, 0, 1, -1, -1, -1, -1},     /* OPP 120 */
  80                {100, 3, 1, -1, -1, -1, -1},    /* OPP TB */
  81                {125, 2, 1, -1, -1, -1, -1}     /* OPP NT */
  82        },
  83        {       /* 25 MHz */
  84                {24, 0, 2, -1, -1, -1, -1},     /* OPP 50 */
  85                {-1, -1, -1, -1, -1, -1, -1},   /* OPP RESERVED */
  86                {24, 0, 1, -1, -1, -1, -1},     /* OPP 100 */
  87                {144, 4, 1, -1, -1, -1, -1},    /* OPP 120 */
  88                {32, 0, 1, -1, -1, -1, -1},     /* OPP TB */
  89                {40, 0, 1, -1, -1, -1, -1}      /* OPP NT */
  90        },
  91        {       /* 26 MHz */
  92                {300, 12, 2, -1, -1, -1, -1},   /* OPP 50 */
  93                {-1, -1, -1, -1, -1, -1, -1},   /* OPP RESERVED */
  94                {300, 12, 1, -1, -1, -1, -1},   /* OPP 100 */
  95                {360, 12, 1, -1, -1, -1, -1},   /* OPP 120 */
  96                {400, 12, 1, -1, -1, -1, -1},   /* OPP TB */
  97                {500, 12, 1, -1, -1, -1, -1}    /* OPP NT */
  98        },
  99};
 100
 101const struct dpll_params dpll_core_1000MHz[NUM_CRYSTAL_FREQ] = {
 102                {625, 11, -1, -1, 10, 8, 4},    /* 19.2 MHz */
 103                {125, 2, -1, -1, 10, 8, 4},     /* 24 MHz */
 104                {40, 0, -1, -1, 10, 8, 4},      /* 25 MHz */
 105                {500, 12, -1, -1, 10, 8, 4}     /* 26 MHz */
 106};
 107
 108const struct dpll_params dpll_per_192MHz[NUM_CRYSTAL_FREQ] = {
 109                {400, 7, 5, -1, -1, -1, -1},    /* 19.2 MHz */
 110                {400, 9, 5, -1, -1, -1, -1},    /* 24 MHz */
 111                {384, 9, 5, -1, -1, -1, -1},    /* 25 MHz */
 112                {480, 12, 5, -1, -1, -1, -1}    /* 26 MHz */
 113};
 114
 115const struct dpll_params dpll_ddr3_303MHz[NUM_CRYSTAL_FREQ] = {
 116                {505, 15, 2, -1, -1, -1, -1}, /*19.2*/
 117                {101, 3, 2, -1, -1, -1, -1}, /* 24 MHz */
 118                {303, 24, 1, -1, -1, -1, -1}, /* 25 MHz */
 119                {303, 12, 2, -1, -1, -1, -1}  /* 26 MHz */
 120};
 121
 122const struct dpll_params dpll_ddr3_400MHz[NUM_CRYSTAL_FREQ] = {
 123                {125, 5, 1, -1, -1, -1, -1}, /*19.2*/
 124                {50, 2, 1, -1, -1, -1, -1}, /* 24 MHz */
 125                {16, 0, 1, -1, -1, -1, -1}, /* 25 MHz */
 126                {200, 12, 1, -1, -1, -1, -1}  /* 26 MHz */
 127};
 128
 129const struct dpll_params dpll_ddr2_266MHz[NUM_CRYSTAL_FREQ] = {
 130                {665, 47, 1, -1, -1, -1, -1}, /*19.2*/
 131                {133, 11, 1, -1, -1, -1, -1}, /* 24 MHz */
 132                {266, 24, 1, -1, -1, -1, -1}, /* 25 MHz */
 133                {133, 12, 1, -1, -1, -1, -1}  /* 26 MHz */
 134};
 135
 136__weak const struct dpll_params *get_dpll_mpu_params(void)
 137{
 138        return &dpll_mpu_opp100;
 139}
 140
 141const struct dpll_params *get_dpll_core_params(void)
 142{
 143        int ind = get_sys_clk_index();
 144
 145        return &dpll_core_1000MHz[ind];
 146}
 147
 148const struct dpll_params *get_dpll_per_params(void)
 149{
 150        int ind = get_sys_clk_index();
 151
 152        return &dpll_per_192MHz[ind];
 153}
 154
 155void setup_clocks_for_console(void)
 156{
 157        clrsetbits_le32(&cmwkup->wkclkstctrl, CD_CLKCTRL_CLKTRCTRL_MASK,
 158                        CD_CLKCTRL_CLKTRCTRL_SW_WKUP <<
 159                        CD_CLKCTRL_CLKTRCTRL_SHIFT);
 160
 161        clrsetbits_le32(&cmper->l4hsclkstctrl, CD_CLKCTRL_CLKTRCTRL_MASK,
 162                        CD_CLKCTRL_CLKTRCTRL_SW_WKUP <<
 163                        CD_CLKCTRL_CLKTRCTRL_SHIFT);
 164
 165        clrsetbits_le32(&cmwkup->wkup_uart0ctrl,
 166                        MODULE_CLKCTRL_MODULEMODE_MASK,
 167                        MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN <<
 168                        MODULE_CLKCTRL_MODULEMODE_SHIFT);
 169        clrsetbits_le32(&cmper->uart1clkctrl,
 170                        MODULE_CLKCTRL_MODULEMODE_MASK,
 171                        MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN <<
 172                        MODULE_CLKCTRL_MODULEMODE_SHIFT);
 173        clrsetbits_le32(&cmper->uart2clkctrl,
 174                        MODULE_CLKCTRL_MODULEMODE_MASK,
 175                        MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN <<
 176                        MODULE_CLKCTRL_MODULEMODE_SHIFT);
 177        clrsetbits_le32(&cmper->uart3clkctrl,
 178                        MODULE_CLKCTRL_MODULEMODE_MASK,
 179                        MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN <<
 180                        MODULE_CLKCTRL_MODULEMODE_SHIFT);
 181        clrsetbits_le32(&cmper->uart4clkctrl,
 182                        MODULE_CLKCTRL_MODULEMODE_MASK,
 183                        MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN <<
 184                        MODULE_CLKCTRL_MODULEMODE_SHIFT);
 185        clrsetbits_le32(&cmper->uart5clkctrl,
 186                        MODULE_CLKCTRL_MODULEMODE_MASK,
 187                        MODULE_CLKCTRL_MODULEMODE_SW_EXPLICIT_EN <<
 188                        MODULE_CLKCTRL_MODULEMODE_SHIFT);
 189}
 190
 191void enable_basic_clocks(void)
 192{
 193        u32 *const clk_domains[] = {
 194                &cmper->l3clkstctrl,
 195                &cmper->l4fwclkstctrl,
 196                &cmper->l3sclkstctrl,
 197                &cmper->l4lsclkstctrl,
 198                &cmwkup->wkclkstctrl,
 199                &cmper->emiffwclkctrl,
 200                &cmrtc->clkstctrl,
 201                0
 202        };
 203
 204        u32 *const clk_modules_explicit_en[] = {
 205                &cmper->l3clkctrl,
 206                &cmper->l4lsclkctrl,
 207                &cmper->l4fwclkctrl,
 208                &cmwkup->wkl4wkclkctrl,
 209                &cmper->l3instrclkctrl,
 210                &cmper->l4hsclkctrl,
 211                &cmwkup->wkgpio0clkctrl,
 212                &cmwkup->wkctrlclkctrl,
 213                &cmper->timer2clkctrl,
 214                &cmper->gpmcclkctrl,
 215                &cmper->elmclkctrl,
 216                &cmper->mmc0clkctrl,
 217                &cmper->mmc1clkctrl,
 218                &cmwkup->wkup_i2c0ctrl,
 219                &cmper->gpio1clkctrl,
 220                &cmper->gpio2clkctrl,
 221                &cmper->gpio3clkctrl,
 222                &cmper->i2c1clkctrl,
 223                &cmper->cpgmac0clkctrl,
 224                &cmper->spi0clkctrl,
 225                &cmrtc->rtcclkctrl,
 226                &cmper->usb0clkctrl,
 227                &cmper->emiffwclkctrl,
 228                &cmper->emifclkctrl,
 229                0
 230        };
 231
 232        do_enable_clocks(clk_domains, clk_modules_explicit_en, 1);
 233
 234        /* Select the Master osc 24 MHZ as Timer2 clock source */
 235        writel(0x1, &cmdpll->clktimer2clk);
 236}
 237
 238/*
 239 * Enable Spread Spectrum for the MPU by calculating the required
 240 * values and setting the registers accordingly.
 241 * @param permille The spreading in permille (10th of a percent)
 242 */
 243void set_mpu_spreadspectrum(int permille)
 244{
 245        u32 multiplier_m;
 246        u32 predivider_n;
 247        u32 cm_clksel_dpll_mpu;
 248        u32 cm_clkmode_dpll_mpu;
 249        u32 ref_clock;
 250        u32 pll_bandwidth;
 251        u32 mod_freq_divider;
 252        u32 exponent;
 253        u32 mantissa;
 254        u32 delta_m_step;
 255
 256        printf("Enabling Spread Spectrum of %d permille for MPU\n",
 257               permille);
 258
 259        /* Read PLL parameter m and n */
 260        cm_clksel_dpll_mpu = readl(&cmwkup->clkseldpllmpu);
 261        multiplier_m = (cm_clksel_dpll_mpu >> 8) & 0x3FF;
 262        predivider_n = cm_clksel_dpll_mpu & 0x7F;
 263
 264        /*
 265         * Calculate reference clock (clock after pre-divider),
 266         * its max. PLL bandwidth,
 267         * and resulting mod_freq_divider
 268         */
 269        ref_clock = V_OSCK / (predivider_n + 1);
 270        pll_bandwidth = ref_clock / 70;
 271        mod_freq_divider = ref_clock / (4 * pll_bandwidth);
 272
 273        /* Calculate Mantissa/Exponent */
 274        exponent = 0;
 275        mantissa = mod_freq_divider;
 276        while ((mantissa > 127) && (exponent < 7)) {
 277                exponent++;
 278                mantissa /= 2;
 279        }
 280        if (mantissa > 127)
 281                mantissa = 127;
 282
 283        mod_freq_divider = mantissa << exponent;
 284
 285        /*
 286         * Calculate Modulation steps
 287         * As we use Downspread only, the spread is twice the value of
 288         * permille, so Div2!
 289         * As it takes the value in percent, divide by ten!
 290         */
 291        delta_m_step = ((u32)((multiplier_m * permille) / 10 / 2)) << 18;
 292        delta_m_step /= 100;
 293        delta_m_step /= mod_freq_divider;
 294        if (delta_m_step > 0xFFFFF)
 295                delta_m_step = 0xFFFFF;
 296
 297        /* Setup Spread Spectrum */
 298        writel(delta_m_step, &cmwkup->sscdeltamstepdllmpu);
 299        writel((exponent << 8) | mantissa, &cmwkup->sscmodfreqdivdpllmpu);
 300        cm_clkmode_dpll_mpu = readl(&cmwkup->clkmoddpllmpu);
 301        /* clear all SSC flags */
 302        cm_clkmode_dpll_mpu &= ~(0xF << CM_CLKMODE_DPLL_SSC_EN_SHIFT);
 303        /* enable SSC with Downspread only */
 304        cm_clkmode_dpll_mpu |=  CM_CLKMODE_DPLL_SSC_EN_MASK |
 305                                CM_CLKMODE_DPLL_SSC_DOWNSPREAD_MASK;
 306        writel(cm_clkmode_dpll_mpu, &cmwkup->clkmoddpllmpu);
 307        while (!(readl(&cmwkup->clkmoddpllmpu) & 0x2000))
 308                ;
 309}
 310