diff options
author | Olof Johansson <olof@lixom.net> | 2013-06-01 02:23:25 -0400 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2013-06-01 02:23:25 -0400 |
commit | 85b9174fda1d516198b4a46a7795e43636a3ea4c (patch) | |
tree | 2721a32c07ca3e1d46df573a19b4e92853688966 /drivers/clk | |
parent | 2dbefbf6a803d65f6327fe617f5e1960f218ce01 (diff) | |
parent | ea7e0bd7e78868bbe6df6834595ef96166dd296a (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/Kconfig | 25 | ||||
-rw-r--r-- | drivers/clk/mvebu/Makefile | 8 | ||||
-rw-r--r-- | drivers/clk/mvebu/armada-370.c | 176 | ||||
-rw-r--r-- | drivers/clk/mvebu/armada-xp.c | 210 | ||||
-rw-r--r-- | drivers/clk/mvebu/clk-core.c | 675 | ||||
-rw-r--r-- | drivers/clk/mvebu/clk-core.h | 18 | ||||
-rw-r--r-- | drivers/clk/mvebu/clk-gating-ctrl.c | 256 | ||||
-rw-r--r-- | drivers/clk/mvebu/clk-gating-ctrl.h | 22 | ||||
-rw-r--r-- | drivers/clk/mvebu/clk.c | 23 | ||||
-rw-r--r-- | drivers/clk/mvebu/common.c | 163 | ||||
-rw-r--r-- | drivers/clk/mvebu/common.h | 48 | ||||
-rw-r--r-- | drivers/clk/mvebu/dove.c | 194 | ||||
-rw-r--r-- | drivers/clk/mvebu/kirkwood.c | 247 |
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 @@ | |||
1 | config MVEBU_CLK_CORE | 1 | config MVEBU_CLK_COMMON |
2 | bool | 2 | bool |
3 | 3 | ||
4 | config MVEBU_CLK_CPU | 4 | config MVEBU_CLK_CPU |
5 | bool | 5 | bool |
6 | 6 | ||
7 | config MVEBU_CLK_GATING | 7 | config ARMADA_370_CLK |
8 | bool | 8 | bool |
9 | select MVEBU_CLK_COMMON | ||
10 | select MVEBU_CLK_CPU | ||
11 | |||
12 | config ARMADA_XP_CLK | ||
13 | bool | ||
14 | select MVEBU_CLK_COMMON | ||
15 | select MVEBU_CLK_CPU | ||
16 | |||
17 | config DOVE_CLK | ||
18 | bool | ||
19 | select MVEBU_CLK_COMMON | ||
20 | |||
21 | config 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 @@ | |||
1 | obj-$(CONFIG_MVEBU_CLK_CORE) += clk.o clk-core.o | 1 | obj-$(CONFIG_MVEBU_CLK_COMMON) += common.o |
2 | obj-$(CONFIG_MVEBU_CLK_CPU) += clk-cpu.o | 2 | obj-$(CONFIG_MVEBU_CLK_CPU) += clk-cpu.o |
3 | obj-$(CONFIG_MVEBU_CLK_GATING) += clk-gating-ctrl.o | 3 | |
4 | obj-$(CONFIG_ARMADA_370_CLK) += armada-370.o | ||
5 | obj-$(CONFIG_ARMADA_XP_CLK) += armada-xp.o | ||
6 | obj-$(CONFIG_DOVE_CLK) += dove.o | ||
7 | obj-$(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 | |||
33 | enum { A370_CPU_TO_NBCLK, A370_CPU_TO_HCLK, A370_CPU_TO_DRAMCLK }; | ||
34 | |||
35 | static 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 | |||
41 | static const u32 __initconst a370_tclk_freqs[] = { | ||
42 | 16600000, | ||
43 | 20000000, | ||
44 | }; | ||
45 | |||
46 | static 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 | |||
55 | static const u32 __initconst a370_cpu_freqs[] = { | ||
56 | 400000000, | ||
57 | 533000000, | ||
58 | 667000000, | ||
59 | 800000000, | ||
60 | 1000000000, | ||
61 | 1067000000, | ||
62 | 1200000000, | ||
63 | }; | ||
64 | |||
65 | static 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 | |||
81 | static 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 | |||
92 | static 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 | |||
103 | static 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 | |||
114 | static 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 | |||
136 | static 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 | |||
144 | static void __init a370_coreclk_init(struct device_node *np) | ||
145 | { | ||
146 | mvebu_coreclk_setup(np, &a370_coreclks); | ||
147 | } | ||
148 | CLK_OF_DECLARE(a370_core_clk, "marvell,armada-370-core-clock", | ||
149 | a370_coreclk_init); | ||
150 | |||
151 | /* | ||
152 | * Clock Gating Control | ||
153 | */ | ||
154 | |||
155 | static 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 | |||
171 | static void __init a370_clk_gating_init(struct device_node *np) | ||
172 | { | ||
173 | mvebu_clk_gating_setup(np, a370_gating_desc); | ||
174 | } | ||
175 | CLK_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 | |||
41 | enum { AXP_CPU_TO_NBCLK, AXP_CPU_TO_HCLK, AXP_CPU_TO_DRAMCLK }; | ||
42 | |||
43 | static 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 */ | ||
50 | static u32 __init axp_get_tclk_freq(void __iomem *sar) | ||
51 | { | ||
52 | return 250000000; | ||
53 | } | ||
54 | |||
55 | static 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 | |||
70 | static 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 | |||
92 | static 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 | |||
103 | static 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 | |||
114 | static 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 | |||
125 | static 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 | |||
153 | static 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 | |||
161 | static void __init axp_coreclk_init(struct device_node *np) | ||
162 | { | ||
163 | mvebu_coreclk_setup(np, &axp_coreclks); | ||
164 | } | ||
165 | CLK_OF_DECLARE(axp_core_clk, "marvell,armada-xp-core-clock", | ||
166 | axp_coreclk_init); | ||
167 | |||
168 | /* | ||
169 | * Clock Gating Control | ||
170 | */ | ||
171 | |||
172 | static 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 | |||
205 | static void __init axp_clk_gating_init(struct device_node *np) | ||
206 | { | ||
207 | mvebu_clk_gating_setup(np, axp_gating_desc); | ||
208 | } | ||
209 | CLK_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 | |||
22 | struct core_ratio { | ||
23 | int id; | ||
24 | const char *name; | ||
25 | }; | ||
26 | |||
27 | struct 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 | |||
35 | static struct clk_onecell_data clk_data; | ||
36 | |||
37 | static 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 | |||
128 | static const u32 __initconst armada_370_tclk_frequencies[] = { | ||
129 | 16600000, | ||
130 | 20000000, | ||
131 | }; | ||
132 | |||
133 | static 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 | |||
142 | static const u32 __initconst armada_370_cpu_frequencies[] = { | ||
143 | 400000000, | ||
144 | 533000000, | ||
145 | 667000000, | ||
146 | 800000000, | ||
147 | 1000000000, | ||
148 | 1067000000, | ||
149 | 1200000000, | ||
150 | }; | ||
151 | |||
152 | static 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 | |||
168 | enum { A370_XP_NBCLK, A370_XP_HCLK, A370_XP_DRAMCLK }; | ||
169 | |||
170 | static 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 | |||
176 | static 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 | |||
187 | static 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 | |||
198 | static 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 | |||
209 | static 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 | |||
228 | static 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 | |||
238 | static 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 | |||
246 | static 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 */ | ||
262 | static u32 __init armada_xp_get_tclk_freq(void __iomem *sar) | ||
263 | { | ||
264 | return 250 * 1000 * 1000; | ||
265 | } | ||
266 | |||
267 | static 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 | |||
290 | static 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 | |||
307 | static 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 | |||
369 | static const u32 __initconst dove_tclk_frequencies[] = { | ||
370 | 166666667, | ||
371 | 125000000, | ||
372 | 0, 0 | ||
373 | }; | ||
374 | |||
375 | static 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 | |||
382 | static 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 | |||
394 | static 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 | |||
401 | enum { DOVE_CPU_TO_L2, DOVE_CPU_TO_DDR }; | ||
402 | |||
403 | static 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 | |||
408 | static 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 | |||
413 | static 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 | |||
420 | static 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 | |||
443 | static 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 | |||
508 | enum { KIRKWOOD_CPU_TO_L2, KIRKWOOD_CPU_TO_DDR }; | ||
509 | |||
510 | static 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 | |||
515 | static 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 | |||
522 | static 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 | |||
537 | static 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 | |||
543 | static 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 | |||
548 | static 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 | |||
555 | static 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 | |||
577 | static 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 | |||
585 | static const u32 __initconst mv88f6180_cpu_frequencies[] = { | ||
586 | 0, 0, 0, 0, 0, | ||
587 | 600000000, | ||
588 | 800000000, | ||
589 | 1000000000 | ||
590 | }; | ||
591 | |||
592 | static 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 | |||
598 | static 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 | |||
603 | static 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 | |||
625 | static 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 | |||
634 | static 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 | |||
666 | void __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 | |||
16 | void __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 | |||
21 | struct mvebu_gating_ctrl { | ||
22 | spinlock_t lock; | ||
23 | struct clk **gates; | ||
24 | int num_gates; | ||
25 | }; | ||
26 | |||
27 | struct 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 | |||
35 | static 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 | |||
53 | static 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 | ||
116 | static 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 | ||
134 | static 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 | ||
169 | static 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 | ||
193 | static 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 | |||
214 | static 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 | |||
246 | void __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 | ||
17 | void __init mvebu_gating_clk_init(void); | ||
18 | #else | ||
19 | void 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 | |||
18 | void __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 | |||
29 | static struct clk_onecell_data clk_data; | ||
30 | |||
31 | void __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 | |||
90 | struct 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 | |||
98 | static 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 | |||
116 | void __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 | |||
20 | struct device_node; | ||
21 | |||
22 | struct coreclk_ratio { | ||
23 | int id; | ||
24 | const char *name; | ||
25 | }; | ||
26 | |||
27 | struct 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 | |||
35 | struct clk_gating_soc_desc { | ||
36 | const char *name; | ||
37 | const char *parent; | ||
38 | int bit_idx; | ||
39 | unsigned long flags; | ||
40 | }; | ||
41 | |||
42 | void __init mvebu_coreclk_setup(struct device_node *np, | ||
43 | const struct coreclk_soc_desc *desc); | ||
44 | |||
45 | void __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 | |||
75 | enum { DOVE_CPU_TO_L2, DOVE_CPU_TO_DDR }; | ||
76 | |||
77 | static 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 | |||
82 | static const u32 __initconst dove_tclk_freqs[] = { | ||
83 | 166666667, | ||
84 | 125000000, | ||
85 | 0, 0 | ||
86 | }; | ||
87 | |||
88 | static 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 | |||
95 | static 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 | |||
107 | static 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 | |||
114 | static 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 | |||
119 | static 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 | |||
126 | static 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 | |||
149 | static 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 | static void __init dove_coreclk_init(struct device_node *np) | ||
158 | { | ||
159 | mvebu_coreclk_setup(np, &dove_coreclks); | ||
160 | } | ||
161 | CLK_OF_DECLARE(dove_core_clk, "marvell,dove-core-clock", dove_coreclk_init); | ||
162 | |||
163 | /* | ||
164 | * Clock Gating Control | ||
165 | */ | ||
166 | |||
167 | static 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 | |||
189 | static void __init dove_clk_gating_init(struct device_node *np) | ||
190 | { | ||
191 | mvebu_clk_gating_setup(np, dove_gating_desc); | ||
192 | } | ||
193 | CLK_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 | |||
79 | enum { KIRKWOOD_CPU_TO_L2, KIRKWOOD_CPU_TO_DDR }; | ||
80 | |||
81 | static 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 | |||
86 | static 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 | |||
93 | static 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 | |||
108 | static 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 | |||
114 | static 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 | |||
119 | static 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 | |||
126 | static 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 | |||
148 | static const u32 __initconst mv88f6180_cpu_freqs[] = { | ||
149 | 0, 0, 0, 0, 0, | ||
150 | 600000000, | ||
151 | 800000000, | ||
152 | 1000000000 | ||
153 | }; | ||
154 | |||
155 | static 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 | |||
161 | static 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 | |||
166 | static 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 | |||
188 | static 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 | |||
196 | static void __init kirkwood_coreclk_init(struct device_node *np) | ||
197 | { | ||
198 | mvebu_coreclk_setup(np, &kirkwood_coreclks); | ||
199 | } | ||
200 | CLK_OF_DECLARE(kirkwood_core_clk, "marvell,kirkwood-core-clock", | ||
201 | kirkwood_coreclk_init); | ||
202 | |||
203 | static 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 | |||
211 | static void __init mv88f6180_coreclk_init(struct device_node *np) | ||
212 | { | ||
213 | mvebu_coreclk_setup(np, &mv88f6180_coreclks); | ||
214 | } | ||
215 | CLK_OF_DECLARE(mv88f6180_core_clk, "marvell,mv88f6180-core-clock", | ||
216 | mv88f6180_coreclk_init); | ||
217 | |||
218 | /* | ||
219 | * Clock Gating Control | ||
220 | */ | ||
221 | |||
222 | static 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 | |||
242 | static void __init kirkwood_clk_gating_init(struct device_node *np) | ||
243 | { | ||
244 | mvebu_clk_gating_setup(np, kirkwood_gating_desc); | ||
245 | } | ||
246 | CLK_OF_DECLARE(kirkwood_clk_gating, "marvell,kirkwood-gating-clock", | ||
247 | kirkwood_clk_gating_init); | ||