linux/drivers/clk/mvebu/clk-core.c
<<
>>
Prefs
   1/*
   2 * Marvell EBU clock core handling defined at reset
   3 *
   4 * Copyright (C) 2012 Marvell
   5 *
   6 * Gregory CLEMENT <gregory.clement@free-electrons.com>
   7 * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
   8 *
   9 * This file is licensed under the terms of the GNU General Public
  10 * License version 2.  This program is licensed "as is" without any
  11 * warranty of any kind, whether express or implied.
  12 */
  13#include <linux/kernel.h>
  14#include <linux/clk.h>
  15#include <linux/clkdev.h>
  16#include <linux/clk-provider.h>
  17#include <linux/of_address.h>
  18#include <linux/io.h>
  19#include <linux/of.h>
  20#include "clk-core.h"
  21
  22struct core_ratio {
  23        int id;
  24        const char *name;
  25};
  26
  27struct core_clocks {
  28        u32 (*get_tclk_freq)(void __iomem *sar);
  29        u32 (*get_cpu_freq)(void __iomem *sar);
  30        void (*get_clk_ratio)(void __iomem *sar, int id, int *mult, int *div);
  31        const struct core_ratio *ratios;
  32        int num_ratios;
  33};
  34
  35static struct clk_onecell_data clk_data;
  36
  37static void __init mvebu_clk_core_setup(struct device_node *np,
  38                                 struct core_clocks *coreclk)
  39{
  40        const char *tclk_name = "tclk";
  41        const char *cpuclk_name = "cpuclk";
  42        void __iomem *base;
  43        unsigned long rate;
  44        int n;
  45
  46        base = of_iomap(np, 0);
  47        if (WARN_ON(!base))
  48                return;
  49
  50        /*
  51         * Allocate struct for TCLK, cpu clk, and core ratio clocks
  52         */
  53        clk_data.clk_num = 2 + coreclk->num_ratios;
  54        clk_data.clks = kzalloc(clk_data.clk_num * sizeof(struct clk *),
  55                                GFP_KERNEL);
  56        if (WARN_ON(!clk_data.clks))
  57                return;
  58
  59        /*
  60         * Register TCLK
  61         */
  62        of_property_read_string_index(np, "clock-output-names", 0,
  63                                      &tclk_name);
  64        rate = coreclk->get_tclk_freq(base);
  65        clk_data.clks[0] = clk_register_fixed_rate(NULL, tclk_name, NULL,
  66                                                   CLK_IS_ROOT, rate);
  67        WARN_ON(IS_ERR(clk_data.clks[0]));
  68
  69        /*
  70         * Register CPU clock
  71         */
  72        of_property_read_string_index(np, "clock-output-names", 1,
  73                                      &cpuclk_name);
  74        rate = coreclk->get_cpu_freq(base);
  75        clk_data.clks[1] = clk_register_fixed_rate(NULL, cpuclk_name, NULL,
  76                                                   CLK_IS_ROOT, rate);
  77        WARN_ON(IS_ERR(clk_data.clks[1]));
  78
  79        /*
  80         * Register fixed-factor clocks derived from CPU clock
  81         */
  82        for (n = 0; n < coreclk->num_ratios; n++) {
  83                const char *rclk_name = coreclk->ratios[n].name;
  84                int mult, div;
  85
  86                of_property_read_string_index(np, "clock-output-names",
  87                                              2+n, &rclk_name);
  88                coreclk->get_clk_ratio(base, coreclk->ratios[n].id,
  89                                       &mult, &div);
  90                clk_data.clks[2+n] = clk_register_fixed_factor(NULL, rclk_name,
  91                                       cpuclk_name, 0, mult, div);
  92                WARN_ON(IS_ERR(clk_data.clks[2+n]));
  93        };
  94
  95        /*
  96         * SAR register isn't needed anymore
  97         */
  98        iounmap(base);
  99
 100        of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
 101}
 102
 103#ifdef CONFIG_MACH_ARMADA_370_XP
 104/*
 105 * Armada 370/XP Sample At Reset is a 64 bit bitfiled split in two
 106 * register of 32 bits
 107 */
 108
 109#define SARL                                0   /* Low part [0:31] */
 110#define     SARL_AXP_PCLK_FREQ_OPT          21
 111#define     SARL_AXP_PCLK_FREQ_OPT_MASK     0x7
 112#define     SARL_A370_PCLK_FREQ_OPT         11
 113#define     SARL_A370_PCLK_FREQ_OPT_MASK    0xF
 114#define     SARL_AXP_FAB_FREQ_OPT           24
 115#define     SARL_AXP_FAB_FREQ_OPT_MASK      0xF
 116#define     SARL_A370_FAB_FREQ_OPT          15
 117#define     SARL_A370_FAB_FREQ_OPT_MASK     0x1F
 118#define     SARL_A370_TCLK_FREQ_OPT         20
 119#define     SARL_A370_TCLK_FREQ_OPT_MASK    0x1
 120#define SARH                                4   /* High part [32:63] */
 121#define     SARH_AXP_PCLK_FREQ_OPT          (52-32)
 122#define     SARH_AXP_PCLK_FREQ_OPT_MASK     0x1
 123#define     SARH_AXP_PCLK_FREQ_OPT_SHIFT    3
 124#define     SARH_AXP_FAB_FREQ_OPT           (51-32)
 125#define     SARH_AXP_FAB_FREQ_OPT_MASK      0x1
 126#define     SARH_AXP_FAB_FREQ_OPT_SHIFT     4
 127
 128static const u32 __initconst armada_370_tclk_frequencies[] = {
 129        166000000,
 130        200000000,
 131};
 132
 133static u32 __init armada_370_get_tclk_freq(void __iomem *sar)
 134{
 135        u8 tclk_freq_select = 0;
 136
 137        tclk_freq_select = ((readl(sar) >> SARL_A370_TCLK_FREQ_OPT) &
 138                            SARL_A370_TCLK_FREQ_OPT_MASK);
 139        return armada_370_tclk_frequencies[tclk_freq_select];
 140}
 141
 142static const u32 __initconst armada_370_cpu_frequencies[] = {
 143        400000000,
 144        533000000,
 145        667000000,
 146        800000000,
 147        1000000000,
 148        1067000000,
 149        1200000000,
 150};
 151
 152static u32 __init armada_370_get_cpu_freq(void __iomem *sar)
 153{
 154        u32 cpu_freq;
 155        u8 cpu_freq_select = 0;
 156
 157        cpu_freq_select = ((readl(sar) >> SARL_A370_PCLK_FREQ_OPT) &
 158                           SARL_A370_PCLK_FREQ_OPT_MASK);
 159        if (cpu_freq_select >= ARRAY_SIZE(armada_370_cpu_frequencies)) {
 160                pr_err("CPU freq select unsupported %d\n", cpu_freq_select);
 161                cpu_freq = 0;
 162        } else
 163                cpu_freq = armada_370_cpu_frequencies[cpu_freq_select];
 164
 165        return cpu_freq;
 166}
 167
 168enum { A370_XP_NBCLK, A370_XP_HCLK, A370_XP_DRAMCLK };
 169
 170static const struct core_ratio __initconst armada_370_xp_core_ratios[] = {
 171        { .id = A370_XP_NBCLK,   .name = "nbclk" },
 172        { .id = A370_XP_HCLK,    .name = "hclk" },
 173        { .id = A370_XP_DRAMCLK, .name = "dramclk" },
 174};
 175
 176static const int __initconst armada_370_xp_nbclk_ratios[32][2] = {
 177        {0, 1}, {1, 2}, {2, 2}, {2, 2},
 178        {1, 2}, {1, 2}, {1, 1}, {2, 3},
 179        {0, 1}, {1, 2}, {2, 4}, {0, 1},
 180        {1, 2}, {0, 1}, {0, 1}, {2, 2},
 181        {0, 1}, {0, 1}, {0, 1}, {1, 1},
 182        {2, 3}, {0, 1}, {0, 1}, {0, 1},
 183        {0, 1}, {0, 1}, {0, 1}, {1, 1},
 184        {0, 1}, {0, 1}, {0, 1}, {0, 1},
 185};
 186
 187static const int __initconst armada_370_xp_hclk_ratios[32][2] = {
 188        {0, 1}, {1, 2}, {2, 6}, {2, 3},
 189        {1, 3}, {1, 4}, {1, 2}, {2, 6},
 190        {0, 1}, {1, 6}, {2, 10}, {0, 1},
 191        {1, 4}, {0, 1}, {0, 1}, {2, 5},
 192        {0, 1}, {0, 1}, {0, 1}, {1, 2},
 193        {2, 6}, {0, 1}, {0, 1}, {0, 1},
 194        {0, 1}, {0, 1}, {0, 1}, {1, 1},
 195        {0, 1}, {0, 1}, {0, 1}, {0, 1},
 196};
 197
 198static const int __initconst armada_370_xp_dramclk_ratios[32][2] = {
 199        {0, 1}, {1, 2}, {2, 3}, {2, 3},
 200        {1, 3}, {1, 2}, {1, 2}, {2, 6},
 201        {0, 1}, {1, 3}, {2, 5}, {0, 1},
 202        {1, 4}, {0, 1}, {0, 1}, {2, 5},
 203        {0, 1}, {0, 1}, {0, 1}, {1, 1},
 204        {2, 3}, {0, 1}, {0, 1}, {0, 1},
 205        {0, 1}, {0, 1}, {0, 1}, {1, 1},
 206        {0, 1}, {0, 1}, {0, 1}, {0, 1},
 207};
 208
 209static void __init armada_370_xp_get_clk_ratio(u32 opt,
 210        void __iomem *sar, int id, int *mult, int *div)
 211{
 212        switch (id) {
 213        case A370_XP_NBCLK:
 214                *mult = armada_370_xp_nbclk_ratios[opt][0];
 215                *div = armada_370_xp_nbclk_ratios[opt][1];
 216                break;
 217        case A370_XP_HCLK:
 218                *mult = armada_370_xp_hclk_ratios[opt][0];
 219                *div = armada_370_xp_hclk_ratios[opt][1];
 220                break;
 221        case A370_XP_DRAMCLK:
 222                *mult = armada_370_xp_dramclk_ratios[opt][0];
 223                *div = armada_370_xp_dramclk_ratios[opt][1];
 224                break;
 225        }
 226}
 227
 228static void __init armada_370_get_clk_ratio(
 229        void __iomem *sar, int id, int *mult, int *div)
 230{
 231        u32 opt = ((readl(sar) >> SARL_A370_FAB_FREQ_OPT) &
 232                SARL_A370_FAB_FREQ_OPT_MASK);
 233
 234        armada_370_xp_get_clk_ratio(opt, sar, id, mult, div);
 235}
 236
 237
 238static const struct core_clocks armada_370_core_clocks = {
 239        .get_tclk_freq = armada_370_get_tclk_freq,
 240        .get_cpu_freq = armada_370_get_cpu_freq,
 241        .get_clk_ratio = armada_370_get_clk_ratio,
 242        .ratios = armada_370_xp_core_ratios,
 243        .num_ratios = ARRAY_SIZE(armada_370_xp_core_ratios),
 244};
 245
 246static const u32 __initconst armada_xp_cpu_frequencies[] = {
 247        1000000000,
 248        1066000000,
 249        1200000000,
 250        1333000000,
 251        1500000000,
 252        1666000000,
 253        1800000000,
 254        2000000000,
 255        667000000,
 256        0,
 257        800000000,
 258        1600000000,
 259};
 260
 261/* For Armada XP TCLK frequency is fix: 250MHz */
 262static u32 __init armada_xp_get_tclk_freq(void __iomem *sar)
 263{
 264        return 250 * 1000 * 1000;
 265}
 266
 267static u32 __init armada_xp_get_cpu_freq(void __iomem *sar)
 268{
 269        u32 cpu_freq;
 270        u8 cpu_freq_select = 0;
 271
 272        cpu_freq_select = ((readl(sar) >> SARL_AXP_PCLK_FREQ_OPT) &
 273                           SARL_AXP_PCLK_FREQ_OPT_MASK);
 274        /*
 275         * The upper bit is not contiguous to the other ones and
 276         * located in the high part of the SAR registers
 277         */
 278        cpu_freq_select |= (((readl(sar+4) >> SARH_AXP_PCLK_FREQ_OPT) &
 279                             SARH_AXP_PCLK_FREQ_OPT_MASK)
 280                            << SARH_AXP_PCLK_FREQ_OPT_SHIFT);
 281        if (cpu_freq_select >= ARRAY_SIZE(armada_xp_cpu_frequencies)) {
 282                pr_err("CPU freq select unsupported: %d\n", cpu_freq_select);
 283                cpu_freq = 0;
 284        } else
 285                cpu_freq = armada_xp_cpu_frequencies[cpu_freq_select];
 286
 287        return cpu_freq;
 288}
 289
 290static void __init armada_xp_get_clk_ratio(
 291        void __iomem *sar, int id, int *mult, int *div)
 292{
 293
 294        u32 opt = ((readl(sar) >> SARL_AXP_FAB_FREQ_OPT) &
 295              SARL_AXP_FAB_FREQ_OPT_MASK);
 296        /*
 297         * The upper bit is not contiguous to the other ones and
 298         * located in the high part of the SAR registers
 299         */
 300        opt |= (((readl(sar+4) >> SARH_AXP_FAB_FREQ_OPT) &
 301                SARH_AXP_FAB_FREQ_OPT_MASK)
 302               << SARH_AXP_FAB_FREQ_OPT_SHIFT);
 303
 304        armada_370_xp_get_clk_ratio(opt, sar, id, mult, div);
 305}
 306
 307static const struct core_clocks armada_xp_core_clocks = {
 308        .get_tclk_freq = armada_xp_get_tclk_freq,
 309        .get_cpu_freq = armada_xp_get_cpu_freq,
 310        .get_clk_ratio = armada_xp_get_clk_ratio,
 311        .ratios = armada_370_xp_core_ratios,
 312        .num_ratios = ARRAY_SIZE(armada_370_xp_core_ratios),
 313};
 314
 315#endif /* CONFIG_MACH_ARMADA_370_XP */
 316
 317/*
 318 * Dove PLL sample-at-reset configuration
 319 *
 320 * SAR0[8:5]   : CPU frequency
 321 *               5  = 1000 MHz
 322 *               6  =  933 MHz
 323 *               7  =  933 MHz
 324 *               8  =  800 MHz
 325 *               9  =  800 MHz
 326 *               10 =  800 MHz
 327 *               11 = 1067 MHz
 328 *               12 =  667 MHz
 329 *               13 =  533 MHz
 330 *               14 =  400 MHz
 331 *               15 =  333 MHz
 332 *               others reserved.
 333 *
 334 * SAR0[11:9]  : CPU to L2 Clock divider ratio
 335 *               0 = (1/1) * CPU
 336 *               2 = (1/2) * CPU
 337 *               4 = (1/3) * CPU
 338 *               6 = (1/4) * CPU
 339 *               others reserved.
 340 *
 341 * SAR0[15:12] : CPU to DDR DRAM Clock divider ratio
 342 *               0  = (1/1) * CPU
 343 *               2  = (1/2) * CPU
 344 *               3  = (2/5) * CPU
 345 *               4  = (1/3) * CPU
 346 *               6  = (1/4) * CPU
 347 *               8  = (1/5) * CPU
 348 *               10 = (1/6) * CPU
 349 *               12 = (1/7) * CPU
 350 *               14 = (1/8) * CPU
 351 *               15 = (1/10) * CPU
 352 *               others reserved.
 353 *
 354 * SAR0[24:23] : TCLK frequency
 355 *               0 = 166 MHz
 356 *               1 = 125 MHz
 357 *               others reserved.
 358 */
 359#ifdef CONFIG_ARCH_DOVE
 360#define SAR_DOVE_CPU_FREQ               5
 361#define SAR_DOVE_CPU_FREQ_MASK          0xf
 362#define SAR_DOVE_L2_RATIO               9
 363#define SAR_DOVE_L2_RATIO_MASK          0x7
 364#define SAR_DOVE_DDR_RATIO              12
 365#define SAR_DOVE_DDR_RATIO_MASK         0xf
 366#define SAR_DOVE_TCLK_FREQ              23
 367#define SAR_DOVE_TCLK_FREQ_MASK         0x3
 368
 369static const u32 __initconst dove_tclk_frequencies[] = {
 370        166666667,
 371        125000000,
 372        0, 0
 373};
 374
 375static u32 __init dove_get_tclk_freq(void __iomem *sar)
 376{
 377        u32 opt = (readl(sar) >> SAR_DOVE_TCLK_FREQ) &
 378                SAR_DOVE_TCLK_FREQ_MASK;
 379        return dove_tclk_frequencies[opt];
 380}
 381
 382static const u32 __initconst dove_cpu_frequencies[] = {
 383        0, 0, 0, 0, 0,
 384        1000000000,
 385        933333333, 933333333,
 386        800000000, 800000000, 800000000,
 387        1066666667,
 388        666666667,
 389        533333333,
 390        400000000,
 391        333333333
 392};
 393
 394static u32 __init dove_get_cpu_freq(void __iomem *sar)
 395{
 396        u32 opt = (readl(sar) >> SAR_DOVE_CPU_FREQ) &
 397                SAR_DOVE_CPU_FREQ_MASK;
 398        return dove_cpu_frequencies[opt];
 399}
 400
 401enum { DOVE_CPU_TO_L2, DOVE_CPU_TO_DDR };
 402
 403static const struct core_ratio __initconst dove_core_ratios[] = {
 404        { .id = DOVE_CPU_TO_L2, .name = "l2clk", },
 405        { .id = DOVE_CPU_TO_DDR, .name = "ddrclk", }
 406};
 407
 408static const int __initconst dove_cpu_l2_ratios[8][2] = {
 409        { 1, 1 }, { 0, 1 }, { 1, 2 }, { 0, 1 },
 410        { 1, 3 }, { 0, 1 }, { 1, 4 }, { 0, 1 }
 411};
 412
 413static const int __initconst dove_cpu_ddr_ratios[16][2] = {
 414        { 1, 1 }, { 0, 1 }, { 1, 2 }, { 2, 5 },
 415        { 1, 3 }, { 0, 1 }, { 1, 4 }, { 0, 1 },
 416        { 1, 5 }, { 0, 1 }, { 1, 6 }, { 0, 1 },
 417        { 1, 7 }, { 0, 1 }, { 1, 8 }, { 1, 10 }
 418};
 419
 420static void __init dove_get_clk_ratio(
 421        void __iomem *sar, int id, int *mult, int *div)
 422{
 423        switch (id) {
 424        case DOVE_CPU_TO_L2:
 425        {
 426                u32 opt = (readl(sar) >> SAR_DOVE_L2_RATIO) &
 427                        SAR_DOVE_L2_RATIO_MASK;
 428                *mult = dove_cpu_l2_ratios[opt][0];
 429                *div = dove_cpu_l2_ratios[opt][1];
 430                break;
 431        }
 432        case DOVE_CPU_TO_DDR:
 433        {
 434                u32 opt = (readl(sar) >> SAR_DOVE_DDR_RATIO) &
 435                        SAR_DOVE_DDR_RATIO_MASK;
 436                *mult = dove_cpu_ddr_ratios[opt][0];
 437                *div = dove_cpu_ddr_ratios[opt][1];
 438                break;
 439        }
 440        }
 441}
 442
 443static const struct core_clocks dove_core_clocks = {
 444        .get_tclk_freq = dove_get_tclk_freq,
 445        .get_cpu_freq = dove_get_cpu_freq,
 446        .get_clk_ratio = dove_get_clk_ratio,
 447        .ratios = dove_core_ratios,
 448        .num_ratios = ARRAY_SIZE(dove_core_ratios),
 449};
 450#endif /* CONFIG_ARCH_DOVE */
 451
 452/*
 453 * Kirkwood PLL sample-at-reset configuration
 454 * (6180 has different SAR layout than other Kirkwood SoCs)
 455 *
 456 * SAR0[4:3,22,1] : CPU frequency (6281,6292,6282)
 457 *      4  =  600 MHz
 458 *      6  =  800 MHz
 459 *      7  = 1000 MHz
 460 *      9  = 1200 MHz
 461 *      12 = 1500 MHz
 462 *      13 = 1600 MHz
 463 *      14 = 1800 MHz
 464 *      15 = 2000 MHz
 465 *      others reserved.
 466 *
 467 * SAR0[19,10:9] : CPU to L2 Clock divider ratio (6281,6292,6282)
 468 *      1 = (1/2) * CPU
 469 *      3 = (1/3) * CPU
 470 *      5 = (1/4) * CPU
 471 *      others reserved.
 472 *
 473 * SAR0[8:5] : CPU to DDR DRAM Clock divider ratio (6281,6292,6282)
 474 *      2 = (1/2) * CPU
 475 *      4 = (1/3) * CPU
 476 *      6 = (1/4) * CPU
 477 *      7 = (2/9) * CPU
 478 *      8 = (1/5) * CPU
 479 *      9 = (1/6) * CPU
 480 *      others reserved.
 481 *
 482 * SAR0[4:2] : Kirkwood 6180 cpu/l2/ddr clock configuration (6180 only)
 483 *      5 = [CPU =  600 MHz, L2 = (1/2) * CPU, DDR = 200 MHz = (1/3) * CPU]
 484 *      6 = [CPU =  800 MHz, L2 = (1/2) * CPU, DDR = 200 MHz = (1/4) * CPU]
 485 *      7 = [CPU = 1000 MHz, L2 = (1/2) * CPU, DDR = 200 MHz = (1/5) * CPU]
 486 *      others reserved.
 487 *
 488 * SAR0[21] : TCLK frequency
 489 *      0 = 200 MHz
 490 *      1 = 166 MHz
 491 *      others reserved.
 492 */
 493#ifdef CONFIG_ARCH_KIRKWOOD
 494#define SAR_KIRKWOOD_CPU_FREQ(x)        \
 495        (((x & (1 <<  1)) >>  1) |      \
 496         ((x & (1 << 22)) >> 21) |      \
 497         ((x & (3 <<  3)) >>  1))
 498#define SAR_KIRKWOOD_L2_RATIO(x)        \
 499        (((x & (3 <<  9)) >> 9) |       \
 500         (((x & (1 << 19)) >> 17)))
 501#define SAR_KIRKWOOD_DDR_RATIO          5
 502#define SAR_KIRKWOOD_DDR_RATIO_MASK     0xf
 503#define SAR_MV88F6180_CLK               2
 504#define SAR_MV88F6180_CLK_MASK          0x7
 505#define SAR_KIRKWOOD_TCLK_FREQ          21
 506#define SAR_KIRKWOOD_TCLK_FREQ_MASK     0x1
 507
 508enum { KIRKWOOD_CPU_TO_L2, KIRKWOOD_CPU_TO_DDR };
 509
 510static const struct core_ratio __initconst kirkwood_core_ratios[] = {
 511        { .id = KIRKWOOD_CPU_TO_L2, .name = "l2clk", },
 512        { .id = KIRKWOOD_CPU_TO_DDR, .name = "ddrclk", }
 513};
 514
 515static u32 __init kirkwood_get_tclk_freq(void __iomem *sar)
 516{
 517        u32 opt = (readl(sar) >> SAR_KIRKWOOD_TCLK_FREQ) &
 518                SAR_KIRKWOOD_TCLK_FREQ_MASK;
 519        return (opt) ? 166666667 : 200000000;
 520}
 521
 522static const u32 __initconst kirkwood_cpu_frequencies[] = {
 523        0, 0, 0, 0,
 524        600000000,
 525        0,
 526        800000000,
 527        1000000000,
 528        0,
 529        1200000000,
 530        0, 0,
 531        1500000000,
 532        1600000000,
 533        1800000000,
 534        2000000000
 535};
 536
 537static u32 __init kirkwood_get_cpu_freq(void __iomem *sar)
 538{
 539        u32 opt = SAR_KIRKWOOD_CPU_FREQ(readl(sar));
 540        return kirkwood_cpu_frequencies[opt];
 541}
 542
 543static const int __initconst kirkwood_cpu_l2_ratios[8][2] = {
 544        { 0, 1 }, { 1, 2 }, { 0, 1 }, { 1, 3 },
 545        { 0, 1 }, { 1, 4 }, { 0, 1 }, { 0, 1 }
 546};
 547
 548static const int __initconst kirkwood_cpu_ddr_ratios[16][2] = {
 549        { 0, 1 }, { 0, 1 }, { 1, 2 }, { 0, 1 },
 550        { 1, 3 }, { 0, 1 }, { 1, 4 }, { 2, 9 },
 551        { 1, 5 }, { 1, 6 }, { 0, 1 }, { 0, 1 },
 552        { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 }
 553};
 554
 555static void __init kirkwood_get_clk_ratio(
 556        void __iomem *sar, int id, int *mult, int *div)
 557{
 558        switch (id) {
 559        case KIRKWOOD_CPU_TO_L2:
 560        {
 561                u32 opt = SAR_KIRKWOOD_L2_RATIO(readl(sar));
 562                *mult = kirkwood_cpu_l2_ratios[opt][0];
 563                *div = kirkwood_cpu_l2_ratios[opt][1];
 564                break;
 565        }
 566        case KIRKWOOD_CPU_TO_DDR:
 567        {
 568                u32 opt = (readl(sar) >> SAR_KIRKWOOD_DDR_RATIO) &
 569                        SAR_KIRKWOOD_DDR_RATIO_MASK;
 570                *mult = kirkwood_cpu_ddr_ratios[opt][0];
 571                *div = kirkwood_cpu_ddr_ratios[opt][1];
 572                break;
 573        }
 574        }
 575}
 576
 577static const struct core_clocks kirkwood_core_clocks = {
 578        .get_tclk_freq = kirkwood_get_tclk_freq,
 579        .get_cpu_freq = kirkwood_get_cpu_freq,
 580        .get_clk_ratio = kirkwood_get_clk_ratio,
 581        .ratios = kirkwood_core_ratios,
 582        .num_ratios = ARRAY_SIZE(kirkwood_core_ratios),
 583};
 584
 585static const u32 __initconst mv88f6180_cpu_frequencies[] = {
 586        0, 0, 0, 0, 0,
 587        600000000,
 588        800000000,
 589        1000000000
 590};
 591
 592static u32 __init mv88f6180_get_cpu_freq(void __iomem *sar)
 593{
 594        u32 opt = (readl(sar) >> SAR_MV88F6180_CLK) & SAR_MV88F6180_CLK_MASK;
 595        return mv88f6180_cpu_frequencies[opt];
 596}
 597
 598static const int __initconst mv88f6180_cpu_ddr_ratios[8][2] = {
 599        { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 },
 600        { 0, 1 }, { 1, 3 }, { 1, 4 }, { 1, 5 }
 601};
 602
 603static void __init mv88f6180_get_clk_ratio(
 604        void __iomem *sar, int id, int *mult, int *div)
 605{
 606        switch (id) {
 607        case KIRKWOOD_CPU_TO_L2:
 608        {
 609                /* mv88f6180 has a fixed 1:2 CPU-to-L2 ratio */
 610                *mult = 1;
 611                *div = 2;
 612                break;
 613        }
 614        case KIRKWOOD_CPU_TO_DDR:
 615        {
 616                u32 opt = (readl(sar) >> SAR_MV88F6180_CLK) &
 617                        SAR_MV88F6180_CLK_MASK;
 618                *mult = mv88f6180_cpu_ddr_ratios[opt][0];
 619                *div = mv88f6180_cpu_ddr_ratios[opt][1];
 620                break;
 621        }
 622        }
 623}
 624
 625static const struct core_clocks mv88f6180_core_clocks = {
 626        .get_tclk_freq = kirkwood_get_tclk_freq,
 627        .get_cpu_freq = mv88f6180_get_cpu_freq,
 628        .get_clk_ratio = mv88f6180_get_clk_ratio,
 629        .ratios = kirkwood_core_ratios,
 630        .num_ratios = ARRAY_SIZE(kirkwood_core_ratios),
 631};
 632#endif /* CONFIG_ARCH_KIRKWOOD */
 633
 634static const __initdata struct of_device_id clk_core_match[] = {
 635#ifdef CONFIG_MACH_ARMADA_370_XP
 636        {
 637                .compatible = "marvell,armada-370-core-clock",
 638                .data = &armada_370_core_clocks,
 639        },
 640        {
 641                .compatible = "marvell,armada-xp-core-clock",
 642                .data = &armada_xp_core_clocks,
 643        },
 644#endif
 645#ifdef CONFIG_ARCH_DOVE
 646        {
 647                .compatible = "marvell,dove-core-clock",
 648                .data = &dove_core_clocks,
 649        },
 650#endif
 651
 652#ifdef CONFIG_ARCH_KIRKWOOD
 653        {
 654                .compatible = "marvell,kirkwood-core-clock",
 655                .data = &kirkwood_core_clocks,
 656        },
 657        {
 658                .compatible = "marvell,mv88f6180-core-clock",
 659                .data = &mv88f6180_core_clocks,
 660        },
 661#endif
 662
 663        { }
 664};
 665
 666void __init mvebu_core_clk_init(void)
 667{
 668        struct device_node *np;
 669
 670        for_each_matching_node(np, clk_core_match) {
 671                const struct of_device_id *match =
 672                        of_match_node(clk_core_match, np);
 673                mvebu_clk_core_setup(np, (struct core_clocks *)match->data);
 674        }
 675}
 676