xref: /linux/arch/sh/kernel/cpu/sh4a/clock-sh7785.c (revision c9904dd15922f349b5f06839e34b1723d4a75940)
132351a28SPaul Mundt /*
232351a28SPaul Mundt  * arch/sh/kernel/cpu/sh4a/clock-sh7785.c
332351a28SPaul Mundt  *
432351a28SPaul Mundt  * SH7785 support for the clock framework
532351a28SPaul Mundt  *
6a77b5ac0SPaul Mundt  *  Copyright (C) 2007 - 2009  Paul Mundt
732351a28SPaul Mundt  *
832351a28SPaul Mundt  * This file is subject to the terms and conditions of the GNU General Public
932351a28SPaul Mundt  * License.  See the file "COPYING" in the main directory of this archive
1032351a28SPaul Mundt  * for more details.
1132351a28SPaul Mundt  */
1232351a28SPaul Mundt #include <linux/init.h>
1332351a28SPaul Mundt #include <linux/kernel.h>
14a77b5ac0SPaul Mundt #include <linux/clk.h>
15a77b5ac0SPaul Mundt #include <linux/io.h>
16cc96eaceSPaul Mundt #include <linux/cpufreq.h>
1732351a28SPaul Mundt #include <asm/clock.h>
1832351a28SPaul Mundt #include <asm/freq.h>
1932351a28SPaul Mundt 
20a77b5ac0SPaul Mundt static unsigned int div2[] = { 1, 2, 4, 6, 8, 12, 16, 18,
21a77b5ac0SPaul Mundt 			       24, 32, 36, 48 };
22a77b5ac0SPaul Mundt struct clk_priv {
23a77b5ac0SPaul Mundt 	unsigned int			shift;
24cc96eaceSPaul Mundt 
25cc96eaceSPaul Mundt 	/* allowable divisor bitmap */
26cc96eaceSPaul Mundt 	unsigned long			div_bitmap;
27cc96eaceSPaul Mundt 
28cc96eaceSPaul Mundt 	/* Supportable frequencies + termination entry */
29cc96eaceSPaul Mundt 	struct cpufreq_frequency_table	freq_table[ARRAY_SIZE(div2)+1];
30a77b5ac0SPaul Mundt };
3132351a28SPaul Mundt 
32cc96eaceSPaul Mundt #define FRQMR_CLK_DATA(_name, _shift, _div_bitmap)	\
33cc96eaceSPaul Mundt static struct clk_priv _name##_data = {			\
34cc96eaceSPaul Mundt 	.shift		= _shift,			\
35cc96eaceSPaul Mundt 	.div_bitmap	= _div_bitmap,			\
36cc96eaceSPaul Mundt 							\
37cc96eaceSPaul Mundt 	.freq_table[0]	= {				\
38cc96eaceSPaul Mundt 		.index = 0,				\
39cc96eaceSPaul Mundt 		.frequency = CPUFREQ_TABLE_END,		\
40cc96eaceSPaul Mundt 	},						\
41cc96eaceSPaul Mundt }
42a77b5ac0SPaul Mundt 
43cc96eaceSPaul Mundt FRQMR_CLK_DATA(pfc,  0, 0x0f80);
44cc96eaceSPaul Mundt FRQMR_CLK_DATA(s3fc, 4, 0x0ff0);
45cc96eaceSPaul Mundt FRQMR_CLK_DATA(s2fc, 8, 0x0030);
46cc96eaceSPaul Mundt FRQMR_CLK_DATA(mfc, 12, 0x000c);
47cc96eaceSPaul Mundt FRQMR_CLK_DATA(bfc, 16, 0x0fe0);
48cc96eaceSPaul Mundt FRQMR_CLK_DATA(sfc, 20, 0x000c);
49cc96eaceSPaul Mundt FRQMR_CLK_DATA(ufc, 24, 0x000c);
50cc96eaceSPaul Mundt FRQMR_CLK_DATA(ifc, 28, 0x000e);
51a77b5ac0SPaul Mundt 
52cc96eaceSPaul Mundt static unsigned long frqmr_recalc(struct clk *clk)
5332351a28SPaul Mundt {
54a77b5ac0SPaul Mundt 	struct clk_priv *data = clk->priv;
55a77b5ac0SPaul Mundt 	unsigned int idx;
56a77b5ac0SPaul Mundt 
57a77b5ac0SPaul Mundt 	idx = (__raw_readl(FRQMR1) >> data->shift) & 0x000f;
58a77b5ac0SPaul Mundt 
59*c9904dd1SMagnus Damm 	return clk->parent->rate / div2[idx];
6032351a28SPaul Mundt }
6132351a28SPaul Mundt 
62cc96eaceSPaul Mundt static void frqmr_build_rate_table(struct clk *clk)
63cc96eaceSPaul Mundt {
64cc96eaceSPaul Mundt 	struct clk_priv *data = clk->priv;
65cc96eaceSPaul Mundt 	int i, entry;
66cc96eaceSPaul Mundt 
67cc96eaceSPaul Mundt 	for (i = entry = 0; i < ARRAY_SIZE(div2); i++) {
68cc96eaceSPaul Mundt 		if ((data->div_bitmap & (1 << i)) == 0)
69cc96eaceSPaul Mundt 			continue;
70cc96eaceSPaul Mundt 
71cc96eaceSPaul Mundt 		data->freq_table[entry].index = entry;
72cc96eaceSPaul Mundt 		data->freq_table[entry].frequency =
73*c9904dd1SMagnus Damm 			clk->parent->rate / div2[i];
74cc96eaceSPaul Mundt 
75cc96eaceSPaul Mundt 		entry++;
76cc96eaceSPaul Mundt 	}
77cc96eaceSPaul Mundt 
78cc96eaceSPaul Mundt 	if (entry == 0) {
79cc96eaceSPaul Mundt 		pr_warning("clkfwk: failed to build frequency table "
80cc96eaceSPaul Mundt 			   "for \"%s\" clk!\n", clk->name);
81cc96eaceSPaul Mundt 		return;
82cc96eaceSPaul Mundt 	}
83cc96eaceSPaul Mundt 
84cc96eaceSPaul Mundt 	/* Termination entry */
85cc96eaceSPaul Mundt 	data->freq_table[entry].index = entry;
86cc96eaceSPaul Mundt 	data->freq_table[entry].frequency = CPUFREQ_TABLE_END;
87cc96eaceSPaul Mundt }
88cc96eaceSPaul Mundt 
89cc96eaceSPaul Mundt static long frqmr_round_rate(struct clk *clk, unsigned long rate)
90cc96eaceSPaul Mundt {
91cc96eaceSPaul Mundt 	struct clk_priv *data = clk->priv;
92cc96eaceSPaul Mundt 	unsigned long rate_error, rate_error_prev = ~0UL;
93cc96eaceSPaul Mundt 	unsigned long rate_best_fit = rate;
94cc96eaceSPaul Mundt 	unsigned long highest, lowest;
95cc96eaceSPaul Mundt 	int i;
96cc96eaceSPaul Mundt 
97cc96eaceSPaul Mundt 	highest = lowest = 0;
98cc96eaceSPaul Mundt 
99cc96eaceSPaul Mundt 	for (i = 0; data->freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
100cc96eaceSPaul Mundt 		unsigned long freq = data->freq_table[i].frequency;
101cc96eaceSPaul Mundt 
102cc96eaceSPaul Mundt 		if (freq == CPUFREQ_ENTRY_INVALID)
103cc96eaceSPaul Mundt 			continue;
104cc96eaceSPaul Mundt 
105cc96eaceSPaul Mundt 		if (freq > highest)
106cc96eaceSPaul Mundt 			highest = freq;
107cc96eaceSPaul Mundt 		if (freq < lowest)
108cc96eaceSPaul Mundt 			lowest = freq;
109cc96eaceSPaul Mundt 
110cc96eaceSPaul Mundt 		rate_error = abs(freq - rate);
111cc96eaceSPaul Mundt 		if (rate_error < rate_error_prev) {
112cc96eaceSPaul Mundt 			rate_best_fit = freq;
113cc96eaceSPaul Mundt 			rate_error_prev = rate_error;
114cc96eaceSPaul Mundt 		}
115cc96eaceSPaul Mundt 
116cc96eaceSPaul Mundt 		if (rate_error == 0)
117cc96eaceSPaul Mundt 			break;
118cc96eaceSPaul Mundt 	}
119cc96eaceSPaul Mundt 
120cc96eaceSPaul Mundt 	if (rate >= highest)
121cc96eaceSPaul Mundt 		rate_best_fit = highest;
122cc96eaceSPaul Mundt 	if (rate <= lowest)
123cc96eaceSPaul Mundt 		rate_best_fit = lowest;
124cc96eaceSPaul Mundt 
125cc96eaceSPaul Mundt 	return rate_best_fit;
126cc96eaceSPaul Mundt }
127cc96eaceSPaul Mundt 
128a77b5ac0SPaul Mundt static struct clk_ops frqmr_clk_ops = {
129cc96eaceSPaul Mundt 	.recalc			= frqmr_recalc,
130cc96eaceSPaul Mundt 	.build_rate_table	= frqmr_build_rate_table,
131cc96eaceSPaul Mundt 	.round_rate		= frqmr_round_rate,
13232351a28SPaul Mundt };
13332351a28SPaul Mundt 
134*c9904dd1SMagnus Damm static unsigned long pll_recalc(struct clk *clk)
135*c9904dd1SMagnus Damm {
136*c9904dd1SMagnus Damm 	/*
137*c9904dd1SMagnus Damm 	 * XXX: PLL1 multiplier is locked for the default clock mode,
138*c9904dd1SMagnus Damm 	 * when mode pin detection and configuration support is added,
139*c9904dd1SMagnus Damm 	 * select the multiplier dynamically.
140*c9904dd1SMagnus Damm 	 */
141*c9904dd1SMagnus Damm 	return clk->parent->rate * 36;
142*c9904dd1SMagnus Damm }
143*c9904dd1SMagnus Damm 
144*c9904dd1SMagnus Damm static struct clk_ops pll_clk_ops = {
145*c9904dd1SMagnus Damm 	.recalc		= pll_recalc,
146*c9904dd1SMagnus Damm };
147*c9904dd1SMagnus Damm 
14832351a28SPaul Mundt /*
149a77b5ac0SPaul Mundt  * Default rate for the root input clock, reset this with clk_set_rate()
150a77b5ac0SPaul Mundt  * from the platform code.
15132351a28SPaul Mundt  */
152a77b5ac0SPaul Mundt static struct clk extal_clk = {
153a77b5ac0SPaul Mundt 	.name		= "extal",
154a77b5ac0SPaul Mundt 	.id		= -1,
155a77b5ac0SPaul Mundt 	.rate		= 33333333,
156a77b5ac0SPaul Mundt };
157a77b5ac0SPaul Mundt 
158*c9904dd1SMagnus Damm static struct clk pll_clk = {
159*c9904dd1SMagnus Damm 	.name		= "pll_clk",
160*c9904dd1SMagnus Damm 	.id		= -1,
161*c9904dd1SMagnus Damm 	.ops		= &pll_clk_ops,
162*c9904dd1SMagnus Damm 	.parent		= &extal_clk,
163*c9904dd1SMagnus Damm 	.flags		= CLK_ENABLE_ON_INIT,
164*c9904dd1SMagnus Damm };
165*c9904dd1SMagnus Damm 
166a77b5ac0SPaul Mundt static struct clk cpu_clk = {
167a77b5ac0SPaul Mundt 	.name		= "cpu_clk",		/* Ick */
168a77b5ac0SPaul Mundt 	.id		= -1,
169a77b5ac0SPaul Mundt 	.ops		= &frqmr_clk_ops,
170*c9904dd1SMagnus Damm 	.parent		= &pll_clk,
171a77b5ac0SPaul Mundt 	.flags		= CLK_ENABLE_ON_INIT,
172a77b5ac0SPaul Mundt 	.priv		= &ifc_data,
173a77b5ac0SPaul Mundt };
174a77b5ac0SPaul Mundt 
175a77b5ac0SPaul Mundt static struct clk shyway_clk = {
176a77b5ac0SPaul Mundt 	.name		= "shyway_clk",		/* SHck */
177a77b5ac0SPaul Mundt 	.id		= -1,
178a77b5ac0SPaul Mundt 	.ops		= &frqmr_clk_ops,
179*c9904dd1SMagnus Damm 	.parent		= &pll_clk,
180a77b5ac0SPaul Mundt 	.flags		= CLK_ENABLE_ON_INIT,
181a77b5ac0SPaul Mundt 	.priv		= &sfc_data,
182a77b5ac0SPaul Mundt };
183a77b5ac0SPaul Mundt 
184a77b5ac0SPaul Mundt static struct clk peripheral_clk = {
185a77b5ac0SPaul Mundt 	.name		= "peripheral_clk",	/* Pck */
186a77b5ac0SPaul Mundt 	.id		= -1,
187a77b5ac0SPaul Mundt 	.ops		= &frqmr_clk_ops,
188*c9904dd1SMagnus Damm 	.parent		= &pll_clk,
189a77b5ac0SPaul Mundt 	.flags		= CLK_ENABLE_ON_INIT,
190a77b5ac0SPaul Mundt 	.priv		= &pfc_data,
191a77b5ac0SPaul Mundt };
192a77b5ac0SPaul Mundt 
193a77b5ac0SPaul Mundt static struct clk ddr_clk = {
194a77b5ac0SPaul Mundt 	.name		= "ddr_clk",		/* DDRck */
195a77b5ac0SPaul Mundt 	.id		= -1,
196a77b5ac0SPaul Mundt 	.ops		= &frqmr_clk_ops,
197*c9904dd1SMagnus Damm 	.parent		= &pll_clk,
198a77b5ac0SPaul Mundt 	.flags		= CLK_ENABLE_ON_INIT,
199a77b5ac0SPaul Mundt 	.priv		= &mfc_data,
200a77b5ac0SPaul Mundt };
201a77b5ac0SPaul Mundt 
202a77b5ac0SPaul Mundt static struct clk bus_clk = {
203a77b5ac0SPaul Mundt 	.name		= "bus_clk",		/* Bck */
204a77b5ac0SPaul Mundt 	.id		= -1,
205a77b5ac0SPaul Mundt 	.ops		= &frqmr_clk_ops,
206*c9904dd1SMagnus Damm 	.parent		= &pll_clk,
207a77b5ac0SPaul Mundt 	.flags		= CLK_ENABLE_ON_INIT,
208a77b5ac0SPaul Mundt 	.priv		= &bfc_data,
209a77b5ac0SPaul Mundt };
210a77b5ac0SPaul Mundt 
211a77b5ac0SPaul Mundt static struct clk ga_clk = {
212a77b5ac0SPaul Mundt 	.name		= "ga_clk",		/* GAck */
213a77b5ac0SPaul Mundt 	.id		= -1,
214a77b5ac0SPaul Mundt 	.ops		= &frqmr_clk_ops,
215*c9904dd1SMagnus Damm 	.parent		= &pll_clk,
216a77b5ac0SPaul Mundt 	.priv		= &s2fc_data,
217a77b5ac0SPaul Mundt };
218a77b5ac0SPaul Mundt 
219a77b5ac0SPaul Mundt static struct clk du_clk = {
220a77b5ac0SPaul Mundt 	.name		= "du_clk",		/* DUck */
221a77b5ac0SPaul Mundt 	.id		= -1,
222a77b5ac0SPaul Mundt 	.ops		= &frqmr_clk_ops,
223*c9904dd1SMagnus Damm 	.parent		= &pll_clk,
224a77b5ac0SPaul Mundt 	.priv		= &s3fc_data,
225a77b5ac0SPaul Mundt };
226a77b5ac0SPaul Mundt 
227a77b5ac0SPaul Mundt static struct clk umem_clk = {
228a77b5ac0SPaul Mundt 	.name		= "umem_clk",		/* uck */
229a77b5ac0SPaul Mundt 	.id		= -1,
230a77b5ac0SPaul Mundt 	.ops		= &frqmr_clk_ops,
231*c9904dd1SMagnus Damm 	.parent		= &pll_clk,
232a77b5ac0SPaul Mundt 	.flags		= CLK_ENABLE_ON_INIT,
233a77b5ac0SPaul Mundt 	.priv		= &ufc_data,
234a77b5ac0SPaul Mundt };
235a77b5ac0SPaul Mundt 
236a77b5ac0SPaul Mundt static struct clk *clks[] = {
237a77b5ac0SPaul Mundt 	&extal_clk,
238*c9904dd1SMagnus Damm 	&pll_clk,
239a77b5ac0SPaul Mundt 	&cpu_clk,
240a77b5ac0SPaul Mundt 	&shyway_clk,
241a77b5ac0SPaul Mundt 	&peripheral_clk,
242a77b5ac0SPaul Mundt 	&ddr_clk,
243a77b5ac0SPaul Mundt 	&bus_clk,
244a77b5ac0SPaul Mundt 	&ga_clk,
245a77b5ac0SPaul Mundt 	&du_clk,
246a77b5ac0SPaul Mundt 	&umem_clk,
24732351a28SPaul Mundt };
24832351a28SPaul Mundt 
249549b5e35SPaul Mundt static int mstpcr_clk_enable(struct clk *clk)
250549b5e35SPaul Mundt {
251549b5e35SPaul Mundt 	__raw_writel(__raw_readl(clk->enable_reg) & ~(1 << clk->enable_bit),
252549b5e35SPaul Mundt 		     clk->enable_reg);
253549b5e35SPaul Mundt 	return 0;
254549b5e35SPaul Mundt }
255549b5e35SPaul Mundt 
256549b5e35SPaul Mundt static void mstpcr_clk_disable(struct clk *clk)
257549b5e35SPaul Mundt {
258549b5e35SPaul Mundt 	__raw_writel(__raw_readl(clk->enable_reg) | (1 << clk->enable_bit),
259549b5e35SPaul Mundt 		     clk->enable_reg);
260549b5e35SPaul Mundt }
261549b5e35SPaul Mundt 
262549b5e35SPaul Mundt static struct clk_ops mstpcr_clk_ops = {
263549b5e35SPaul Mundt 	.enable		= mstpcr_clk_enable,
264549b5e35SPaul Mundt 	.disable	= mstpcr_clk_disable,
265549b5e35SPaul Mundt 	.recalc		= followparent_recalc,
266549b5e35SPaul Mundt };
267549b5e35SPaul Mundt 
268549b5e35SPaul Mundt #define MSTPCR0		0xffc80030
269549b5e35SPaul Mundt #define MSTPCR1		0xffc80034
270549b5e35SPaul Mundt 
271549b5e35SPaul Mundt #define CLK(_name, _id, _parent, _enable_reg,		\
272549b5e35SPaul Mundt 	    _enable_bit, _flags)			\
273549b5e35SPaul Mundt {							\
274549b5e35SPaul Mundt 	.name		= _name,			\
275549b5e35SPaul Mundt 	.id		= _id,				\
276549b5e35SPaul Mundt 	.parent		= _parent,			\
277549b5e35SPaul Mundt 	.enable_reg	= (void __iomem *)_enable_reg,	\
278549b5e35SPaul Mundt 	.enable_bit	= _enable_bit,			\
279549b5e35SPaul Mundt 	.flags		= _flags,			\
280549b5e35SPaul Mundt 	.ops		= &mstpcr_clk_ops,		\
281549b5e35SPaul Mundt }
282549b5e35SPaul Mundt 
283549b5e35SPaul Mundt static struct clk mstpcr_clks[] = {
284549b5e35SPaul Mundt 	/* MSTPCR0 */
285549b5e35SPaul Mundt 	CLK("scif_fck", 5, &peripheral_clk, MSTPCR0, 29, 0),
286549b5e35SPaul Mundt 	CLK("scif_fck", 4, &peripheral_clk, MSTPCR0, 28, 0),
287549b5e35SPaul Mundt 	CLK("scif_fck", 3, &peripheral_clk, MSTPCR0, 27, 0),
288549b5e35SPaul Mundt 	CLK("scif_fck", 2, &peripheral_clk, MSTPCR0, 26, 0),
289549b5e35SPaul Mundt 	CLK("scif_fck", 1, &peripheral_clk, MSTPCR0, 25, 0),
290549b5e35SPaul Mundt 	CLK("scif_fck", 0, &peripheral_clk, MSTPCR0, 24, 0),
291549b5e35SPaul Mundt 	CLK("ssi_fck", 1, &peripheral_clk, MSTPCR0, 21, 0),
292549b5e35SPaul Mundt 	CLK("ssi_fck", 0, &peripheral_clk, MSTPCR0, 20, 0),
293549b5e35SPaul Mundt 	CLK("hac_fck", 1, &peripheral_clk, MSTPCR0, 17, 0),
294549b5e35SPaul Mundt 	CLK("hac_fck", 0, &peripheral_clk, MSTPCR0, 16, 0),
295549b5e35SPaul Mundt 	CLK("mmcif_fck", -1, &peripheral_clk, MSTPCR0, 13, 0),
296549b5e35SPaul Mundt 	CLK("flctl_fck", -1, &peripheral_clk, MSTPCR0, 12, 0),
297549b5e35SPaul Mundt 	CLK("tmu345_fck", -1, &peripheral_clk, MSTPCR0, 9, 0),
298549b5e35SPaul Mundt 	CLK("tmu012_fck", -1, &peripheral_clk, MSTPCR0, 8, 0),
299549b5e35SPaul Mundt 	CLK("siof_fck", -1, &peripheral_clk, MSTPCR0, 3, 0),
300549b5e35SPaul Mundt 	CLK("hspi_fck", -1, &peripheral_clk, MSTPCR0, 2, 0),
301549b5e35SPaul Mundt 
302549b5e35SPaul Mundt 	/* MSTPCR1 */
303549b5e35SPaul Mundt 	CLK("hudi_fck", -1, NULL, MSTPCR1, 19, 0),
304549b5e35SPaul Mundt 	CLK("ubc_fck", -1, NULL, MSTPCR1, 17, 0),
305549b5e35SPaul Mundt 	CLK("dmac_11_6_fck", -1, NULL, MSTPCR1, 5, 0),
306549b5e35SPaul Mundt 	CLK("dmac_5_0_fck", -1, NULL, MSTPCR1, 4, 0),
307549b5e35SPaul Mundt 	CLK("gdta_fck", -1, NULL, MSTPCR1, 0, 0),
308549b5e35SPaul Mundt };
309549b5e35SPaul Mundt 
3109fe5ee0eSPaul Mundt int __init arch_clk_init(void)
31132351a28SPaul Mundt {
312f5c84cf5SPaul Mundt 	int i, ret = 0;
31332351a28SPaul Mundt 
314a77b5ac0SPaul Mundt 	for (i = 0; i < ARRAY_SIZE(clks); i++)
315a77b5ac0SPaul Mundt 		ret |= clk_register(clks[i]);
316549b5e35SPaul Mundt 	for (i = 0; i < ARRAY_SIZE(mstpcr_clks); i++)
317549b5e35SPaul Mundt 		ret |= clk_register(&mstpcr_clks[i]);
31832351a28SPaul Mundt 
319f5c84cf5SPaul Mundt 	return ret;
32032351a28SPaul Mundt }
321