PageRenderTime 26ms CodeModel.GetById 2ms app.highlight 20ms RepoModel.GetById 1ms app.codeStats 0ms

/Ethereal-msm8939-beta9/arch/mips/ath79/clock.c

https://bitbucket.org/MilosStamenkovic95/etherealos
C | 450 lines | 348 code | 87 blank | 15 comment | 46 complexity | 8a8843cc14bd6bbcb57d8fcd6be3a74b MD5 | raw file
  1/*
  2 *  Atheros AR71XX/AR724X/AR913X common routines
  3 *
  4 *  Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com>
  5 *  Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
  6 *
  7 *  Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP
  8 *
  9 *  This program is free software; you can redistribute it and/or modify it
 10 *  under the terms of the GNU General Public License version 2 as published
 11 *  by the Free Software Foundation.
 12 */
 13
 14#include <linux/kernel.h>
 15#include <linux/module.h>
 16#include <linux/init.h>
 17#include <linux/err.h>
 18#include <linux/clk.h>
 19
 20#include <asm/div64.h>
 21
 22#include <asm/mach-ath79/ath79.h>
 23#include <asm/mach-ath79/ar71xx_regs.h>
 24#include "common.h"
 25
 26#define AR71XX_BASE_FREQ	40000000
 27#define AR724X_BASE_FREQ	5000000
 28#define AR913X_BASE_FREQ	5000000
 29
 30struct clk {
 31	unsigned long rate;
 32};
 33
 34static struct clk ath79_ref_clk;
 35static struct clk ath79_cpu_clk;
 36static struct clk ath79_ddr_clk;
 37static struct clk ath79_ahb_clk;
 38static struct clk ath79_wdt_clk;
 39static struct clk ath79_uart_clk;
 40
 41static void __init ar71xx_clocks_init(void)
 42{
 43	u32 pll;
 44	u32 freq;
 45	u32 div;
 46
 47	ath79_ref_clk.rate = AR71XX_BASE_FREQ;
 48
 49	pll = ath79_pll_rr(AR71XX_PLL_REG_CPU_CONFIG);
 50
 51	div = ((pll >> AR71XX_PLL_DIV_SHIFT) & AR71XX_PLL_DIV_MASK) + 1;
 52	freq = div * ath79_ref_clk.rate;
 53
 54	div = ((pll >> AR71XX_CPU_DIV_SHIFT) & AR71XX_CPU_DIV_MASK) + 1;
 55	ath79_cpu_clk.rate = freq / div;
 56
 57	div = ((pll >> AR71XX_DDR_DIV_SHIFT) & AR71XX_DDR_DIV_MASK) + 1;
 58	ath79_ddr_clk.rate = freq / div;
 59
 60	div = (((pll >> AR71XX_AHB_DIV_SHIFT) & AR71XX_AHB_DIV_MASK) + 1) * 2;
 61	ath79_ahb_clk.rate = ath79_cpu_clk.rate / div;
 62
 63	ath79_wdt_clk.rate = ath79_ahb_clk.rate;
 64	ath79_uart_clk.rate = ath79_ahb_clk.rate;
 65}
 66
 67static void __init ar724x_clocks_init(void)
 68{
 69	u32 pll;
 70	u32 freq;
 71	u32 div;
 72
 73	ath79_ref_clk.rate = AR724X_BASE_FREQ;
 74	pll = ath79_pll_rr(AR724X_PLL_REG_CPU_CONFIG);
 75
 76	div = ((pll >> AR724X_PLL_DIV_SHIFT) & AR724X_PLL_DIV_MASK);
 77	freq = div * ath79_ref_clk.rate;
 78
 79	div = ((pll >> AR724X_PLL_REF_DIV_SHIFT) & AR724X_PLL_REF_DIV_MASK);
 80	freq *= div;
 81
 82	ath79_cpu_clk.rate = freq;
 83
 84	div = ((pll >> AR724X_DDR_DIV_SHIFT) & AR724X_DDR_DIV_MASK) + 1;
 85	ath79_ddr_clk.rate = freq / div;
 86
 87	div = (((pll >> AR724X_AHB_DIV_SHIFT) & AR724X_AHB_DIV_MASK) + 1) * 2;
 88	ath79_ahb_clk.rate = ath79_cpu_clk.rate / div;
 89
 90	ath79_wdt_clk.rate = ath79_ahb_clk.rate;
 91	ath79_uart_clk.rate = ath79_ahb_clk.rate;
 92}
 93
 94static void __init ar913x_clocks_init(void)
 95{
 96	u32 pll;
 97	u32 freq;
 98	u32 div;
 99
100	ath79_ref_clk.rate = AR913X_BASE_FREQ;
101	pll = ath79_pll_rr(AR913X_PLL_REG_CPU_CONFIG);
102
103	div = ((pll >> AR913X_PLL_DIV_SHIFT) & AR913X_PLL_DIV_MASK);
104	freq = div * ath79_ref_clk.rate;
105
106	ath79_cpu_clk.rate = freq;
107
108	div = ((pll >> AR913X_DDR_DIV_SHIFT) & AR913X_DDR_DIV_MASK) + 1;
109	ath79_ddr_clk.rate = freq / div;
110
111	div = (((pll >> AR913X_AHB_DIV_SHIFT) & AR913X_AHB_DIV_MASK) + 1) * 2;
112	ath79_ahb_clk.rate = ath79_cpu_clk.rate / div;
113
114	ath79_wdt_clk.rate = ath79_ahb_clk.rate;
115	ath79_uart_clk.rate = ath79_ahb_clk.rate;
116}
117
118static void __init ar933x_clocks_init(void)
119{
120	u32 clock_ctrl;
121	u32 cpu_config;
122	u32 freq;
123	u32 t;
124
125	t = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP);
126	if (t & AR933X_BOOTSTRAP_REF_CLK_40)
127		ath79_ref_clk.rate = (40 * 1000 * 1000);
128	else
129		ath79_ref_clk.rate = (25 * 1000 * 1000);
130
131	clock_ctrl = ath79_pll_rr(AR933X_PLL_CLOCK_CTRL_REG);
132	if (clock_ctrl & AR933X_PLL_CLOCK_CTRL_BYPASS) {
133		ath79_cpu_clk.rate = ath79_ref_clk.rate;
134		ath79_ahb_clk.rate = ath79_ref_clk.rate;
135		ath79_ddr_clk.rate = ath79_ref_clk.rate;
136	} else {
137		cpu_config = ath79_pll_rr(AR933X_PLL_CPU_CONFIG_REG);
138
139		t = (cpu_config >> AR933X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
140		    AR933X_PLL_CPU_CONFIG_REFDIV_MASK;
141		freq = ath79_ref_clk.rate / t;
142
143		t = (cpu_config >> AR933X_PLL_CPU_CONFIG_NINT_SHIFT) &
144		    AR933X_PLL_CPU_CONFIG_NINT_MASK;
145		freq *= t;
146
147		t = (cpu_config >> AR933X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
148		    AR933X_PLL_CPU_CONFIG_OUTDIV_MASK;
149		if (t == 0)
150			t = 1;
151
152		freq >>= t;
153
154		t = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_CPU_DIV_SHIFT) &
155		     AR933X_PLL_CLOCK_CTRL_CPU_DIV_MASK) + 1;
156		ath79_cpu_clk.rate = freq / t;
157
158		t = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_DDR_DIV_SHIFT) &
159		      AR933X_PLL_CLOCK_CTRL_DDR_DIV_MASK) + 1;
160		ath79_ddr_clk.rate = freq / t;
161
162		t = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_AHB_DIV_SHIFT) &
163		     AR933X_PLL_CLOCK_CTRL_AHB_DIV_MASK) + 1;
164		ath79_ahb_clk.rate = freq / t;
165	}
166
167	ath79_wdt_clk.rate = ath79_ahb_clk.rate;
168	ath79_uart_clk.rate = ath79_ref_clk.rate;
169}
170
171static u32 __init ar934x_get_pll_freq(u32 ref, u32 ref_div, u32 nint, u32 nfrac,
172				      u32 frac, u32 out_div)
173{
174	u64 t;
175	u32 ret;
176
177	t = ath79_ref_clk.rate;
178	t *= nint;
179	do_div(t, ref_div);
180	ret = t;
181
182	t = ath79_ref_clk.rate;
183	t *= nfrac;
184	do_div(t, ref_div * frac);
185	ret += t;
186
187	ret /= (1 << out_div);
188	return ret;
189}
190
191static void __init ar934x_clocks_init(void)
192{
193	u32 pll, out_div, ref_div, nint, nfrac, frac, clk_ctrl, postdiv;
194	u32 cpu_pll, ddr_pll;
195	u32 bootstrap;
196	void __iomem *dpll_base;
197
198	dpll_base = ioremap(AR934X_SRIF_BASE, AR934X_SRIF_SIZE);
199
200	bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP);
201	if (bootstrap & AR934X_BOOTSTRAP_REF_CLK_40)
202		ath79_ref_clk.rate = 40 * 1000 * 1000;
203	else
204		ath79_ref_clk.rate = 25 * 1000 * 1000;
205
206	pll = __raw_readl(dpll_base + AR934X_SRIF_CPU_DPLL2_REG);
207	if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) {
208		out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) &
209			  AR934X_SRIF_DPLL2_OUTDIV_MASK;
210		pll = __raw_readl(dpll_base + AR934X_SRIF_CPU_DPLL1_REG);
211		nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) &
212		       AR934X_SRIF_DPLL1_NINT_MASK;
213		nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK;
214		ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) &
215			  AR934X_SRIF_DPLL1_REFDIV_MASK;
216		frac = 1 << 18;
217	} else {
218		pll = ath79_pll_rr(AR934X_PLL_CPU_CONFIG_REG);
219		out_div = (pll >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
220			AR934X_PLL_CPU_CONFIG_OUTDIV_MASK;
221		ref_div = (pll >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
222			  AR934X_PLL_CPU_CONFIG_REFDIV_MASK;
223		nint = (pll >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) &
224		       AR934X_PLL_CPU_CONFIG_NINT_MASK;
225		nfrac = (pll >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) &
226			AR934X_PLL_CPU_CONFIG_NFRAC_MASK;
227		frac = 1 << 6;
228	}
229
230	cpu_pll = ar934x_get_pll_freq(ath79_ref_clk.rate, ref_div, nint,
231				      nfrac, frac, out_div);
232
233	pll = __raw_readl(dpll_base + AR934X_SRIF_DDR_DPLL2_REG);
234	if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) {
235		out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) &
236			  AR934X_SRIF_DPLL2_OUTDIV_MASK;
237		pll = __raw_readl(dpll_base + AR934X_SRIF_DDR_DPLL1_REG);
238		nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) &
239		       AR934X_SRIF_DPLL1_NINT_MASK;
240		nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK;
241		ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) &
242			  AR934X_SRIF_DPLL1_REFDIV_MASK;
243		frac = 1 << 18;
244	} else {
245		pll = ath79_pll_rr(AR934X_PLL_DDR_CONFIG_REG);
246		out_div = (pll >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) &
247			  AR934X_PLL_DDR_CONFIG_OUTDIV_MASK;
248		ref_div = (pll >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) &
249			   AR934X_PLL_DDR_CONFIG_REFDIV_MASK;
250		nint = (pll >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) &
251		       AR934X_PLL_DDR_CONFIG_NINT_MASK;
252		nfrac = (pll >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) &
253			AR934X_PLL_DDR_CONFIG_NFRAC_MASK;
254		frac = 1 << 10;
255	}
256
257	ddr_pll = ar934x_get_pll_freq(ath79_ref_clk.rate, ref_div, nint,
258				      nfrac, frac, out_div);
259
260	clk_ctrl = ath79_pll_rr(AR934X_PLL_CPU_DDR_CLK_CTRL_REG);
261
262	postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_SHIFT) &
263		  AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_POST_DIV_MASK;
264
265	if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPU_PLL_BYPASS)
266		ath79_cpu_clk.rate = ath79_ref_clk.rate;
267	else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_CPUCLK_FROM_CPUPLL)
268		ath79_cpu_clk.rate = cpu_pll / (postdiv + 1);
269	else
270		ath79_cpu_clk.rate = ddr_pll / (postdiv + 1);
271
272	postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_SHIFT) &
273		  AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_POST_DIV_MASK;
274
275	if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDR_PLL_BYPASS)
276		ath79_ddr_clk.rate = ath79_ref_clk.rate;
277	else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL)
278		ath79_ddr_clk.rate = ddr_pll / (postdiv + 1);
279	else
280		ath79_ddr_clk.rate = cpu_pll / (postdiv + 1);
281
282	postdiv = (clk_ctrl >> AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_SHIFT) &
283		  AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_POST_DIV_MASK;
284
285	if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHB_PLL_BYPASS)
286		ath79_ahb_clk.rate = ath79_ref_clk.rate;
287	else if (clk_ctrl & AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL)
288		ath79_ahb_clk.rate = ddr_pll / (postdiv + 1);
289	else
290		ath79_ahb_clk.rate = cpu_pll / (postdiv + 1);
291
292	ath79_wdt_clk.rate = ath79_ref_clk.rate;
293	ath79_uart_clk.rate = ath79_ref_clk.rate;
294
295	iounmap(dpll_base);
296}
297
298static void __init qca955x_clocks_init(void)
299{
300	u32 pll, out_div, ref_div, nint, frac, clk_ctrl, postdiv;
301	u32 cpu_pll, ddr_pll;
302	u32 bootstrap;
303
304	bootstrap = ath79_reset_rr(QCA955X_RESET_REG_BOOTSTRAP);
305	if (bootstrap &	QCA955X_BOOTSTRAP_REF_CLK_40)
306		ath79_ref_clk.rate = 40 * 1000 * 1000;
307	else
308		ath79_ref_clk.rate = 25 * 1000 * 1000;
309
310	pll = ath79_pll_rr(QCA955X_PLL_CPU_CONFIG_REG);
311	out_div = (pll >> QCA955X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
312		  QCA955X_PLL_CPU_CONFIG_OUTDIV_MASK;
313	ref_div = (pll >> QCA955X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
314		  QCA955X_PLL_CPU_CONFIG_REFDIV_MASK;
315	nint = (pll >> QCA955X_PLL_CPU_CONFIG_NINT_SHIFT) &
316	       QCA955X_PLL_CPU_CONFIG_NINT_MASK;
317	frac = (pll >> QCA955X_PLL_CPU_CONFIG_NFRAC_SHIFT) &
318	       QCA955X_PLL_CPU_CONFIG_NFRAC_MASK;
319
320	cpu_pll = nint * ath79_ref_clk.rate / ref_div;
321	cpu_pll += frac * ath79_ref_clk.rate / (ref_div * (1 << 6));
322	cpu_pll /= (1 << out_div);
323
324	pll = ath79_pll_rr(QCA955X_PLL_DDR_CONFIG_REG);
325	out_div = (pll >> QCA955X_PLL_DDR_CONFIG_OUTDIV_SHIFT) &
326		  QCA955X_PLL_DDR_CONFIG_OUTDIV_MASK;
327	ref_div = (pll >> QCA955X_PLL_DDR_CONFIG_REFDIV_SHIFT) &
328		  QCA955X_PLL_DDR_CONFIG_REFDIV_MASK;
329	nint = (pll >> QCA955X_PLL_DDR_CONFIG_NINT_SHIFT) &
330	       QCA955X_PLL_DDR_CONFIG_NINT_MASK;
331	frac = (pll >> QCA955X_PLL_DDR_CONFIG_NFRAC_SHIFT) &
332	       QCA955X_PLL_DDR_CONFIG_NFRAC_MASK;
333
334	ddr_pll = nint * ath79_ref_clk.rate / ref_div;
335	ddr_pll += frac * ath79_ref_clk.rate / (ref_div * (1 << 10));
336	ddr_pll /= (1 << out_div);
337
338	clk_ctrl = ath79_pll_rr(QCA955X_PLL_CLK_CTRL_REG);
339
340	postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) &
341		  QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_MASK;
342
343	if (clk_ctrl & QCA955X_PLL_CLK_CTRL_CPU_PLL_BYPASS)
344		ath79_cpu_clk.rate = ath79_ref_clk.rate;
345	else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL)
346		ath79_cpu_clk.rate = ddr_pll / (postdiv + 1);
347	else
348		ath79_cpu_clk.rate = cpu_pll / (postdiv + 1);
349
350	postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) &
351		  QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_MASK;
352
353	if (clk_ctrl & QCA955X_PLL_CLK_CTRL_DDR_PLL_BYPASS)
354		ath79_ddr_clk.rate = ath79_ref_clk.rate;
355	else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL)
356		ath79_ddr_clk.rate = cpu_pll / (postdiv + 1);
357	else
358		ath79_ddr_clk.rate = ddr_pll / (postdiv + 1);
359
360	postdiv = (clk_ctrl >> QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) &
361		  QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_MASK;
362
363	if (clk_ctrl & QCA955X_PLL_CLK_CTRL_AHB_PLL_BYPASS)
364		ath79_ahb_clk.rate = ath79_ref_clk.rate;
365	else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL)
366		ath79_ahb_clk.rate = ddr_pll / (postdiv + 1);
367	else
368		ath79_ahb_clk.rate = cpu_pll / (postdiv + 1);
369
370	ath79_wdt_clk.rate = ath79_ref_clk.rate;
371	ath79_uart_clk.rate = ath79_ref_clk.rate;
372}
373
374void __init ath79_clocks_init(void)
375{
376	if (soc_is_ar71xx())
377		ar71xx_clocks_init();
378	else if (soc_is_ar724x())
379		ar724x_clocks_init();
380	else if (soc_is_ar913x())
381		ar913x_clocks_init();
382	else if (soc_is_ar933x())
383		ar933x_clocks_init();
384	else if (soc_is_ar934x())
385		ar934x_clocks_init();
386	else if (soc_is_qca955x())
387		qca955x_clocks_init();
388	else
389		BUG();
390
391	pr_info("Clocks: CPU:%lu.%03luMHz, DDR:%lu.%03luMHz, AHB:%lu.%03luMHz, "
392		"Ref:%lu.%03luMHz",
393		ath79_cpu_clk.rate / 1000000,
394		(ath79_cpu_clk.rate / 1000) % 1000,
395		ath79_ddr_clk.rate / 1000000,
396		(ath79_ddr_clk.rate / 1000) % 1000,
397		ath79_ahb_clk.rate / 1000000,
398		(ath79_ahb_clk.rate / 1000) % 1000,
399		ath79_ref_clk.rate / 1000000,
400		(ath79_ref_clk.rate / 1000) % 1000);
401}
402
403/*
404 * Linux clock API
405 */
406struct clk *clk_get(struct device *dev, const char *id)
407{
408	if (!strcmp(id, "ref"))
409		return &ath79_ref_clk;
410
411	if (!strcmp(id, "cpu"))
412		return &ath79_cpu_clk;
413
414	if (!strcmp(id, "ddr"))
415		return &ath79_ddr_clk;
416
417	if (!strcmp(id, "ahb"))
418		return &ath79_ahb_clk;
419
420	if (!strcmp(id, "wdt"))
421		return &ath79_wdt_clk;
422
423	if (!strcmp(id, "uart"))
424		return &ath79_uart_clk;
425
426	return ERR_PTR(-ENOENT);
427}
428EXPORT_SYMBOL(clk_get);
429
430int clk_enable(struct clk *clk)
431{
432	return 0;
433}
434EXPORT_SYMBOL(clk_enable);
435
436void clk_disable(struct clk *clk)
437{
438}
439EXPORT_SYMBOL(clk_disable);
440
441unsigned long clk_get_rate(struct clk *clk)
442{
443	return clk->rate;
444}
445EXPORT_SYMBOL(clk_get_rate);
446
447void clk_put(struct clk *clk)
448{
449}
450EXPORT_SYMBOL(clk_put);