diff options
Diffstat (limited to 'drivers/clk/mvebu/armada-375.c')
-rw-r--r-- | drivers/clk/mvebu/armada-375.c | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/drivers/clk/mvebu/armada-375.c b/drivers/clk/mvebu/armada-375.c new file mode 100644 index 000000000000..c991a4d95e10 --- /dev/null +++ b/drivers/clk/mvebu/armada-375.c | |||
@@ -0,0 +1,184 @@ | |||
1 | /* | ||
2 | * Marvell Armada 375 SoC clocks | ||
3 | * | ||
4 | * Copyright (C) 2014 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 | /* | ||
26 | * For the Armada 375 SoCs, the CPU, DDR and L2 clocks frequencies are | ||
27 | * all modified at the same time, and not separately as for the Armada | ||
28 | * 370 or the Armada XP SoCs. | ||
29 | * | ||
30 | * SAR0[21:17] : CPU frequency DDR frequency L2 frequency | ||
31 | * 6 = 400 MHz 400 MHz 200 MHz | ||
32 | * 15 = 600 MHz 600 MHz 300 MHz | ||
33 | * 21 = 800 MHz 534 MHz 400 MHz | ||
34 | * 25 = 1000 MHz 500 MHz 500 MHz | ||
35 | * others reserved. | ||
36 | * | ||
37 | * SAR0[22] : TCLK frequency | ||
38 | * 0 = 166 MHz | ||
39 | * 1 = 200 MHz | ||
40 | */ | ||
41 | |||
42 | #define SAR1_A375_TCLK_FREQ_OPT 22 | ||
43 | #define SAR1_A375_TCLK_FREQ_OPT_MASK 0x1 | ||
44 | #define SAR1_A375_CPU_DDR_L2_FREQ_OPT 17 | ||
45 | #define SAR1_A375_CPU_DDR_L2_FREQ_OPT_MASK 0x1F | ||
46 | |||
47 | static const u32 armada_375_tclk_frequencies[] __initconst = { | ||
48 | 166000000, | ||
49 | 200000000, | ||
50 | }; | ||
51 | |||
52 | static u32 __init armada_375_get_tclk_freq(void __iomem *sar) | ||
53 | { | ||
54 | u8 tclk_freq_select; | ||
55 | |||
56 | tclk_freq_select = ((readl(sar) >> SAR1_A375_TCLK_FREQ_OPT) & | ||
57 | SAR1_A375_TCLK_FREQ_OPT_MASK); | ||
58 | return armada_375_tclk_frequencies[tclk_freq_select]; | ||
59 | } | ||
60 | |||
61 | |||
62 | static const u32 armada_375_cpu_frequencies[] __initconst = { | ||
63 | 0, 0, 0, 0, 0, 0, | ||
64 | 400000000, | ||
65 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
66 | 600000000, | ||
67 | 0, 0, 0, 0, 0, | ||
68 | 800000000, | ||
69 | 0, 0, 0, | ||
70 | 1000000000, | ||
71 | }; | ||
72 | |||
73 | static u32 __init armada_375_get_cpu_freq(void __iomem *sar) | ||
74 | { | ||
75 | u8 cpu_freq_select; | ||
76 | |||
77 | cpu_freq_select = ((readl(sar) >> SAR1_A375_CPU_DDR_L2_FREQ_OPT) & | ||
78 | SAR1_A375_CPU_DDR_L2_FREQ_OPT_MASK); | ||
79 | if (cpu_freq_select >= ARRAY_SIZE(armada_375_cpu_frequencies)) { | ||
80 | pr_err("Selected CPU frequency (%d) unsupported\n", | ||
81 | cpu_freq_select); | ||
82 | return 0; | ||
83 | } else | ||
84 | return armada_375_cpu_frequencies[cpu_freq_select]; | ||
85 | } | ||
86 | |||
87 | enum { A375_CPU_TO_DDR, A375_CPU_TO_L2 }; | ||
88 | |||
89 | static const struct coreclk_ratio armada_375_coreclk_ratios[] __initconst = { | ||
90 | { .id = A375_CPU_TO_L2, .name = "l2clk" }, | ||
91 | { .id = A375_CPU_TO_DDR, .name = "ddrclk" }, | ||
92 | }; | ||
93 | |||
94 | static const int armada_375_cpu_l2_ratios[32][2] __initconst = { | ||
95 | {0, 1}, {0, 1}, {0, 1}, {0, 1}, | ||
96 | {0, 1}, {0, 1}, {1, 2}, {0, 1}, | ||
97 | {0, 1}, {0, 1}, {0, 1}, {0, 1}, | ||
98 | {0, 1}, {0, 1}, {0, 1}, {1, 2}, | ||
99 | {0, 1}, {0, 1}, {0, 1}, {0, 1}, | ||
100 | {0, 1}, {1, 2}, {0, 1}, {0, 1}, | ||
101 | {0, 1}, {1, 2}, {0, 1}, {0, 1}, | ||
102 | {0, 1}, {0, 1}, {0, 1}, {0, 1}, | ||
103 | }; | ||
104 | |||
105 | static const int armada_375_cpu_ddr_ratios[32][2] __initconst = { | ||
106 | {0, 1}, {0, 1}, {0, 1}, {0, 1}, | ||
107 | {0, 1}, {0, 1}, {1, 1}, {0, 1}, | ||
108 | {0, 1}, {0, 1}, {0, 1}, {0, 1}, | ||
109 | {0, 1}, {0, 1}, {0, 1}, {2, 3}, | ||
110 | {0, 1}, {0, 1}, {0, 1}, {0, 1}, | ||
111 | {0, 1}, {2, 3}, {0, 1}, {0, 1}, | ||
112 | {0, 1}, {1, 2}, {0, 1}, {0, 1}, | ||
113 | {0, 1}, {0, 1}, {0, 1}, {0, 1}, | ||
114 | }; | ||
115 | |||
116 | static void __init armada_375_get_clk_ratio( | ||
117 | void __iomem *sar, int id, int *mult, int *div) | ||
118 | { | ||
119 | u32 opt = ((readl(sar) >> SAR1_A375_CPU_DDR_L2_FREQ_OPT) & | ||
120 | SAR1_A375_CPU_DDR_L2_FREQ_OPT_MASK); | ||
121 | |||
122 | switch (id) { | ||
123 | case A375_CPU_TO_L2: | ||
124 | *mult = armada_375_cpu_l2_ratios[opt][0]; | ||
125 | *div = armada_375_cpu_l2_ratios[opt][1]; | ||
126 | break; | ||
127 | case A375_CPU_TO_DDR: | ||
128 | *mult = armada_375_cpu_ddr_ratios[opt][0]; | ||
129 | *div = armada_375_cpu_ddr_ratios[opt][1]; | ||
130 | break; | ||
131 | } | ||
132 | } | ||
133 | |||
134 | static const struct coreclk_soc_desc armada_375_coreclks = { | ||
135 | .get_tclk_freq = armada_375_get_tclk_freq, | ||
136 | .get_cpu_freq = armada_375_get_cpu_freq, | ||
137 | .get_clk_ratio = armada_375_get_clk_ratio, | ||
138 | .ratios = armada_375_coreclk_ratios, | ||
139 | .num_ratios = ARRAY_SIZE(armada_375_coreclk_ratios), | ||
140 | }; | ||
141 | |||
142 | static void __init armada_375_coreclk_init(struct device_node *np) | ||
143 | { | ||
144 | mvebu_coreclk_setup(np, &armada_375_coreclks); | ||
145 | } | ||
146 | CLK_OF_DECLARE(armada_375_core_clk, "marvell,armada-375-core-clock", | ||
147 | armada_375_coreclk_init); | ||
148 | |||
149 | /* | ||
150 | * Clock Gating Control | ||
151 | */ | ||
152 | static const struct clk_gating_soc_desc armada_375_gating_desc[] __initconst = { | ||
153 | { "mu", NULL, 2 }, | ||
154 | { "pp", NULL, 3 }, | ||
155 | { "ptp", NULL, 4 }, | ||
156 | { "pex0", NULL, 5 }, | ||
157 | { "pex1", NULL, 6 }, | ||
158 | { "audio", NULL, 8 }, | ||
159 | { "nd_clk", "nand", 11 }, | ||
160 | { "sata0_link", "sata0_core", 14 }, | ||
161 | { "sata0_core", NULL, 15 }, | ||
162 | { "usb3", NULL, 16 }, | ||
163 | { "sdio", NULL, 17 }, | ||
164 | { "usb", NULL, 18 }, | ||
165 | { "gop", NULL, 19 }, | ||
166 | { "sata1_link", "sata1_core", 20 }, | ||
167 | { "sata1_core", NULL, 21 }, | ||
168 | { "xor0", NULL, 22 }, | ||
169 | { "xor1", NULL, 23 }, | ||
170 | { "copro", NULL, 24 }, | ||
171 | { "tdm", NULL, 25 }, | ||
172 | { "crypto0_enc", NULL, 28 }, | ||
173 | { "crypto0_core", NULL, 29 }, | ||
174 | { "crypto1_enc", NULL, 30 }, | ||
175 | { "crypto1_core", NULL, 31 }, | ||
176 | { } | ||
177 | }; | ||
178 | |||
179 | static void __init armada_375_clk_gating_init(struct device_node *np) | ||
180 | { | ||
181 | mvebu_clk_gating_setup(np, armada_375_gating_desc); | ||
182 | } | ||
183 | CLK_OF_DECLARE(armada_375_clk_gating, "marvell,armada-375-gating-clock", | ||
184 | armada_375_clk_gating_init); | ||