aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2013-06-01 02:23:25 -0400
committerOlof Johansson <olof@lixom.net>2013-06-01 02:23:25 -0400
commit85b9174fda1d516198b4a46a7795e43636a3ea4c (patch)
tree2721a32c07ca3e1d46df573a19b4e92853688966 /drivers/clk
parent2dbefbf6a803d65f6327fe617f5e1960f218ce01 (diff)
parentea7e0bd7e78868bbe6df6834595ef96166dd296a (diff)
Merge tag 'seb_clk-3.11' of git://git.infradead.org/users/jcooper/linux into next/soc
From Jason Cooper: mvebu clock restructuring for v3.11 - clk: mvebu - reorganize by SoC to remove built up #ifdefs - add clk flags per clock gate * tag 'seb_clk-3.11' of git://git.infradead.org/users/jcooper/linux: clk: mvebu: disintegrate obsolete file ARM: mvebu: move DT boards to SoC-centric clock init ARM: kirkwood: move DT boards to SoC-centric clock init ARM: dove: move DT boards to SoC-centric clock init clk: mvebu: add Armada XP SoC-centric clock init clk: mvebu: add Armada 370 SoC-centric clock init clk: mvebu: add Kirkwood SoC-centric clock init clk: mvebu: add Dove SoC-centric clock init clk: mvebu: add common clock functions for core clk and clk gating clk: mvebu: introduce per-clock-gate flags
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/mvebu/Kconfig25
-rw-r--r--drivers/clk/mvebu/Makefile8
-rw-r--r--drivers/clk/mvebu/armada-370.c176
-rw-r--r--drivers/clk/mvebu/armada-xp.c210
-rw-r--r--drivers/clk/mvebu/clk-core.c675
-rw-r--r--drivers/clk/mvebu/clk-core.h18
-rw-r--r--drivers/clk/mvebu/clk-gating-ctrl.c256
-rw-r--r--drivers/clk/mvebu/clk-gating-ctrl.h22
-rw-r--r--drivers/clk/mvebu/clk.c23
-rw-r--r--drivers/clk/mvebu/common.c163
-rw-r--r--drivers/clk/mvebu/common.h48
-rw-r--r--drivers/clk/mvebu/dove.c194
-rw-r--r--drivers/clk/mvebu/kirkwood.c247
13 files changed, 1064 insertions, 1001 deletions
diff --git a/drivers/clk/mvebu/Kconfig b/drivers/clk/mvebu/Kconfig
index 57323fd15ec9..0b0f3e729cf7 100644
--- a/drivers/clk/mvebu/Kconfig
+++ b/drivers/clk/mvebu/Kconfig
@@ -1,8 +1,23 @@
1config MVEBU_CLK_CORE 1config MVEBU_CLK_COMMON
2 bool 2 bool
3 3
4config MVEBU_CLK_CPU 4config MVEBU_CLK_CPU
5 bool 5 bool
6 6
7config MVEBU_CLK_GATING 7config ARMADA_370_CLK
8 bool 8 bool
9 select MVEBU_CLK_COMMON
10 select MVEBU_CLK_CPU
11
12config ARMADA_XP_CLK
13 bool
14 select MVEBU_CLK_COMMON
15 select MVEBU_CLK_CPU
16
17config DOVE_CLK
18 bool
19 select MVEBU_CLK_COMMON
20
21config KIRKWOOD_CLK
22 bool
23 select MVEBU_CLK_COMMON
diff --git a/drivers/clk/mvebu/Makefile b/drivers/clk/mvebu/Makefile
index 58df3dc49363..1c7e70c63fb2 100644
--- a/drivers/clk/mvebu/Makefile
+++ b/drivers/clk/mvebu/Makefile
@@ -1,3 +1,7 @@
1obj-$(CONFIG_MVEBU_CLK_CORE) += clk.o clk-core.o 1obj-$(CONFIG_MVEBU_CLK_COMMON) += common.o
2obj-$(CONFIG_MVEBU_CLK_CPU) += clk-cpu.o 2obj-$(CONFIG_MVEBU_CLK_CPU) += clk-cpu.o
3obj-$(CONFIG_MVEBU_CLK_GATING) += clk-gating-ctrl.o 3
4obj-$(CONFIG_ARMADA_370_CLK) += armada-370.o
5obj-$(CONFIG_ARMADA_XP_CLK) += armada-xp.o
6obj-$(CONFIG_DOVE_CLK) += dove.o
7obj-$(CONFIG_KIRKWOOD_CLK) += kirkwood.o
diff --git a/drivers/clk/mvebu/armada-370.c b/drivers/clk/mvebu/armada-370.c
new file mode 100644
index 000000000000..079960e7c304
--- /dev/null
+++ b/drivers/clk/mvebu/armada-370.c
@@ -0,0 +1,176 @@
1/*
2 * Marvell Armada 370 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
25#define SARL 0 /* Low part [0:31] */
26#define SARL_A370_PCLK_FREQ_OPT 11
27#define SARL_A370_PCLK_FREQ_OPT_MASK 0xF
28#define SARL_A370_FAB_FREQ_OPT 15
29#define SARL_A370_FAB_FREQ_OPT_MASK 0x1F
30#define SARL_A370_TCLK_FREQ_OPT 20
31#define SARL_A370_TCLK_FREQ_OPT_MASK 0x1
32
33enum { A370_CPU_TO_NBCLK, A370_CPU_TO_HCLK, A370_CPU_TO_DRAMCLK };
34
35static const struct coreclk_ratio __initconst a370_coreclk_ratios[] = {
36 { .id = A370_CPU_TO_NBCLK, .name = "nbclk" },
37 { .id = A370_CPU_TO_HCLK, .name = "hclk" },
38 { .id = A370_CPU_TO_DRAMCLK, .name = "dramclk" },
39};
40
41static const u32 __initconst a370_tclk_freqs[] = {
42 16600000,
43 20000000,
44};
45
46static u32 __init a370_get_tclk_freq(void __iomem *sar)
47{
48 u8 tclk_freq_select = 0;
49
50 tclk_freq_select = ((readl(sar) >> SARL_A370_TCLK_FREQ_OPT) &
51 SARL_A370_TCLK_FREQ_OPT_MASK);
52 return a370_tclk_freqs[tclk_freq_select];
53}
54
55static const u32 __initconst a370_cpu_freqs[] = {
56 400000000,
57 533000000,
58 667000000,
59 800000000,
60 1000000000,
61 1067000000,
62 1200000000,
63};
64
65static u32 __init a370_get_cpu_freq(void __iomem *sar)
66{
67 u32 cpu_freq;
68 u8 cpu_freq_select = 0;
69
70 cpu_freq_select = ((readl(sar) >> SARL_A370_PCLK_FREQ_OPT) &
71 SARL_A370_PCLK_FREQ_OPT_MASK);
72 if (cpu_freq_select >= ARRAY_SIZE(a370_cpu_freqs)) {
73 pr_err("CPU freq select unsupported %d\n", cpu_freq_select);
74 cpu_freq = 0;
75 } else
76 cpu_freq = a370_cpu_freqs[cpu_freq_select];
77
78 return cpu_freq;
79}
80
81static const int __initconst a370_nbclk_ratios[32][2] = {
82 {0, 1}, {1, 2}, {2, 2}, {2, 2},
83 {1, 2}, {1, 2}, {1, 1}, {2, 3},
84 {0, 1}, {1, 2}, {2, 4}, {0, 1},
85 {1, 2}, {0, 1}, {0, 1}, {2, 2},
86 {0, 1}, {0, 1}, {0, 1}, {1, 1},
87 {2, 3}, {0, 1}, {0, 1}, {0, 1},
88 {0, 1}, {0, 1}, {0, 1}, {1, 1},
89 {0, 1}, {0, 1}, {0, 1}, {0, 1},
90};
91
92static const int __initconst a370_hclk_ratios[32][2] = {
93 {0, 1}, {1, 2}, {2, 6}, {2, 3},
94 {1, 3}, {1, 4}, {1, 2}, {2, 6},
95 {0, 1}, {1, 6}, {2, 10}, {0, 1},
96 {1, 4}, {0, 1}, {0, 1}, {2, 5},
97 {0, 1}, {0, 1}, {0, 1}, {1, 2},
98 {2, 6}, {0, 1}, {0, 1}, {0, 1},
99 {0, 1}, {0, 1}, {0, 1}, {1, 1},
100 {0, 1}, {0, 1}, {0, 1}, {0, 1},
101};
102
103static const int __initconst a370_dramclk_ratios[32][2] = {
104 {0, 1}, {1, 2}, {2, 3}, {2, 3},
105 {1, 3}, {1, 2}, {1, 2}, {2, 6},
106 {0, 1}, {1, 3}, {2, 5}, {0, 1},
107 {1, 4}, {0, 1}, {0, 1}, {2, 5},
108 {0, 1}, {0, 1}, {0, 1}, {1, 1},
109 {2, 3}, {0, 1}, {0, 1}, {0, 1},
110 {0, 1}, {0, 1}, {0, 1}, {1, 1},
111 {0, 1}, {0, 1}, {0, 1}, {0, 1},
112};
113
114static void __init a370_get_clk_ratio(
115 void __iomem *sar, int id, int *mult, int *div)
116{
117 u32 opt = ((readl(sar) >> SARL_A370_FAB_FREQ_OPT) &
118 SARL_A370_FAB_FREQ_OPT_MASK);
119
120 switch (id) {
121 case A370_CPU_TO_NBCLK:
122 *mult = a370_nbclk_ratios[opt][0];
123 *div = a370_nbclk_ratios[opt][1];
124 break;
125 case A370_CPU_TO_HCLK:
126 *mult = a370_hclk_ratios[opt][0];
127 *div = a370_hclk_ratios[opt][1];
128 break;
129 case A370_CPU_TO_DRAMCLK:
130 *mult = a370_dramclk_ratios[opt][0];
131 *div = a370_dramclk_ratios[opt][1];
132 break;
133 }
134}
135
136static const struct coreclk_soc_desc a370_coreclks = {
137 .get_tclk_freq = a370_get_tclk_freq,
138 .get_cpu_freq = a370_get_cpu_freq,
139 .get_clk_ratio = a370_get_clk_ratio,
140 .ratios = a370_coreclk_ratios,
141 .num_ratios = ARRAY_SIZE(a370_coreclk_ratios),
142};
143
144static void __init a370_coreclk_init(struct device_node *np)
145{
146 mvebu_coreclk_setup(np, &a370_coreclks);
147}
148CLK_OF_DECLARE(a370_core_clk, "marvell,armada-370-core-clock",
149 a370_coreclk_init);
150
151/*
152 * Clock Gating Control
153 */
154
155static const struct clk_gating_soc_desc __initconst a370_gating_desc[] = {
156 { "audio", NULL, 0, 0 },
157 { "pex0_en", NULL, 1, 0 },
158 { "pex1_en", NULL, 2, 0 },
159 { "ge1", NULL, 3, 0 },
160 { "ge0", NULL, 4, 0 },
161 { "pex0", "pex0_en", 5, 0 },
162 { "pex1", "pex1_en", 9, 0 },
163 { "sata0", NULL, 15, 0 },
164 { "sdio", NULL, 17, 0 },
165 { "tdm", NULL, 25, 0 },
166 { "ddr", NULL, 28, CLK_IGNORE_UNUSED },
167 { "sata1", NULL, 30, 0 },
168 { }
169};
170
171static void __init a370_clk_gating_init(struct device_node *np)
172{
173 mvebu_clk_gating_setup(np, a370_gating_desc);
174}
175CLK_OF_DECLARE(a370_clk_gating, "marvell,armada-370-gating-clock",
176 a370_clk_gating_init);
diff --git a/drivers/clk/mvebu/armada-xp.c b/drivers/clk/mvebu/armada-xp.c
new file mode 100644
index 000000000000..13b62ceb3407
--- /dev/null
+++ b/drivers/clk/mvebu/armada-xp.c
@@ -0,0 +1,210 @@
1/*
2 * Marvell Armada XP 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 * Armada XP Sample At Reset is a 64 bit bitfiled split in two
25 * register of 32 bits
26 */
27
28#define SARL 0 /* Low part [0:31] */
29#define SARL_AXP_PCLK_FREQ_OPT 21
30#define SARL_AXP_PCLK_FREQ_OPT_MASK 0x7
31#define SARL_AXP_FAB_FREQ_OPT 24
32#define SARL_AXP_FAB_FREQ_OPT_MASK 0xF
33#define SARH 4 /* High part [32:63] */
34#define SARH_AXP_PCLK_FREQ_OPT (52-32)
35#define SARH_AXP_PCLK_FREQ_OPT_MASK 0x1
36#define SARH_AXP_PCLK_FREQ_OPT_SHIFT 3
37#define SARH_AXP_FAB_FREQ_OPT (51-32)
38#define SARH_AXP_FAB_FREQ_OPT_MASK 0x1
39#define SARH_AXP_FAB_FREQ_OPT_SHIFT 4
40
41enum { AXP_CPU_TO_NBCLK, AXP_CPU_TO_HCLK, AXP_CPU_TO_DRAMCLK };
42
43static const struct coreclk_ratio __initconst axp_coreclk_ratios[] = {
44 { .id = AXP_CPU_TO_NBCLK, .name = "nbclk" },
45 { .id = AXP_CPU_TO_HCLK, .name = "hclk" },
46 { .id = AXP_CPU_TO_DRAMCLK, .name = "dramclk" },
47};
48
49/* Armada XP TCLK frequency is fixed to 250MHz */
50static u32 __init axp_get_tclk_freq(void __iomem *sar)
51{
52 return 250000000;
53}
54
55static const u32 __initconst axp_cpu_freqs[] = {
56 1000000000,
57 1066000000,
58 1200000000,
59 1333000000,
60 1500000000,
61 1666000000,
62 1800000000,
63 2000000000,
64 667000000,
65 0,
66 800000000,
67 1600000000,
68};
69
70static u32 __init axp_get_cpu_freq(void __iomem *sar)
71{
72 u32 cpu_freq;
73 u8 cpu_freq_select = 0;
74
75 cpu_freq_select = ((readl(sar + SARL) >> SARL_AXP_PCLK_FREQ_OPT) &
76 SARL_AXP_PCLK_FREQ_OPT_MASK);
77 /*
78 * The upper bit is not contiguous to the other ones and
79 * located in the high part of the SAR registers
80 */
81 cpu_freq_select |= (((readl(sar + SARH) >> SARH_AXP_PCLK_FREQ_OPT) &
82 SARH_AXP_PCLK_FREQ_OPT_MASK) << SARH_AXP_PCLK_FREQ_OPT_SHIFT);
83 if (cpu_freq_select >= ARRAY_SIZE(axp_cpu_freqs)) {
84 pr_err("CPU freq select unsupported: %d\n", cpu_freq_select);
85 cpu_freq = 0;
86 } else
87 cpu_freq = axp_cpu_freqs[cpu_freq_select];
88
89 return cpu_freq;
90}
91
92static const int __initconst axp_nbclk_ratios[32][2] = {
93 {0, 1}, {1, 2}, {2, 2}, {2, 2},
94 {1, 2}, {1, 2}, {1, 1}, {2, 3},
95 {0, 1}, {1, 2}, {2, 4}, {0, 1},
96 {1, 2}, {0, 1}, {0, 1}, {2, 2},
97 {0, 1}, {0, 1}, {0, 1}, {1, 1},
98 {2, 3}, {0, 1}, {0, 1}, {0, 1},
99 {0, 1}, {0, 1}, {0, 1}, {1, 1},
100 {0, 1}, {0, 1}, {0, 1}, {0, 1},
101};
102
103static const int __initconst axp_hclk_ratios[32][2] = {
104 {0, 1}, {1, 2}, {2, 6}, {2, 3},
105 {1, 3}, {1, 4}, {1, 2}, {2, 6},
106 {0, 1}, {1, 6}, {2, 10}, {0, 1},
107 {1, 4}, {0, 1}, {0, 1}, {2, 5},
108 {0, 1}, {0, 1}, {0, 1}, {1, 2},
109 {2, 6}, {0, 1}, {0, 1}, {0, 1},
110 {0, 1}, {0, 1}, {0, 1}, {1, 1},
111 {0, 1}, {0, 1}, {0, 1}, {0, 1},
112};
113
114static const int __initconst axp_dramclk_ratios[32][2] = {
115 {0, 1}, {1, 2}, {2, 3}, {2, 3},
116 {1, 3}, {1, 2}, {1, 2}, {2, 6},
117 {0, 1}, {1, 3}, {2, 5}, {0, 1},
118 {1, 4}, {0, 1}, {0, 1}, {2, 5},
119 {0, 1}, {0, 1}, {0, 1}, {1, 1},
120 {2, 3}, {0, 1}, {0, 1}, {0, 1},
121 {0, 1}, {0, 1}, {0, 1}, {1, 1},
122 {0, 1}, {0, 1}, {0, 1}, {0, 1},
123};
124
125static void __init axp_get_clk_ratio(
126 void __iomem *sar, int id, int *mult, int *div)
127{
128 u32 opt = ((readl(sar + SARL) >> SARL_AXP_FAB_FREQ_OPT) &
129 SARL_AXP_FAB_FREQ_OPT_MASK);
130 /*
131 * The upper bit is not contiguous to the other ones and
132 * located in the high part of the SAR registers
133 */
134 opt |= (((readl(sar + SARH) >> SARH_AXP_FAB_FREQ_OPT) &
135 SARH_AXP_FAB_FREQ_OPT_MASK) << SARH_AXP_FAB_FREQ_OPT_SHIFT);
136
137 switch (id) {
138 case AXP_CPU_TO_NBCLK:
139 *mult = axp_nbclk_ratios[opt][0];
140 *div = axp_nbclk_ratios[opt][1];
141 break;
142 case AXP_CPU_TO_HCLK:
143 *mult = axp_hclk_ratios[opt][0];
144 *div = axp_hclk_ratios[opt][1];
145 break;
146 case AXP_CPU_TO_DRAMCLK:
147 *mult = axp_dramclk_ratios[opt][0];
148 *div = axp_dramclk_ratios[opt][1];
149 break;
150 }
151}
152
153static const struct coreclk_soc_desc axp_coreclks = {
154 .get_tclk_freq = axp_get_tclk_freq,
155 .get_cpu_freq = axp_get_cpu_freq,
156 .get_clk_ratio = axp_get_clk_ratio,
157 .ratios = axp_coreclk_ratios,
158 .num_ratios = ARRAY_SIZE(axp_coreclk_ratios),
159};
160
161static void __init axp_coreclk_init(struct device_node *np)
162{
163 mvebu_coreclk_setup(np, &axp_coreclks);
164}
165CLK_OF_DECLARE(axp_core_clk, "marvell,armada-xp-core-clock",
166 axp_coreclk_init);
167
168/*
169 * Clock Gating Control
170 */
171
172static const struct clk_gating_soc_desc __initconst axp_gating_desc[] = {
173 { "audio", NULL, 0, 0 },
174 { "ge3", NULL, 1, 0 },
175 { "ge2", NULL, 2, 0 },
176 { "ge1", NULL, 3, 0 },
177 { "ge0", NULL, 4, 0 },
178 { "pex00", NULL, 5, 0 },
179 { "pex01", NULL, 6, 0 },
180 { "pex02", NULL, 7, 0 },
181 { "pex03", NULL, 8, 0 },
182 { "pex10", NULL, 9, 0 },
183 { "pex11", NULL, 10, 0 },
184 { "pex12", NULL, 11, 0 },
185 { "pex13", NULL, 12, 0 },
186 { "bp", NULL, 13, 0 },
187 { "sata0lnk", NULL, 14, 0 },
188 { "sata0", "sata0lnk", 15, 0 },
189 { "lcd", NULL, 16, 0 },
190 { "sdio", NULL, 17, 0 },
191 { "usb0", NULL, 18, 0 },
192 { "usb1", NULL, 19, 0 },
193 { "usb2", NULL, 20, 0 },
194 { "xor0", NULL, 22, 0 },
195 { "crypto", NULL, 23, 0 },
196 { "tdm", NULL, 25, 0 },
197 { "pex20", NULL, 26, 0 },
198 { "pex30", NULL, 27, 0 },
199 { "xor1", NULL, 28, 0 },
200 { "sata1lnk", NULL, 29, 0 },
201 { "sata1", "sata1lnk", 30, 0 },
202 { }
203};
204
205static void __init axp_clk_gating_init(struct device_node *np)
206{
207 mvebu_clk_gating_setup(np, axp_gating_desc);
208}
209CLK_OF_DECLARE(axp_clk_gating, "marvell,armada-xp-gating-clock",
210 axp_clk_gating_init);
diff --git a/drivers/clk/mvebu/clk-core.c b/drivers/clk/mvebu/clk-core.c
deleted file mode 100644
index 0a53edbae8b8..000000000000
--- a/drivers/clk/mvebu/clk-core.c
+++ /dev/null
@@ -1,675 +0,0 @@
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 16600000,
130 20000000,
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}
diff --git a/drivers/clk/mvebu/clk-core.h b/drivers/clk/mvebu/clk-core.h
deleted file mode 100644
index 28b5e02e9885..000000000000
--- a/drivers/clk/mvebu/clk-core.h
+++ /dev/null
@@ -1,18 +0,0 @@
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 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12
13#ifndef __MVEBU_CLK_CORE_H
14#define __MVEBU_CLK_CORE_H
15
16void __init mvebu_core_clk_init(void);
17
18#endif
diff --git a/drivers/clk/mvebu/clk-gating-ctrl.c b/drivers/clk/mvebu/clk-gating-ctrl.c
deleted file mode 100644
index 2f037235bdbd..000000000000
--- a/drivers/clk/mvebu/clk-gating-ctrl.c
+++ /dev/null
@@ -1,256 +0,0 @@
1/*
2 * Marvell MVEBU clock gating control.
3 *
4 * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
5 * Andrew Lunn <andrew@lunn.ch>
6 *
7 * This file is licensed under the terms of the GNU General Public
8 * License version 2. This program is licensed "as is" without any
9 * warranty of any kind, whether express or implied.
10 */
11#include <linux/kernel.h>
12#include <linux/bitops.h>
13#include <linux/io.h>
14#include <linux/clk.h>
15#include <linux/clkdev.h>
16#include <linux/clk-provider.h>
17#include <linux/clk/mvebu.h>
18#include <linux/of.h>
19#include <linux/of_address.h>
20
21struct mvebu_gating_ctrl {
22 spinlock_t lock;
23 struct clk **gates;
24 int num_gates;
25};
26
27struct mvebu_soc_descr {
28 const char *name;
29 const char *parent;
30 int bit_idx;
31};
32
33#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
34
35static struct clk *mvebu_clk_gating_get_src(
36 struct of_phandle_args *clkspec, void *data)
37{
38 struct mvebu_gating_ctrl *ctrl = (struct mvebu_gating_ctrl *)data;
39 int n;
40
41 if (clkspec->args_count < 1)
42 return ERR_PTR(-EINVAL);
43
44 for (n = 0; n < ctrl->num_gates; n++) {
45 struct clk_gate *gate =
46 to_clk_gate(__clk_get_hw(ctrl->gates[n]));
47 if (clkspec->args[0] == gate->bit_idx)
48 return ctrl->gates[n];
49 }
50 return ERR_PTR(-ENODEV);
51}
52
53static void __init mvebu_clk_gating_setup(
54 struct device_node *np, const struct mvebu_soc_descr *descr)
55{
56 struct mvebu_gating_ctrl *ctrl;
57 struct clk *clk;
58 void __iomem *base;
59 const char *default_parent = NULL;
60 int n;
61
62 base = of_iomap(np, 0);
63
64 clk = of_clk_get(np, 0);
65 if (!IS_ERR(clk)) {
66 default_parent = __clk_get_name(clk);
67 clk_put(clk);
68 }
69
70 ctrl = kzalloc(sizeof(struct mvebu_gating_ctrl), GFP_KERNEL);
71 if (WARN_ON(!ctrl))
72 return;
73
74 spin_lock_init(&ctrl->lock);
75
76 /*
77 * Count, allocate, and register clock gates
78 */
79 for (n = 0; descr[n].name;)
80 n++;
81
82 ctrl->num_gates = n;
83 ctrl->gates = kzalloc(ctrl->num_gates * sizeof(struct clk *),
84 GFP_KERNEL);
85 if (WARN_ON(!ctrl->gates)) {
86 kfree(ctrl);
87 return;
88 }
89
90 for (n = 0; n < ctrl->num_gates; n++) {
91 u8 flags = 0;
92 const char *parent =
93 (descr[n].parent) ? descr[n].parent : default_parent;
94
95 /*
96 * On Armada 370, the DDR clock is a special case: it
97 * isn't taken by any driver, but should anyway be
98 * kept enabled, so we mark it as IGNORE_UNUSED for
99 * now.
100 */
101 if (!strcmp(descr[n].name, "ddr"))
102 flags |= CLK_IGNORE_UNUSED;
103
104 ctrl->gates[n] = clk_register_gate(NULL, descr[n].name, parent,
105 flags, base, descr[n].bit_idx, 0, &ctrl->lock);
106 WARN_ON(IS_ERR(ctrl->gates[n]));
107 }
108 of_clk_add_provider(np, mvebu_clk_gating_get_src, ctrl);
109}
110
111/*
112 * SoC specific clock gating control
113 */
114
115#ifdef CONFIG_MACH_ARMADA_370
116static const struct mvebu_soc_descr __initconst armada_370_gating_descr[] = {
117 { "audio", NULL, 0 },
118 { "pex0_en", NULL, 1 },
119 { "pex1_en", NULL, 2 },
120 { "ge1", NULL, 3 },
121 { "ge0", NULL, 4 },
122 { "pex0", "pex0_en", 5 },
123 { "pex1", "pex1_en", 9 },
124 { "sata0", NULL, 15 },
125 { "sdio", NULL, 17 },
126 { "tdm", NULL, 25 },
127 { "ddr", NULL, 28 },
128 { "sata1", NULL, 30 },
129 { }
130};
131#endif
132
133#ifdef CONFIG_MACH_ARMADA_XP
134static const struct mvebu_soc_descr __initconst armada_xp_gating_descr[] = {
135 { "audio", NULL, 0 },
136 { "ge3", NULL, 1 },
137 { "ge2", NULL, 2 },
138 { "ge1", NULL, 3 },
139 { "ge0", NULL, 4 },
140 { "pex00", NULL, 5 },
141 { "pex01", NULL, 6 },
142 { "pex02", NULL, 7 },
143 { "pex03", NULL, 8 },
144 { "pex10", NULL, 9 },
145 { "pex11", NULL, 10 },
146 { "pex12", NULL, 11 },
147 { "pex13", NULL, 12 },
148 { "bp", NULL, 13 },
149 { "sata0lnk", NULL, 14 },
150 { "sata0", "sata0lnk", 15 },
151 { "lcd", NULL, 16 },
152 { "sdio", NULL, 17 },
153 { "usb0", NULL, 18 },
154 { "usb1", NULL, 19 },
155 { "usb2", NULL, 20 },
156 { "xor0", NULL, 22 },
157 { "crypto", NULL, 23 },
158 { "tdm", NULL, 25 },
159 { "pex20", NULL, 26 },
160 { "pex30", NULL, 27 },
161 { "xor1", NULL, 28 },
162 { "sata1lnk", NULL, 29 },
163 { "sata1", "sata1lnk", 30 },
164 { }
165};
166#endif
167
168#ifdef CONFIG_ARCH_DOVE
169static const struct mvebu_soc_descr __initconst dove_gating_descr[] = {
170 { "usb0", NULL, 0 },
171 { "usb1", NULL, 1 },
172 { "ge", "gephy", 2 },
173 { "sata", NULL, 3 },
174 { "pex0", NULL, 4 },
175 { "pex1", NULL, 5 },
176 { "sdio0", NULL, 8 },
177 { "sdio1", NULL, 9 },
178 { "nand", NULL, 10 },
179 { "camera", NULL, 11 },
180 { "i2s0", NULL, 12 },
181 { "i2s1", NULL, 13 },
182 { "crypto", NULL, 15 },
183 { "ac97", NULL, 21 },
184 { "pdma", NULL, 22 },
185 { "xor0", NULL, 23 },
186 { "xor1", NULL, 24 },
187 { "gephy", NULL, 30 },
188 { }
189};
190#endif
191
192#ifdef CONFIG_ARCH_KIRKWOOD
193static const struct mvebu_soc_descr __initconst kirkwood_gating_descr[] = {
194 { "ge0", NULL, 0 },
195 { "pex0", NULL, 2 },
196 { "usb0", NULL, 3 },
197 { "sdio", NULL, 4 },
198 { "tsu", NULL, 5 },
199 { "runit", NULL, 7 },
200 { "xor0", NULL, 8 },
201 { "audio", NULL, 9 },
202 { "powersave", "cpuclk", 11 },
203 { "sata0", NULL, 14 },
204 { "sata1", NULL, 15 },
205 { "xor1", NULL, 16 },
206 { "crypto", NULL, 17 },
207 { "pex1", NULL, 18 },
208 { "ge1", NULL, 19 },
209 { "tdm", NULL, 20 },
210 { }
211};
212#endif
213
214static const __initdata struct of_device_id clk_gating_match[] = {
215#ifdef CONFIG_MACH_ARMADA_370
216 {
217 .compatible = "marvell,armada-370-gating-clock",
218 .data = armada_370_gating_descr,
219 },
220#endif
221
222#ifdef CONFIG_MACH_ARMADA_XP
223 {
224 .compatible = "marvell,armada-xp-gating-clock",
225 .data = armada_xp_gating_descr,
226 },
227#endif
228
229#ifdef CONFIG_ARCH_DOVE
230 {
231 .compatible = "marvell,dove-gating-clock",
232 .data = dove_gating_descr,
233 },
234#endif
235
236#ifdef CONFIG_ARCH_KIRKWOOD
237 {
238 .compatible = "marvell,kirkwood-gating-clock",
239 .data = kirkwood_gating_descr,
240 },
241#endif
242
243 { }
244};
245
246void __init mvebu_gating_clk_init(void)
247{
248 struct device_node *np;
249
250 for_each_matching_node(np, clk_gating_match) {
251 const struct of_device_id *match =
252 of_match_node(clk_gating_match, np);
253 mvebu_clk_gating_setup(np,
254 (const struct mvebu_soc_descr *)match->data);
255 }
256}
diff --git a/drivers/clk/mvebu/clk-gating-ctrl.h b/drivers/clk/mvebu/clk-gating-ctrl.h
deleted file mode 100644
index 9275d1e51f1b..000000000000
--- a/drivers/clk/mvebu/clk-gating-ctrl.h
+++ /dev/null
@@ -1,22 +0,0 @@
1/*
2 * Marvell EBU gating clock handling
3 *
4 * Copyright (C) 2012 Marvell
5 *
6 * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12
13#ifndef __MVEBU_CLK_GATING_H
14#define __MVEBU_CLK_GATING_H
15
16#ifdef CONFIG_MVEBU_CLK_GATING
17void __init mvebu_gating_clk_init(void);
18#else
19void mvebu_gating_clk_init(void) {}
20#endif
21
22#endif
diff --git a/drivers/clk/mvebu/clk.c b/drivers/clk/mvebu/clk.c
deleted file mode 100644
index 29f10fb3006c..000000000000
--- a/drivers/clk/mvebu/clk.c
+++ /dev/null
@@ -1,23 +0,0 @@
1/*
2 * Marvell EBU SoC clock handling.
3 *
4 * Copyright (C) 2012 Marvell
5 *
6 * Gregory CLEMENT <gregory.clement@free-electrons.com>
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12#include <linux/kernel.h>
13#include <linux/clk-provider.h>
14#include <linux/of.h>
15#include "clk-core.h"
16#include "clk-gating-ctrl.h"
17
18void __init mvebu_clocks_init(void)
19{
20 mvebu_core_clk_init();
21 mvebu_gating_clk_init();
22 of_clk_init(NULL);
23}
diff --git a/drivers/clk/mvebu/common.c b/drivers/clk/mvebu/common.c
new file mode 100644
index 000000000000..adaa4a1821b8
--- /dev/null
+++ b/drivers/clk/mvebu/common.c
@@ -0,0 +1,163 @@
1/*
2 * Marvell EBU SoC common clock handling
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.h>
17#include <linux/clkdev.h>
18#include <linux/clk-provider.h>
19#include <linux/io.h>
20#include <linux/of.h>
21#include <linux/of_address.h>
22
23#include "common.h"
24
25/*
26 * Core Clocks
27 */
28
29static struct clk_onecell_data clk_data;
30
31void __init mvebu_coreclk_setup(struct device_node *np,
32 const struct coreclk_soc_desc *desc)
33{
34 const char *tclk_name = "tclk";
35 const char *cpuclk_name = "cpuclk";
36 void __iomem *base;
37 unsigned long rate;
38 int n;
39
40 base = of_iomap(np, 0);
41 if (WARN_ON(!base))
42 return;
43
44 /* Allocate struct for TCLK, cpu clk, and core ratio clocks */
45 clk_data.clk_num = 2 + desc->num_ratios;
46 clk_data.clks = kzalloc(clk_data.clk_num * sizeof(struct clk *),
47 GFP_KERNEL);
48 if (WARN_ON(!clk_data.clks))
49 return;
50
51 /* Register TCLK */
52 of_property_read_string_index(np, "clock-output-names", 0,
53 &tclk_name);
54 rate = desc->get_tclk_freq(base);
55 clk_data.clks[0] = clk_register_fixed_rate(NULL, tclk_name, NULL,
56 CLK_IS_ROOT, rate);
57 WARN_ON(IS_ERR(clk_data.clks[0]));
58
59 /* Register CPU clock */
60 of_property_read_string_index(np, "clock-output-names", 1,
61 &cpuclk_name);
62 rate = desc->get_cpu_freq(base);
63 clk_data.clks[1] = clk_register_fixed_rate(NULL, cpuclk_name, NULL,
64 CLK_IS_ROOT, rate);
65 WARN_ON(IS_ERR(clk_data.clks[1]));
66
67 /* Register fixed-factor clocks derived from CPU clock */
68 for (n = 0; n < desc->num_ratios; n++) {
69 const char *rclk_name = desc->ratios[n].name;
70 int mult, div;
71
72 of_property_read_string_index(np, "clock-output-names",
73 2+n, &rclk_name);
74 desc->get_clk_ratio(base, desc->ratios[n].id, &mult, &div);
75 clk_data.clks[2+n] = clk_register_fixed_factor(NULL, rclk_name,
76 cpuclk_name, 0, mult, div);
77 WARN_ON(IS_ERR(clk_data.clks[2+n]));
78 };
79
80 /* SAR register isn't needed anymore */
81 iounmap(base);
82
83 of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
84}
85
86/*
87 * Clock Gating Control
88 */
89
90struct clk_gating_ctrl {
91 spinlock_t lock;
92 struct clk **gates;
93 int num_gates;
94};
95
96#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
97
98static struct clk *clk_gating_get_src(
99 struct of_phandle_args *clkspec, void *data)
100{
101 struct clk_gating_ctrl *ctrl = (struct clk_gating_ctrl *)data;
102 int n;
103
104 if (clkspec->args_count < 1)
105 return ERR_PTR(-EINVAL);
106
107 for (n = 0; n < ctrl->num_gates; n++) {
108 struct clk_gate *gate =
109 to_clk_gate(__clk_get_hw(ctrl->gates[n]));
110 if (clkspec->args[0] == gate->bit_idx)
111 return ctrl->gates[n];
112 }
113 return ERR_PTR(-ENODEV);
114}
115
116void __init mvebu_clk_gating_setup(struct device_node *np,
117 const struct clk_gating_soc_desc *desc)
118{
119 struct clk_gating_ctrl *ctrl;
120 struct clk *clk;
121 void __iomem *base;
122 const char *default_parent = NULL;
123 int n;
124
125 base = of_iomap(np, 0);
126 if (WARN_ON(!base))
127 return;
128
129 clk = of_clk_get(np, 0);
130 if (!IS_ERR(clk)) {
131 default_parent = __clk_get_name(clk);
132 clk_put(clk);
133 }
134
135 ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
136 if (WARN_ON(!ctrl))
137 return;
138
139 spin_lock_init(&ctrl->lock);
140
141 /* Count, allocate, and register clock gates */
142 for (n = 0; desc[n].name;)
143 n++;
144
145 ctrl->num_gates = n;
146 ctrl->gates = kzalloc(ctrl->num_gates * sizeof(struct clk *),
147 GFP_KERNEL);
148 if (WARN_ON(!ctrl->gates)) {
149 kfree(ctrl);
150 return;
151 }
152
153 for (n = 0; n < ctrl->num_gates; n++) {
154 const char *parent =
155 (desc[n].parent) ? desc[n].parent : default_parent;
156 ctrl->gates[n] = clk_register_gate(NULL, desc[n].name, parent,
157 desc[n].flags, base, desc[n].bit_idx,
158 0, &ctrl->lock);
159 WARN_ON(IS_ERR(ctrl->gates[n]));
160 }
161
162 of_clk_add_provider(np, clk_gating_get_src, ctrl);
163}
diff --git a/drivers/clk/mvebu/common.h b/drivers/clk/mvebu/common.h
new file mode 100644
index 000000000000..f968b4d9df92
--- /dev/null
+++ b/drivers/clk/mvebu/common.h
@@ -0,0 +1,48 @@
1/*
2 * Marvell EBU SoC common clock handling
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#ifndef __CLK_MVEBU_COMMON_H_
16#define __CLK_MVEBU_COMMON_H_
17
18#include <linux/kernel.h>
19
20struct device_node;
21
22struct coreclk_ratio {
23 int id;
24 const char *name;
25};
26
27struct coreclk_soc_desc {
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 coreclk_ratio *ratios;
32 int num_ratios;
33};
34
35struct clk_gating_soc_desc {
36 const char *name;
37 const char *parent;
38 int bit_idx;
39 unsigned long flags;
40};
41
42void __init mvebu_coreclk_setup(struct device_node *np,
43 const struct coreclk_soc_desc *desc);
44
45void __init mvebu_clk_gating_setup(struct device_node *np,
46 const struct clk_gating_soc_desc *desc);
47
48#endif
diff --git a/drivers/clk/mvebu/dove.c b/drivers/clk/mvebu/dove.c
new file mode 100644
index 000000000000..79d7aedf03fb
--- /dev/null
+++ b/drivers/clk/mvebu/dove.c
@@ -0,0 +1,194 @@
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 __initconst dove_coreclk_ratios[] = {
78 { .id = DOVE_CPU_TO_L2, .name = "l2clk", },
79 { .id = DOVE_CPU_TO_DDR, .name = "ddrclk", }
80};
81
82static const u32 __initconst dove_tclk_freqs[] = {
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 __initconst dove_cpu_freqs[] = {
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 __initconst dove_cpu_l2_ratios[8][2] = {
115 { 1, 1 }, { 0, 1 }, { 1, 2 }, { 0, 1 },
116 { 1, 3 }, { 0, 1 }, { 1, 4 }, { 0, 1 }
117};
118
119static const int __initconst dove_cpu_ddr_ratios[16][2] = {
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
157static void __init dove_coreclk_init(struct device_node *np)
158{
159 mvebu_coreclk_setup(np, &dove_coreclks);
160}
161CLK_OF_DECLARE(dove_core_clk, "marvell,dove-core-clock", dove_coreclk_init);
162
163/*
164 * Clock Gating Control
165 */
166
167static const struct clk_gating_soc_desc __initconst dove_gating_desc[] = {
168 { "usb0", NULL, 0, 0 },
169 { "usb1", NULL, 1, 0 },
170 { "ge", "gephy", 2, 0 },
171 { "sata", NULL, 3, 0 },
172 { "pex0", NULL, 4, 0 },
173 { "pex1", NULL, 5, 0 },
174 { "sdio0", NULL, 8, 0 },
175 { "sdio1", NULL, 9, 0 },
176 { "nand", NULL, 10, 0 },
177 { "camera", NULL, 11, 0 },
178 { "i2s0", NULL, 12, 0 },
179 { "i2s1", NULL, 13, 0 },
180 { "crypto", NULL, 15, 0 },
181 { "ac97", NULL, 21, 0 },
182 { "pdma", NULL, 22, 0 },
183 { "xor0", NULL, 23, 0 },
184 { "xor1", NULL, 24, 0 },
185 { "gephy", NULL, 30, 0 },
186 { }
187};
188
189static void __init dove_clk_gating_init(struct device_node *np)
190{
191 mvebu_clk_gating_setup(np, dove_gating_desc);
192}
193CLK_OF_DECLARE(dove_clk_gating, "marvell,dove-gating-clock",
194 dove_clk_gating_init);
diff --git a/drivers/clk/mvebu/kirkwood.c b/drivers/clk/mvebu/kirkwood.c
new file mode 100644
index 000000000000..71d24619ccdb
--- /dev/null
+++ b/drivers/clk/mvebu/kirkwood.c
@@ -0,0 +1,247 @@
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
81static const struct coreclk_ratio __initconst kirkwood_coreclk_ratios[] = {
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
93static const u32 __initconst kirkwood_cpu_freqs[] = {
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
114static const int __initconst kirkwood_cpu_l2_ratios[8][2] = {
115 { 0, 1 }, { 1, 2 }, { 0, 1 }, { 1, 3 },
116 { 0, 1 }, { 1, 4 }, { 0, 1 }, { 0, 1 }
117};
118
119static const int __initconst kirkwood_cpu_ddr_ratios[16][2] = {
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
148static const u32 __initconst mv88f6180_cpu_freqs[] = {
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
161static const int __initconst mv88f6180_cpu_ddr_ratios[8][2] = {
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
222static const struct clk_gating_soc_desc __initconst kirkwood_gating_desc[] = {
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);