xref: /openbmc/linux/drivers/clk/mvebu/kirkwood.c (revision aaedb9e0)
1c3828949SGregory CLEMENT // SPDX-License-Identifier: GPL-2.0
2e89406c9SSebastian Hesselbarth /*
3e89406c9SSebastian Hesselbarth  * Marvell Kirkwood SoC clocks
4e89406c9SSebastian Hesselbarth  *
5e89406c9SSebastian Hesselbarth  * Copyright (C) 2012 Marvell
6e89406c9SSebastian Hesselbarth  *
7e89406c9SSebastian Hesselbarth  * Gregory CLEMENT <gregory.clement@free-electrons.com>
8e89406c9SSebastian Hesselbarth  * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
9e89406c9SSebastian Hesselbarth  * Andrew Lunn <andrew@lunn.ch>
10e89406c9SSebastian Hesselbarth  *
11e89406c9SSebastian Hesselbarth  */
12e89406c9SSebastian Hesselbarth 
13e89406c9SSebastian Hesselbarth #include <linux/kernel.h>
14e8e8a9b0SMike Turquette #include <linux/slab.h>
15e89406c9SSebastian Hesselbarth #include <linux/clk-provider.h>
16e89406c9SSebastian Hesselbarth #include <linux/io.h>
17e89406c9SSebastian Hesselbarth #include <linux/of.h>
18e8e8a9b0SMike Turquette #include <linux/of_address.h>
19e89406c9SSebastian Hesselbarth #include "common.h"
20e89406c9SSebastian Hesselbarth 
21e89406c9SSebastian Hesselbarth /*
22e89406c9SSebastian Hesselbarth  * Core Clocks
23e89406c9SSebastian Hesselbarth  *
24e89406c9SSebastian Hesselbarth  * Kirkwood PLL sample-at-reset configuration
25e89406c9SSebastian Hesselbarth  * (6180 has different SAR layout than other Kirkwood SoCs)
26e89406c9SSebastian Hesselbarth  *
27e89406c9SSebastian Hesselbarth  * SAR0[4:3,22,1] : CPU frequency (6281,6292,6282)
28e89406c9SSebastian Hesselbarth  *	4  =  600 MHz
29e89406c9SSebastian Hesselbarth  *	6  =  800 MHz
30e89406c9SSebastian Hesselbarth  *	7  = 1000 MHz
31e89406c9SSebastian Hesselbarth  *	9  = 1200 MHz
32e89406c9SSebastian Hesselbarth  *	12 = 1500 MHz
33e89406c9SSebastian Hesselbarth  *	13 = 1600 MHz
34e89406c9SSebastian Hesselbarth  *	14 = 1800 MHz
35e89406c9SSebastian Hesselbarth  *	15 = 2000 MHz
36e89406c9SSebastian Hesselbarth  *	others reserved.
37e89406c9SSebastian Hesselbarth  *
38e89406c9SSebastian Hesselbarth  * SAR0[19,10:9] : CPU to L2 Clock divider ratio (6281,6292,6282)
39e89406c9SSebastian Hesselbarth  *	1 = (1/2) * CPU
40e89406c9SSebastian Hesselbarth  *	3 = (1/3) * CPU
41e89406c9SSebastian Hesselbarth  *	5 = (1/4) * CPU
42e89406c9SSebastian Hesselbarth  *	others reserved.
43e89406c9SSebastian Hesselbarth  *
44e89406c9SSebastian Hesselbarth  * SAR0[8:5] : CPU to DDR DRAM Clock divider ratio (6281,6292,6282)
45e89406c9SSebastian Hesselbarth  *	2 = (1/2) * CPU
46e89406c9SSebastian Hesselbarth  *	4 = (1/3) * CPU
47e89406c9SSebastian Hesselbarth  *	6 = (1/4) * CPU
48e89406c9SSebastian Hesselbarth  *	7 = (2/9) * CPU
49e89406c9SSebastian Hesselbarth  *	8 = (1/5) * CPU
50e89406c9SSebastian Hesselbarth  *	9 = (1/6) * CPU
51e89406c9SSebastian Hesselbarth  *	others reserved.
52e89406c9SSebastian Hesselbarth  *
53e89406c9SSebastian Hesselbarth  * SAR0[4:2] : Kirkwood 6180 cpu/l2/ddr clock configuration (6180 only)
54e89406c9SSebastian Hesselbarth  *	5 = [CPU =  600 MHz, L2 = (1/2) * CPU, DDR = 200 MHz = (1/3) * CPU]
55e89406c9SSebastian Hesselbarth  *	6 = [CPU =  800 MHz, L2 = (1/2) * CPU, DDR = 200 MHz = (1/4) * CPU]
56e89406c9SSebastian Hesselbarth  *	7 = [CPU = 1000 MHz, L2 = (1/2) * CPU, DDR = 200 MHz = (1/5) * CPU]
57e89406c9SSebastian Hesselbarth  *	others reserved.
58e89406c9SSebastian Hesselbarth  *
59e89406c9SSebastian Hesselbarth  * SAR0[21] : TCLK frequency
60e89406c9SSebastian Hesselbarth  *	0 = 200 MHz
61e89406c9SSebastian Hesselbarth  *	1 = 166 MHz
62e89406c9SSebastian Hesselbarth  *	others reserved.
63e89406c9SSebastian Hesselbarth  */
64e89406c9SSebastian Hesselbarth 
65e89406c9SSebastian Hesselbarth #define SAR_KIRKWOOD_CPU_FREQ(x)	\
66e89406c9SSebastian Hesselbarth 	(((x & (1 <<  1)) >>  1) |	\
67e89406c9SSebastian Hesselbarth 	 ((x & (1 << 22)) >> 21) |	\
68e89406c9SSebastian Hesselbarth 	 ((x & (3 <<  3)) >>  1))
69e89406c9SSebastian Hesselbarth #define SAR_KIRKWOOD_L2_RATIO(x)	\
70e89406c9SSebastian Hesselbarth 	(((x & (3 <<  9)) >> 9) |	\
71e89406c9SSebastian Hesselbarth 	 (((x & (1 << 19)) >> 17)))
72e89406c9SSebastian Hesselbarth #define SAR_KIRKWOOD_DDR_RATIO		5
73e89406c9SSebastian Hesselbarth #define SAR_KIRKWOOD_DDR_RATIO_MASK	0xf
74e89406c9SSebastian Hesselbarth #define SAR_MV88F6180_CLK		2
75e89406c9SSebastian Hesselbarth #define SAR_MV88F6180_CLK_MASK		0x7
76e89406c9SSebastian Hesselbarth #define SAR_KIRKWOOD_TCLK_FREQ		21
77e89406c9SSebastian Hesselbarth #define SAR_KIRKWOOD_TCLK_FREQ_MASK	0x1
78e89406c9SSebastian Hesselbarth 
79e89406c9SSebastian Hesselbarth enum { KIRKWOOD_CPU_TO_L2, KIRKWOOD_CPU_TO_DDR };
80e89406c9SSebastian Hesselbarth 
81847b1c00SSachin Kamat static const struct coreclk_ratio kirkwood_coreclk_ratios[] __initconst = {
82e89406c9SSebastian Hesselbarth 	{ .id = KIRKWOOD_CPU_TO_L2, .name = "l2clk", },
83e89406c9SSebastian Hesselbarth 	{ .id = KIRKWOOD_CPU_TO_DDR, .name = "ddrclk", }
84e89406c9SSebastian Hesselbarth };
85e89406c9SSebastian Hesselbarth 
kirkwood_get_tclk_freq(void __iomem * sar)86e89406c9SSebastian Hesselbarth static u32 __init kirkwood_get_tclk_freq(void __iomem *sar)
87e89406c9SSebastian Hesselbarth {
88e89406c9SSebastian Hesselbarth 	u32 opt = (readl(sar) >> SAR_KIRKWOOD_TCLK_FREQ) &
89e89406c9SSebastian Hesselbarth 		SAR_KIRKWOOD_TCLK_FREQ_MASK;
90e89406c9SSebastian Hesselbarth 	return (opt) ? 166666667 : 200000000;
91e89406c9SSebastian Hesselbarth }
92e89406c9SSebastian Hesselbarth 
93847b1c00SSachin Kamat static const u32 kirkwood_cpu_freqs[] __initconst = {
94e89406c9SSebastian Hesselbarth 	0, 0, 0, 0,
95e89406c9SSebastian Hesselbarth 	600000000,
96e89406c9SSebastian Hesselbarth 	0,
97e89406c9SSebastian Hesselbarth 	800000000,
98e89406c9SSebastian Hesselbarth 	1000000000,
99e89406c9SSebastian Hesselbarth 	0,
100e89406c9SSebastian Hesselbarth 	1200000000,
101e89406c9SSebastian Hesselbarth 	0, 0,
102e89406c9SSebastian Hesselbarth 	1500000000,
103e89406c9SSebastian Hesselbarth 	1600000000,
104e89406c9SSebastian Hesselbarth 	1800000000,
105e89406c9SSebastian Hesselbarth 	2000000000
106e89406c9SSebastian Hesselbarth };
107e89406c9SSebastian Hesselbarth 
kirkwood_get_cpu_freq(void __iomem * sar)108e89406c9SSebastian Hesselbarth static u32 __init kirkwood_get_cpu_freq(void __iomem *sar)
109e89406c9SSebastian Hesselbarth {
110e89406c9SSebastian Hesselbarth 	u32 opt = SAR_KIRKWOOD_CPU_FREQ(readl(sar));
111e89406c9SSebastian Hesselbarth 	return kirkwood_cpu_freqs[opt];
112e89406c9SSebastian Hesselbarth }
113e89406c9SSebastian Hesselbarth 
114847b1c00SSachin Kamat static const int kirkwood_cpu_l2_ratios[8][2] __initconst = {
115e89406c9SSebastian Hesselbarth 	{ 0, 1 }, { 1, 2 }, { 0, 1 }, { 1, 3 },
116e89406c9SSebastian Hesselbarth 	{ 0, 1 }, { 1, 4 }, { 0, 1 }, { 0, 1 }
117e89406c9SSebastian Hesselbarth };
118e89406c9SSebastian Hesselbarth 
119847b1c00SSachin Kamat static const int kirkwood_cpu_ddr_ratios[16][2] __initconst = {
120e89406c9SSebastian Hesselbarth 	{ 0, 1 }, { 0, 1 }, { 1, 2 }, { 0, 1 },
121e89406c9SSebastian Hesselbarth 	{ 1, 3 }, { 0, 1 }, { 1, 4 }, { 2, 9 },
122e89406c9SSebastian Hesselbarth 	{ 1, 5 }, { 1, 6 }, { 0, 1 }, { 0, 1 },
123e89406c9SSebastian Hesselbarth 	{ 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 }
124e89406c9SSebastian Hesselbarth };
125e89406c9SSebastian Hesselbarth 
kirkwood_get_clk_ratio(void __iomem * sar,int id,int * mult,int * div)126e89406c9SSebastian Hesselbarth static void __init kirkwood_get_clk_ratio(
127e89406c9SSebastian Hesselbarth 	void __iomem *sar, int id, int *mult, int *div)
128e89406c9SSebastian Hesselbarth {
129e89406c9SSebastian Hesselbarth 	switch (id) {
130e89406c9SSebastian Hesselbarth 	case KIRKWOOD_CPU_TO_L2:
131e89406c9SSebastian Hesselbarth 	{
132e89406c9SSebastian Hesselbarth 		u32 opt = SAR_KIRKWOOD_L2_RATIO(readl(sar));
133e89406c9SSebastian Hesselbarth 		*mult = kirkwood_cpu_l2_ratios[opt][0];
134e89406c9SSebastian Hesselbarth 		*div = kirkwood_cpu_l2_ratios[opt][1];
135e89406c9SSebastian Hesselbarth 		break;
136e89406c9SSebastian Hesselbarth 	}
137e89406c9SSebastian Hesselbarth 	case KIRKWOOD_CPU_TO_DDR:
138e89406c9SSebastian Hesselbarth 	{
139e89406c9SSebastian Hesselbarth 		u32 opt = (readl(sar) >> SAR_KIRKWOOD_DDR_RATIO) &
140e89406c9SSebastian Hesselbarth 			SAR_KIRKWOOD_DDR_RATIO_MASK;
141e89406c9SSebastian Hesselbarth 		*mult = kirkwood_cpu_ddr_ratios[opt][0];
142e89406c9SSebastian Hesselbarth 		*div = kirkwood_cpu_ddr_ratios[opt][1];
143e89406c9SSebastian Hesselbarth 		break;
144e89406c9SSebastian Hesselbarth 	}
145e89406c9SSebastian Hesselbarth 	}
146e89406c9SSebastian Hesselbarth }
147e89406c9SSebastian Hesselbarth 
148847b1c00SSachin Kamat static const u32 mv88f6180_cpu_freqs[] __initconst = {
149e89406c9SSebastian Hesselbarth 	0, 0, 0, 0, 0,
150e89406c9SSebastian Hesselbarth 	600000000,
151e89406c9SSebastian Hesselbarth 	800000000,
152e89406c9SSebastian Hesselbarth 	1000000000
153e89406c9SSebastian Hesselbarth };
154e89406c9SSebastian Hesselbarth 
mv88f6180_get_cpu_freq(void __iomem * sar)155e89406c9SSebastian Hesselbarth static u32 __init mv88f6180_get_cpu_freq(void __iomem *sar)
156e89406c9SSebastian Hesselbarth {
157e89406c9SSebastian Hesselbarth 	u32 opt = (readl(sar) >> SAR_MV88F6180_CLK) & SAR_MV88F6180_CLK_MASK;
158e89406c9SSebastian Hesselbarth 	return mv88f6180_cpu_freqs[opt];
159e89406c9SSebastian Hesselbarth }
160e89406c9SSebastian Hesselbarth 
161847b1c00SSachin Kamat static const int mv88f6180_cpu_ddr_ratios[8][2] __initconst = {
162e89406c9SSebastian Hesselbarth 	{ 0, 1 }, { 0, 1 }, { 0, 1 }, { 0, 1 },
163e89406c9SSebastian Hesselbarth 	{ 0, 1 }, { 1, 3 }, { 1, 4 }, { 1, 5 }
164e89406c9SSebastian Hesselbarth };
165e89406c9SSebastian Hesselbarth 
mv88f6180_get_clk_ratio(void __iomem * sar,int id,int * mult,int * div)166e89406c9SSebastian Hesselbarth static void __init mv88f6180_get_clk_ratio(
167e89406c9SSebastian Hesselbarth 	void __iomem *sar, int id, int *mult, int *div)
168e89406c9SSebastian Hesselbarth {
169e89406c9SSebastian Hesselbarth 	switch (id) {
170e89406c9SSebastian Hesselbarth 	case KIRKWOOD_CPU_TO_L2:
171e89406c9SSebastian Hesselbarth 	{
172e89406c9SSebastian Hesselbarth 		/* mv88f6180 has a fixed 1:2 CPU-to-L2 ratio */
173e89406c9SSebastian Hesselbarth 		*mult = 1;
174e89406c9SSebastian Hesselbarth 		*div = 2;
175e89406c9SSebastian Hesselbarth 		break;
176e89406c9SSebastian Hesselbarth 	}
177e89406c9SSebastian Hesselbarth 	case KIRKWOOD_CPU_TO_DDR:
178e89406c9SSebastian Hesselbarth 	{
179e89406c9SSebastian Hesselbarth 		u32 opt = (readl(sar) >> SAR_MV88F6180_CLK) &
180e89406c9SSebastian Hesselbarth 			SAR_MV88F6180_CLK_MASK;
181e89406c9SSebastian Hesselbarth 		*mult = mv88f6180_cpu_ddr_ratios[opt][0];
182e89406c9SSebastian Hesselbarth 		*div = mv88f6180_cpu_ddr_ratios[opt][1];
183e89406c9SSebastian Hesselbarth 		break;
184e89406c9SSebastian Hesselbarth 	}
185e89406c9SSebastian Hesselbarth 	}
186e89406c9SSebastian Hesselbarth }
187e89406c9SSebastian Hesselbarth 
mv98dx1135_get_tclk_freq(void __iomem * sar)18888aa7af9SChris Packham static u32 __init mv98dx1135_get_tclk_freq(void __iomem *sar)
18988aa7af9SChris Packham {
19088aa7af9SChris Packham 	return 166666667;
19188aa7af9SChris Packham }
19288aa7af9SChris Packham 
193e89406c9SSebastian Hesselbarth static const struct coreclk_soc_desc kirkwood_coreclks = {
194e89406c9SSebastian Hesselbarth 	.get_tclk_freq = kirkwood_get_tclk_freq,
195e89406c9SSebastian Hesselbarth 	.get_cpu_freq = kirkwood_get_cpu_freq,
196e89406c9SSebastian Hesselbarth 	.get_clk_ratio = kirkwood_get_clk_ratio,
197e89406c9SSebastian Hesselbarth 	.ratios = kirkwood_coreclk_ratios,
198e89406c9SSebastian Hesselbarth 	.num_ratios = ARRAY_SIZE(kirkwood_coreclk_ratios),
199e89406c9SSebastian Hesselbarth };
200e89406c9SSebastian Hesselbarth 
201e89406c9SSebastian Hesselbarth static const struct coreclk_soc_desc mv88f6180_coreclks = {
202e89406c9SSebastian Hesselbarth 	.get_tclk_freq = kirkwood_get_tclk_freq,
203e89406c9SSebastian Hesselbarth 	.get_cpu_freq = mv88f6180_get_cpu_freq,
204e89406c9SSebastian Hesselbarth 	.get_clk_ratio = mv88f6180_get_clk_ratio,
205e89406c9SSebastian Hesselbarth 	.ratios = kirkwood_coreclk_ratios,
206e89406c9SSebastian Hesselbarth 	.num_ratios = ARRAY_SIZE(kirkwood_coreclk_ratios),
207e89406c9SSebastian Hesselbarth };
208e89406c9SSebastian Hesselbarth 
20988aa7af9SChris Packham static const struct coreclk_soc_desc mv98dx1135_coreclks = {
21088aa7af9SChris Packham 	.get_tclk_freq = mv98dx1135_get_tclk_freq,
21188aa7af9SChris Packham 	.get_cpu_freq = kirkwood_get_cpu_freq,
21288aa7af9SChris Packham 	.get_clk_ratio = kirkwood_get_clk_ratio,
21388aa7af9SChris Packham 	.ratios = kirkwood_coreclk_ratios,
21488aa7af9SChris Packham 	.num_ratios = ARRAY_SIZE(kirkwood_coreclk_ratios),
21588aa7af9SChris Packham };
21688aa7af9SChris Packham 
217e89406c9SSebastian Hesselbarth /*
218e89406c9SSebastian Hesselbarth  * Clock Gating Control
219e89406c9SSebastian Hesselbarth  */
220e89406c9SSebastian Hesselbarth 
221847b1c00SSachin Kamat static const struct clk_gating_soc_desc kirkwood_gating_desc[] __initconst = {
222e89406c9SSebastian Hesselbarth 	{ "ge0", NULL, 0, 0 },
223e89406c9SSebastian Hesselbarth 	{ "pex0", NULL, 2, 0 },
224e89406c9SSebastian Hesselbarth 	{ "usb0", NULL, 3, 0 },
225e89406c9SSebastian Hesselbarth 	{ "sdio", NULL, 4, 0 },
226e89406c9SSebastian Hesselbarth 	{ "tsu", NULL, 5, 0 },
227e89406c9SSebastian Hesselbarth 	{ "runit", NULL, 7, 0 },
228e89406c9SSebastian Hesselbarth 	{ "xor0", NULL, 8, 0 },
229e89406c9SSebastian Hesselbarth 	{ "audio", NULL, 9, 0 },
230e89406c9SSebastian Hesselbarth 	{ "sata0", NULL, 14, 0 },
231e89406c9SSebastian Hesselbarth 	{ "sata1", NULL, 15, 0 },
232e89406c9SSebastian Hesselbarth 	{ "xor1", NULL, 16, 0 },
233e89406c9SSebastian Hesselbarth 	{ "crypto", NULL, 17, 0 },
234e89406c9SSebastian Hesselbarth 	{ "pex1", NULL, 18, 0 },
235e89406c9SSebastian Hesselbarth 	{ "ge1", NULL, 19, 0 },
236e89406c9SSebastian Hesselbarth 	{ "tdm", NULL, 20, 0 },
237e89406c9SSebastian Hesselbarth 	{ }
238e89406c9SSebastian Hesselbarth };
239e89406c9SSebastian Hesselbarth 
240e8e8a9b0SMike Turquette 
241e8e8a9b0SMike Turquette /*
242e8e8a9b0SMike Turquette  * Clock Muxing Control
243e8e8a9b0SMike Turquette  */
244e8e8a9b0SMike Turquette 
245e8e8a9b0SMike Turquette struct clk_muxing_soc_desc {
246e8e8a9b0SMike Turquette 	const char *name;
247e8e8a9b0SMike Turquette 	const char **parents;
248e8e8a9b0SMike Turquette 	int num_parents;
249e8e8a9b0SMike Turquette 	int shift;
250e8e8a9b0SMike Turquette 	int width;
251e8e8a9b0SMike Turquette 	unsigned long flags;
252e8e8a9b0SMike Turquette };
253e8e8a9b0SMike Turquette 
254e8e8a9b0SMike Turquette struct clk_muxing_ctrl {
255e8e8a9b0SMike Turquette 	spinlock_t *lock;
256e8e8a9b0SMike Turquette 	struct clk **muxes;
257e8e8a9b0SMike Turquette 	int num_muxes;
258e8e8a9b0SMike Turquette };
259e8e8a9b0SMike Turquette 
26010529938SMike Turquette static const char *powersave_parents[] = {
26110529938SMike Turquette 	"cpuclk",
26210529938SMike Turquette 	"ddrclk",
26310529938SMike Turquette };
26410529938SMike Turquette 
26510529938SMike Turquette static const struct clk_muxing_soc_desc kirkwood_mux_desc[] __initconst = {
26610529938SMike Turquette 	{ "powersave", powersave_parents, ARRAY_SIZE(powersave_parents),
26710529938SMike Turquette 		11, 1, 0 },
268*aaedb9e0SLinus Walleij 	{ }
26910529938SMike Turquette };
27010529938SMike Turquette 
clk_muxing_get_src(struct of_phandle_args * clkspec,void * data)271e8e8a9b0SMike Turquette static struct clk *clk_muxing_get_src(
272e8e8a9b0SMike Turquette 	struct of_phandle_args *clkspec, void *data)
273e8e8a9b0SMike Turquette {
274e8e8a9b0SMike Turquette 	struct clk_muxing_ctrl *ctrl = (struct clk_muxing_ctrl *)data;
275e8e8a9b0SMike Turquette 	int n;
276e8e8a9b0SMike Turquette 
277e8e8a9b0SMike Turquette 	if (clkspec->args_count < 1)
278e8e8a9b0SMike Turquette 		return ERR_PTR(-EINVAL);
279e8e8a9b0SMike Turquette 
280e8e8a9b0SMike Turquette 	for (n = 0; n < ctrl->num_muxes; n++) {
281e8e8a9b0SMike Turquette 		struct clk_mux *mux =
282e8e8a9b0SMike Turquette 			to_clk_mux(__clk_get_hw(ctrl->muxes[n]));
283e8e8a9b0SMike Turquette 		if (clkspec->args[0] == mux->shift)
284e8e8a9b0SMike Turquette 			return ctrl->muxes[n];
285e8e8a9b0SMike Turquette 	}
286e8e8a9b0SMike Turquette 	return ERR_PTR(-ENODEV);
287e8e8a9b0SMike Turquette }
288e8e8a9b0SMike Turquette 
kirkwood_clk_muxing_setup(struct device_node * np,const struct clk_muxing_soc_desc * desc)289e8e8a9b0SMike Turquette static void __init kirkwood_clk_muxing_setup(struct device_node *np,
290e8e8a9b0SMike Turquette 				   const struct clk_muxing_soc_desc *desc)
291e8e8a9b0SMike Turquette {
292e8e8a9b0SMike Turquette 	struct clk_muxing_ctrl *ctrl;
293e8e8a9b0SMike Turquette 	void __iomem *base;
294e8e8a9b0SMike Turquette 	int n;
295e8e8a9b0SMike Turquette 
296e8e8a9b0SMike Turquette 	base = of_iomap(np, 0);
297e8e8a9b0SMike Turquette 	if (WARN_ON(!base))
298e8e8a9b0SMike Turquette 		return;
299e8e8a9b0SMike Turquette 
300e8e8a9b0SMike Turquette 	ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
301e8e8a9b0SMike Turquette 	if (WARN_ON(!ctrl))
302e8e8a9b0SMike Turquette 		goto ctrl_out;
303e8e8a9b0SMike Turquette 
304e8e8a9b0SMike Turquette 	/* lock must already be initialized */
305e8e8a9b0SMike Turquette 	ctrl->lock = &ctrl_gating_lock;
306e8e8a9b0SMike Turquette 
307e8e8a9b0SMike Turquette 	/* Count, allocate, and register clock muxes */
308e8e8a9b0SMike Turquette 	for (n = 0; desc[n].name;)
309e8e8a9b0SMike Turquette 		n++;
310e8e8a9b0SMike Turquette 
311e8e8a9b0SMike Turquette 	ctrl->num_muxes = n;
312e8e8a9b0SMike Turquette 	ctrl->muxes = kcalloc(ctrl->num_muxes, sizeof(struct clk *),
313e8e8a9b0SMike Turquette 			GFP_KERNEL);
314e8e8a9b0SMike Turquette 	if (WARN_ON(!ctrl->muxes))
315e8e8a9b0SMike Turquette 		goto muxes_out;
316e8e8a9b0SMike Turquette 
317e8e8a9b0SMike Turquette 	for (n = 0; n < ctrl->num_muxes; n++) {
318e8e8a9b0SMike Turquette 		ctrl->muxes[n] = clk_register_mux(NULL, desc[n].name,
319e8e8a9b0SMike Turquette 				desc[n].parents, desc[n].num_parents,
320e8e8a9b0SMike Turquette 				desc[n].flags, base, desc[n].shift,
321e8e8a9b0SMike Turquette 				desc[n].width, desc[n].flags, ctrl->lock);
322e8e8a9b0SMike Turquette 		WARN_ON(IS_ERR(ctrl->muxes[n]));
323e8e8a9b0SMike Turquette 	}
324e8e8a9b0SMike Turquette 
325e8e8a9b0SMike Turquette 	of_clk_add_provider(np, clk_muxing_get_src, ctrl);
326e8e8a9b0SMike Turquette 
327e8e8a9b0SMike Turquette 	return;
328e8e8a9b0SMike Turquette muxes_out:
329e8e8a9b0SMike Turquette 	kfree(ctrl);
330e8e8a9b0SMike Turquette ctrl_out:
331e8e8a9b0SMike Turquette 	iounmap(base);
332e8e8a9b0SMike Turquette }
333e8e8a9b0SMike Turquette 
kirkwood_clk_init(struct device_node * np)33458d516aeSSebastian Hesselbarth static void __init kirkwood_clk_init(struct device_node *np)
335e89406c9SSebastian Hesselbarth {
33658d516aeSSebastian Hesselbarth 	struct device_node *cgnp =
33758d516aeSSebastian Hesselbarth 		of_find_compatible_node(NULL, NULL, "marvell,kirkwood-gating-clock");
33858d516aeSSebastian Hesselbarth 
33958d516aeSSebastian Hesselbarth 
34058d516aeSSebastian Hesselbarth 	if (of_device_is_compatible(np, "marvell,mv88f6180-core-clock"))
34158d516aeSSebastian Hesselbarth 		mvebu_coreclk_setup(np, &mv88f6180_coreclks);
34288aa7af9SChris Packham 	else if (of_device_is_compatible(np, "marvell,mv98dx1135-core-clock"))
34388aa7af9SChris Packham 		mvebu_coreclk_setup(np, &mv98dx1135_coreclks);
34458d516aeSSebastian Hesselbarth 	else
34558d516aeSSebastian Hesselbarth 		mvebu_coreclk_setup(np, &kirkwood_coreclks);
34658d516aeSSebastian Hesselbarth 
34710529938SMike Turquette 	if (cgnp) {
34858d516aeSSebastian Hesselbarth 		mvebu_clk_gating_setup(cgnp, kirkwood_gating_desc);
34910529938SMike Turquette 		kirkwood_clk_muxing_setup(cgnp, kirkwood_mux_desc);
350e7beeab9SYangtao Li 
351e7beeab9SYangtao Li 		of_node_put(cgnp);
35210529938SMike Turquette 	}
353e89406c9SSebastian Hesselbarth }
35458d516aeSSebastian Hesselbarth CLK_OF_DECLARE(kirkwood_clk, "marvell,kirkwood-core-clock",
35558d516aeSSebastian Hesselbarth 	       kirkwood_clk_init);
35658d516aeSSebastian Hesselbarth CLK_OF_DECLARE(mv88f6180_clk, "marvell,mv88f6180-core-clock",
35758d516aeSSebastian Hesselbarth 	       kirkwood_clk_init);
35888aa7af9SChris Packham CLK_OF_DECLARE(98dx1135_clk, "marvell,mv98dx1135-core-clock",
35988aa7af9SChris Packham 	       kirkwood_clk_init);
360