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