uboot/arch/arm/mach-s5pc1xx/clock.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2009 Samsung Electronics
   4 * Minkyu Kang <mk7.kang@samsung.com>
   5 * Heungjun Kim <riverful.kim@samsung.com>
   6 */
   7
   8#include <common.h>
   9#include <asm/io.h>
  10#include <asm/arch/clock.h>
  11#include <asm/arch/clk.h>
  12
  13#define CLK_M   0
  14#define CLK_D   1
  15#define CLK_P   2
  16
  17#ifndef CONFIG_SYS_CLK_FREQ_C100
  18#define CONFIG_SYS_CLK_FREQ_C100        12000000
  19#endif
  20#ifndef CONFIG_SYS_CLK_FREQ_C110
  21#define CONFIG_SYS_CLK_FREQ_C110        24000000
  22#endif
  23
  24/* s5pc110: return pll clock frequency */
  25static unsigned long s5pc100_get_pll_clk(int pllreg)
  26{
  27        struct s5pc100_clock *clk =
  28                (struct s5pc100_clock *)samsung_get_base_clock();
  29        unsigned long r, m, p, s, mask, fout;
  30        unsigned int freq;
  31
  32        switch (pllreg) {
  33        case APLL:
  34                r = readl(&clk->apll_con);
  35                break;
  36        case MPLL:
  37                r = readl(&clk->mpll_con);
  38                break;
  39        case EPLL:
  40                r = readl(&clk->epll_con);
  41                break;
  42        case HPLL:
  43                r = readl(&clk->hpll_con);
  44                break;
  45        default:
  46                printf("Unsupported PLL (%d)\n", pllreg);
  47                return 0;
  48        }
  49
  50        /*
  51         * APLL_CON: MIDV [25:16]
  52         * MPLL_CON: MIDV [23:16]
  53         * EPLL_CON: MIDV [23:16]
  54         * HPLL_CON: MIDV [23:16]
  55         */
  56        if (pllreg == APLL)
  57                mask = 0x3ff;
  58        else
  59                mask = 0x0ff;
  60
  61        m = (r >> 16) & mask;
  62
  63        /* PDIV [13:8] */
  64        p = (r >> 8) & 0x3f;
  65        /* SDIV [2:0] */
  66        s = r & 0x7;
  67
  68        /* FOUT = MDIV * FIN / (PDIV * 2^SDIV) */
  69        freq = CONFIG_SYS_CLK_FREQ_C100;
  70        fout = m * (freq / (p * (1 << s)));
  71
  72        return fout;
  73}
  74
  75/* s5pc100: return pll clock frequency */
  76static unsigned long s5pc110_get_pll_clk(int pllreg)
  77{
  78        struct s5pc110_clock *clk =
  79                (struct s5pc110_clock *)samsung_get_base_clock();
  80        unsigned long r, m, p, s, mask, fout;
  81        unsigned int freq;
  82
  83        switch (pllreg) {
  84        case APLL:
  85                r = readl(&clk->apll_con);
  86                break;
  87        case MPLL:
  88                r = readl(&clk->mpll_con);
  89                break;
  90        case EPLL:
  91                r = readl(&clk->epll_con);
  92                break;
  93        case VPLL:
  94                r = readl(&clk->vpll_con);
  95                break;
  96        default:
  97                printf("Unsupported PLL (%d)\n", pllreg);
  98                return 0;
  99        }
 100
 101        /*
 102         * APLL_CON: MIDV [25:16]
 103         * MPLL_CON: MIDV [25:16]
 104         * EPLL_CON: MIDV [24:16]
 105         * VPLL_CON: MIDV [24:16]
 106         */
 107        if (pllreg == APLL || pllreg == MPLL)
 108                mask = 0x3ff;
 109        else
 110                mask = 0x1ff;
 111
 112        m = (r >> 16) & mask;
 113
 114        /* PDIV [13:8] */
 115        p = (r >> 8) & 0x3f;
 116        /* SDIV [2:0] */
 117        s = r & 0x7;
 118
 119        freq = CONFIG_SYS_CLK_FREQ_C110;
 120        if (pllreg == APLL) {
 121                if (s < 1)
 122                        s = 1;
 123                /* FOUT = MDIV * FIN / (PDIV * 2^(SDIV - 1)) */
 124                fout = m * (freq / (p * (1 << (s - 1))));
 125        } else
 126                /* FOUT = MDIV * FIN / (PDIV * 2^SDIV) */
 127                fout = m * (freq / (p * (1 << s)));
 128
 129        return fout;
 130}
 131
 132/* s5pc110: return ARM clock frequency */
 133static unsigned long s5pc110_get_arm_clk(void)
 134{
 135        struct s5pc110_clock *clk =
 136                (struct s5pc110_clock *)samsung_get_base_clock();
 137        unsigned long div;
 138        unsigned long dout_apll, armclk;
 139        unsigned int apll_ratio;
 140
 141        div = readl(&clk->div0);
 142
 143        /* APLL_RATIO: [2:0] */
 144        apll_ratio = div & 0x7;
 145
 146        dout_apll = get_pll_clk(APLL) / (apll_ratio + 1);
 147        armclk = dout_apll;
 148
 149        return armclk;
 150}
 151
 152/* s5pc100: return ARM clock frequency */
 153static unsigned long s5pc100_get_arm_clk(void)
 154{
 155        struct s5pc100_clock *clk =
 156                (struct s5pc100_clock *)samsung_get_base_clock();
 157        unsigned long div;
 158        unsigned long dout_apll, armclk;
 159        unsigned int apll_ratio, arm_ratio;
 160
 161        div = readl(&clk->div0);
 162
 163        /* ARM_RATIO: [6:4] */
 164        arm_ratio = (div >> 4) & 0x7;
 165        /* APLL_RATIO: [0] */
 166        apll_ratio = div & 0x1;
 167
 168        dout_apll = get_pll_clk(APLL) / (apll_ratio + 1);
 169        armclk = dout_apll / (arm_ratio + 1);
 170
 171        return armclk;
 172}
 173
 174/* s5pc100: return HCLKD0 frequency */
 175static unsigned long get_hclk(void)
 176{
 177        struct s5pc100_clock *clk =
 178                (struct s5pc100_clock *)samsung_get_base_clock();
 179        unsigned long hclkd0;
 180        uint div, d0_bus_ratio;
 181
 182        div = readl(&clk->div0);
 183        /* D0_BUS_RATIO: [10:8] */
 184        d0_bus_ratio = (div >> 8) & 0x7;
 185
 186        hclkd0 = get_arm_clk() / (d0_bus_ratio + 1);
 187
 188        return hclkd0;
 189}
 190
 191/* s5pc100: return PCLKD1 frequency */
 192static unsigned long get_pclkd1(void)
 193{
 194        struct s5pc100_clock *clk =
 195                (struct s5pc100_clock *)samsung_get_base_clock();
 196        unsigned long d1_bus, pclkd1;
 197        uint div, d1_bus_ratio, pclkd1_ratio;
 198
 199        div = readl(&clk->div0);
 200        /* D1_BUS_RATIO: [14:12] */
 201        d1_bus_ratio = (div >> 12) & 0x7;
 202        /* PCLKD1_RATIO: [18:16] */
 203        pclkd1_ratio = (div >> 16) & 0x7;
 204
 205        /* ASYNC Mode */
 206        d1_bus = get_pll_clk(MPLL) / (d1_bus_ratio + 1);
 207        pclkd1 = d1_bus / (pclkd1_ratio + 1);
 208
 209        return pclkd1;
 210}
 211
 212/* s5pc110: return HCLKs frequency */
 213static unsigned long get_hclk_sys(int dom)
 214{
 215        struct s5pc110_clock *clk =
 216                (struct s5pc110_clock *)samsung_get_base_clock();
 217        unsigned long hclk;
 218        unsigned int div;
 219        unsigned int offset;
 220        unsigned int hclk_sys_ratio;
 221
 222        if (dom == CLK_M)
 223                return get_hclk();
 224
 225        div = readl(&clk->div0);
 226
 227        /*
 228         * HCLK_MSYS_RATIO: [10:8]
 229         * HCLK_DSYS_RATIO: [19:16]
 230         * HCLK_PSYS_RATIO: [27:24]
 231         */
 232        offset = 8 + (dom << 0x3);
 233
 234        hclk_sys_ratio = (div >> offset) & 0xf;
 235
 236        hclk = get_pll_clk(MPLL) / (hclk_sys_ratio + 1);
 237
 238        return hclk;
 239}
 240
 241/* s5pc110: return PCLKs frequency */
 242static unsigned long get_pclk_sys(int dom)
 243{
 244        struct s5pc110_clock *clk =
 245                (struct s5pc110_clock *)samsung_get_base_clock();
 246        unsigned long pclk;
 247        unsigned int div;
 248        unsigned int offset;
 249        unsigned int pclk_sys_ratio;
 250
 251        div = readl(&clk->div0);
 252
 253        /*
 254         * PCLK_MSYS_RATIO: [14:12]
 255         * PCLK_DSYS_RATIO: [22:20]
 256         * PCLK_PSYS_RATIO: [30:28]
 257         */
 258        offset = 12 + (dom << 0x3);
 259
 260        pclk_sys_ratio = (div >> offset) & 0x7;
 261
 262        pclk = get_hclk_sys(dom) / (pclk_sys_ratio + 1);
 263
 264        return pclk;
 265}
 266
 267/* s5pc110: return peripheral clock frequency */
 268static unsigned long s5pc110_get_pclk(void)
 269{
 270        return get_pclk_sys(CLK_P);
 271}
 272
 273/* s5pc100: return peripheral clock frequency */
 274static unsigned long s5pc100_get_pclk(void)
 275{
 276        return get_pclkd1();
 277}
 278
 279/* s5pc1xx: return uart clock frequency */
 280static unsigned long s5pc1xx_get_uart_clk(int dev_index)
 281{
 282        if (cpu_is_s5pc110())
 283                return s5pc110_get_pclk();
 284        else
 285                return s5pc100_get_pclk();
 286}
 287
 288/* s5pc1xx: return pwm clock frequency */
 289static unsigned long s5pc1xx_get_pwm_clk(void)
 290{
 291        if (cpu_is_s5pc110())
 292                return s5pc110_get_pclk();
 293        else
 294                return s5pc100_get_pclk();
 295}
 296
 297unsigned long get_pll_clk(int pllreg)
 298{
 299        if (cpu_is_s5pc110())
 300                return s5pc110_get_pll_clk(pllreg);
 301        else
 302                return s5pc100_get_pll_clk(pllreg);
 303}
 304
 305unsigned long get_arm_clk(void)
 306{
 307        if (cpu_is_s5pc110())
 308                return s5pc110_get_arm_clk();
 309        else
 310                return s5pc100_get_arm_clk();
 311}
 312
 313unsigned long get_pwm_clk(void)
 314{
 315        return s5pc1xx_get_pwm_clk();
 316}
 317
 318unsigned long get_uart_clk(int dev_index)
 319{
 320        return s5pc1xx_get_uart_clk(dev_index);
 321}
 322
 323void set_mmc_clk(int dev_index, unsigned int div)
 324{
 325        /* Do NOTHING */
 326}
 327