linux/drivers/clk/mvebu/dove.c
<<
>>
Prefs
   1/*
   2 * Marvell Dove SoC clocks
   3 *
   4 * Copyright (C) 2012 Marvell
   5 *
   6 * Gregory CLEMENT <gregory.clement@free-electrons.com>
   7 * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
   8 * Andrew Lunn <andrew@lunn.ch>
   9 *
  10 * This file is licensed under the terms of the GNU General Public
  11 * License version 2.  This program is licensed "as is" without any
  12 * warranty of any kind, whether express or implied.
  13 */
  14
  15#include <linux/kernel.h>
  16#include <linux/clk-provider.h>
  17#include <linux/io.h>
  18#include <linux/of.h>
  19#include "common.h"
  20
  21/*
  22 * Core Clocks
  23 *
  24 * Dove PLL sample-at-reset configuration
  25 *
  26 * SAR0[8:5]   : CPU frequency
  27 *               5  = 1000 MHz
  28 *               6  =  933 MHz
  29 *               7  =  933 MHz
  30 *               8  =  800 MHz
  31 *               9  =  800 MHz
  32 *               10 =  800 MHz
  33 *               11 = 1067 MHz
  34 *               12 =  667 MHz
  35 *               13 =  533 MHz
  36 *               14 =  400 MHz
  37 *               15 =  333 MHz
  38 *               others reserved.
  39 *
  40 * SAR0[11:9]  : CPU to L2 Clock divider ratio
  41 *               0 = (1/1) * CPU
  42 *               2 = (1/2) * CPU
  43 *               4 = (1/3) * CPU
  44 *               6 = (1/4) * CPU
  45 *               others reserved.
  46 *
  47 * SAR0[15:12] : CPU to DDR DRAM Clock divider ratio
  48 *               0  = (1/1) * CPU
  49 *               2  = (1/2) * CPU
  50 *               3  = (2/5) * CPU
  51 *               4  = (1/3) * CPU
  52 *               6  = (1/4) * CPU
  53 *               8  = (1/5) * CPU
  54 *               10 = (1/6) * CPU
  55 *               12 = (1/7) * CPU
  56 *               14 = (1/8) * CPU
  57 *               15 = (1/10) * CPU
  58 *               others reserved.
  59 *
  60 * SAR0[24:23] : TCLK frequency
  61 *               0 = 166 MHz
  62 *               1 = 125 MHz
  63 *               others reserved.
  64 */
  65
  66#define SAR_DOVE_CPU_FREQ               5
  67#define SAR_DOVE_CPU_FREQ_MASK          0xf
  68#define SAR_DOVE_L2_RATIO               9
  69#define SAR_DOVE_L2_RATIO_MASK          0x7
  70#define SAR_DOVE_DDR_RATIO              12
  71#define SAR_DOVE_DDR_RATIO_MASK         0xf
  72#define SAR_DOVE_TCLK_FREQ              23
  73#define SAR_DOVE_TCLK_FREQ_MASK         0x3
  74
  75enum { DOVE_CPU_TO_L2, DOVE_CPU_TO_DDR };
  76
  77static const struct coreclk_ratio dove_coreclk_ratios[] __initconst = {
  78        { .id = DOVE_CPU_TO_L2, .name = "l2clk", },
  79        { .id = DOVE_CPU_TO_DDR, .name = "ddrclk", }
  80};
  81
  82static const u32 dove_tclk_freqs[] __initconst = {
  83        166666667,
  84        125000000,
  85        0, 0
  86};
  87
  88static u32 __init dove_get_tclk_freq(void __iomem *sar)
  89{
  90        u32 opt = (readl(sar) >> SAR_DOVE_TCLK_FREQ) &
  91                SAR_DOVE_TCLK_FREQ_MASK;
  92        return dove_tclk_freqs[opt];
  93}
  94
  95static const u32 dove_cpu_freqs[] __initconst = {
  96        0, 0, 0, 0, 0,
  97        1000000000,
  98        933333333, 933333333,
  99        800000000, 800000000, 800000000,
 100        1066666667,
 101        666666667,
 102        533333333,
 103        400000000,
 104        333333333
 105};
 106
 107static u32 __init dove_get_cpu_freq(void __iomem *sar)
 108{
 109        u32 opt = (readl(sar) >> SAR_DOVE_CPU_FREQ) &
 110                SAR_DOVE_CPU_FREQ_MASK;
 111        return dove_cpu_freqs[opt];
 112}
 113
 114static const int dove_cpu_l2_ratios[8][2] __initconst = {
 115        { 1, 1 }, { 0, 1 }, { 1, 2 }, { 0, 1 },
 116        { 1, 3 }, { 0, 1 }, { 1, 4 }, { 0, 1 }
 117};
 118
 119static const int dove_cpu_ddr_ratios[16][2] __initconst = {
 120        { 1, 1 }, { 0, 1 }, { 1, 2 }, { 2, 5 },
 121        { 1, 3 }, { 0, 1 }, { 1, 4 }, { 0, 1 },
 122        { 1, 5 }, { 0, 1 }, { 1, 6 }, { 0, 1 },
 123        { 1, 7 }, { 0, 1 }, { 1, 8 }, { 1, 10 }
 124};
 125
 126static void __init dove_get_clk_ratio(
 127        void __iomem *sar, int id, int *mult, int *div)
 128{
 129        switch (id) {
 130        case DOVE_CPU_TO_L2:
 131        {
 132                u32 opt = (readl(sar) >> SAR_DOVE_L2_RATIO) &
 133                        SAR_DOVE_L2_RATIO_MASK;
 134                *mult = dove_cpu_l2_ratios[opt][0];
 135                *div = dove_cpu_l2_ratios[opt][1];
 136                break;
 137        }
 138        case DOVE_CPU_TO_DDR:
 139        {
 140                u32 opt = (readl(sar) >> SAR_DOVE_DDR_RATIO) &
 141                        SAR_DOVE_DDR_RATIO_MASK;
 142                *mult = dove_cpu_ddr_ratios[opt][0];
 143                *div = dove_cpu_ddr_ratios[opt][1];
 144                break;
 145        }
 146        }
 147}
 148
 149static const struct coreclk_soc_desc dove_coreclks = {
 150        .get_tclk_freq = dove_get_tclk_freq,
 151        .get_cpu_freq = dove_get_cpu_freq,
 152        .get_clk_ratio = dove_get_clk_ratio,
 153        .ratios = dove_coreclk_ratios,
 154        .num_ratios = ARRAY_SIZE(dove_coreclk_ratios),
 155};
 156
 157/*
 158 * Clock Gating Control
 159 */
 160
 161static const struct clk_gating_soc_desc dove_gating_desc[] __initconst = {
 162        { "usb0", NULL, 0, 0 },
 163        { "usb1", NULL, 1, 0 },
 164        { "ge", "gephy", 2, 0 },
 165        { "sata", NULL, 3, 0 },
 166        { "pex0", NULL, 4, 0 },
 167        { "pex1", NULL, 5, 0 },
 168        { "sdio0", NULL, 8, 0 },
 169        { "sdio1", NULL, 9, 0 },
 170        { "nand", NULL, 10, 0 },
 171        { "camera", NULL, 11, 0 },
 172        { "i2s0", NULL, 12, 0 },
 173        { "i2s1", NULL, 13, 0 },
 174        { "crypto", NULL, 15, 0 },
 175        { "ac97", NULL, 21, 0 },
 176        { "pdma", NULL, 22, 0 },
 177        { "xor0", NULL, 23, 0 },
 178        { "xor1", NULL, 24, 0 },
 179        { "gephy", NULL, 30, 0 },
 180        { }
 181};
 182
 183static void __init dove_clk_init(struct device_node *np)
 184{
 185        struct device_node *cgnp =
 186                of_find_compatible_node(NULL, NULL, "marvell,dove-gating-clock");
 187
 188        mvebu_coreclk_setup(np, &dove_coreclks);
 189
 190        if (cgnp)
 191                mvebu_clk_gating_setup(cgnp, dove_gating_desc);
 192}
 193CLK_OF_DECLARE(dove_clk, "marvell,dove-core-clock", dove_clk_init);
 194