Merge tag 'jfs-3.12' of git://github.com/kleikamp/linux-shaggy
[deliverable/linux.git] / drivers / clk / mvebu / kirkwood.c
CommitLineData
e89406c9
SH
1/*
2 * Marvell Kirkwood 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 * Kirkwood PLL sample-at-reset configuration
25 * (6180 has different SAR layout than other Kirkwood SoCs)
26 *
27 * SAR0[4:3,22,1] : CPU frequency (6281,6292,6282)
28 * 4 = 600 MHz
29 * 6 = 800 MHz
30 * 7 = 1000 MHz
31 * 9 = 1200 MHz
32 * 12 = 1500 MHz
33 * 13 = 1600 MHz
34 * 14 = 1800 MHz
35 * 15 = 2000 MHz
36 * others reserved.
37 *
38 * SAR0[19,10:9] : CPU to L2 Clock divider ratio (6281,6292,6282)
39 * 1 = (1/2) * CPU
40 * 3 = (1/3) * CPU
41 * 5 = (1/4) * CPU
42 * others reserved.
43 *
44 * SAR0[8:5] : CPU to DDR DRAM Clock divider ratio (6281,6292,6282)
45 * 2 = (1/2) * CPU
46 * 4 = (1/3) * CPU
47 * 6 = (1/4) * CPU
48 * 7 = (2/9) * CPU
49 * 8 = (1/5) * CPU
50 * 9 = (1/6) * CPU
51 * others reserved.
52 *
53 * SAR0[4:2] : Kirkwood 6180 cpu/l2/ddr clock configuration (6180 only)
54 * 5 = [CPU = 600 MHz, L2 = (1/2) * CPU, DDR = 200 MHz = (1/3) * CPU]
55 * 6 = [CPU = 800 MHz, L2 = (1/2) * CPU, DDR = 200 MHz = (1/4) * CPU]
56 * 7 = [CPU = 1000 MHz, L2 = (1/2) * CPU, DDR = 200 MHz = (1/5) * CPU]
57 * others reserved.
58 *
59 * SAR0[21] : TCLK frequency
60 * 0 = 200 MHz
61 * 1 = 166 MHz
62 * others reserved.
63 */
64
65#define SAR_KIRKWOOD_CPU_FREQ(x) \
66 (((x & (1 << 1)) >> 1) | \
67 ((x & (1 << 22)) >> 21) | \
68 ((x & (3 << 3)) >> 1))
69#define SAR_KIRKWOOD_L2_RATIO(x) \
70 (((x & (3 << 9)) >> 9) | \
71 (((x & (1 << 19)) >> 17)))
72#define SAR_KIRKWOOD_DDR_RATIO 5
73#define SAR_KIRKWOOD_DDR_RATIO_MASK 0xf
74#define SAR_MV88F6180_CLK 2
75#define SAR_MV88F6180_CLK_MASK 0x7
76#define SAR_KIRKWOOD_TCLK_FREQ 21
77#define SAR_KIRKWOOD_TCLK_FREQ_MASK 0x1
78
79enum { KIRKWOOD_CPU_TO_L2, KIRKWOOD_CPU_TO_DDR };
80
847b1c00 81static const struct coreclk_ratio kirkwood_coreclk_ratios[] __initconst = {
e89406c9
SH
82 { .id = KIRKWOOD_CPU_TO_L2, .name = "l2clk", },
83 { .id = KIRKWOOD_CPU_TO_DDR, .name = "ddrclk", }
84};
85
86static u32 __init kirkwood_get_tclk_freq(void __iomem *sar)
87{
88 u32 opt = (readl(sar) >> SAR_KIRKWOOD_TCLK_FREQ) &
89 SAR_KIRKWOOD_TCLK_FREQ_MASK;
90 return (opt) ? 166666667 : 200000000;
91}
92
847b1c00 93static const u32 kirkwood_cpu_freqs[] __initconst = {
e89406c9
SH
94 0, 0, 0, 0,
95 600000000,
96 0,
97 800000000,
98 1000000000,
99 0,
100 1200000000,
101 0, 0,
102 1500000000,
103 1600000000,
104 1800000000,
105 2000000000
106};
107
108static u32 __init kirkwood_get_cpu_freq(void __iomem *sar)
109{
110 u32 opt = SAR_KIRKWOOD_CPU_FREQ(readl(sar));
111 return kirkwood_cpu_freqs[opt];
112}
113
847b1c00 114static const int kirkwood_cpu_l2_ratios[8][2] __initconst = {
e89406c9
SH
115 { 0, 1 }, { 1, 2 }, { 0, 1 }, { 1, 3 },
116 { 0, 1 }, { 1, 4 }, { 0, 1 }, { 0, 1 }
117};
118
847b1c00 119static const int kirkwood_cpu_ddr_ratios[16][2] __initconst = {
e89406c9
SH
120 { 0, 1 }, { 0, 1 }, { 1, 2 }, { 0, 1 },
121 { 1, 3 }, { 0, 1 }, { 1, 4 }, { 2, 9 },
122 { 1, 5 }, { 1, 6 }, { 0, 1 }, { 0, 1 },
123 { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 }
124};
125
126static void __init kirkwood_get_clk_ratio(
127 void __iomem *sar, int id, int *mult, int *div)
128{
129 switch (id) {
130 case KIRKWOOD_CPU_TO_L2:
131 {
132 u32 opt = SAR_KIRKWOOD_L2_RATIO(readl(sar));
133 *mult = kirkwood_cpu_l2_ratios[opt][0];
134 *div = kirkwood_cpu_l2_ratios[opt][1];
135 break;
136 }
137 case KIRKWOOD_CPU_TO_DDR:
138 {
139 u32 opt = (readl(sar) >> SAR_KIRKWOOD_DDR_RATIO) &
140 SAR_KIRKWOOD_DDR_RATIO_MASK;
141 *mult = kirkwood_cpu_ddr_ratios[opt][0];
142 *div = kirkwood_cpu_ddr_ratios[opt][1];
143 break;
144 }
145 }
146}
147
847b1c00 148static const u32 mv88f6180_cpu_freqs[] __initconst = {
e89406c9
SH
149 0, 0, 0, 0, 0,
150 600000000,
151 800000000,
152 1000000000
153};
154
155static u32 __init mv88f6180_get_cpu_freq(void __iomem *sar)
156{
157 u32 opt = (readl(sar) >> SAR_MV88F6180_CLK) & SAR_MV88F6180_CLK_MASK;
158 return mv88f6180_cpu_freqs[opt];
159}
160
847b1c00 161static const int mv88f6180_cpu_ddr_ratios[8][2] __initconst = {
e89406c9
SH
162 { 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 },
163 { 0, 1 }, { 1, 3 }, { 1, 4 }, { 1, 5 }
164};
165
166static void __init mv88f6180_get_clk_ratio(
167 void __iomem *sar, int id, int *mult, int *div)
168{
169 switch (id) {
170 case KIRKWOOD_CPU_TO_L2:
171 {
172 /* mv88f6180 has a fixed 1:2 CPU-to-L2 ratio */
173 *mult = 1;
174 *div = 2;
175 break;
176 }
177 case KIRKWOOD_CPU_TO_DDR:
178 {
179 u32 opt = (readl(sar) >> SAR_MV88F6180_CLK) &
180 SAR_MV88F6180_CLK_MASK;
181 *mult = mv88f6180_cpu_ddr_ratios[opt][0];
182 *div = mv88f6180_cpu_ddr_ratios[opt][1];
183 break;
184 }
185 }
186}
187
188static const struct coreclk_soc_desc kirkwood_coreclks = {
189 .get_tclk_freq = kirkwood_get_tclk_freq,
190 .get_cpu_freq = kirkwood_get_cpu_freq,
191 .get_clk_ratio = kirkwood_get_clk_ratio,
192 .ratios = kirkwood_coreclk_ratios,
193 .num_ratios = ARRAY_SIZE(kirkwood_coreclk_ratios),
194};
195
196static void __init kirkwood_coreclk_init(struct device_node *np)
197{
198 mvebu_coreclk_setup(np, &kirkwood_coreclks);
199}
200CLK_OF_DECLARE(kirkwood_core_clk, "marvell,kirkwood-core-clock",
201 kirkwood_coreclk_init);
202
203static const struct coreclk_soc_desc mv88f6180_coreclks = {
204 .get_tclk_freq = kirkwood_get_tclk_freq,
205 .get_cpu_freq = mv88f6180_get_cpu_freq,
206 .get_clk_ratio = mv88f6180_get_clk_ratio,
207 .ratios = kirkwood_coreclk_ratios,
208 .num_ratios = ARRAY_SIZE(kirkwood_coreclk_ratios),
209};
210
211static void __init mv88f6180_coreclk_init(struct device_node *np)
212{
213 mvebu_coreclk_setup(np, &mv88f6180_coreclks);
214}
215CLK_OF_DECLARE(mv88f6180_core_clk, "marvell,mv88f6180-core-clock",
216 mv88f6180_coreclk_init);
217
218/*
219 * Clock Gating Control
220 */
221
847b1c00 222static const struct clk_gating_soc_desc kirkwood_gating_desc[] __initconst = {
e89406c9
SH
223 { "ge0", NULL, 0, 0 },
224 { "pex0", NULL, 2, 0 },
225 { "usb0", NULL, 3, 0 },
226 { "sdio", NULL, 4, 0 },
227 { "tsu", NULL, 5, 0 },
228 { "runit", NULL, 7, 0 },
229 { "xor0", NULL, 8, 0 },
230 { "audio", NULL, 9, 0 },
231 { "powersave", "cpuclk", 11, 0 },
232 { "sata0", NULL, 14, 0 },
233 { "sata1", NULL, 15, 0 },
234 { "xor1", NULL, 16, 0 },
235 { "crypto", NULL, 17, 0 },
236 { "pex1", NULL, 18, 0 },
237 { "ge1", NULL, 19, 0 },
238 { "tdm", NULL, 20, 0 },
239 { }
240};
241
242static void __init kirkwood_clk_gating_init(struct device_node *np)
243{
244 mvebu_clk_gating_setup(np, kirkwood_gating_desc);
245}
246CLK_OF_DECLARE(kirkwood_clk_gating, "marvell,kirkwood-gating-clock",
247 kirkwood_clk_gating_init);
This page took 0.053792 seconds and 5 git commands to generate.