1/*
2 *  This program is free software; you can redistribute it and/or modify it
3 *  under the terms of the GNU General Public License version 2 as published
4 *  by the Free Software Foundation.
5 *
6 *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
7 *  Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG
8 */
9
10#include <linux/io.h>
11#include <linux/export.h>
12#include <linux/clk.h>
13
14#include <asm/time.h>
15#include <asm/irq.h>
16#include <asm/div64.h>
17
18#include <lantiq_soc.h>
19
20#include "../clk.h"
21
22static unsigned int ram_clocks[] = {
23	CLOCK_167M, CLOCK_133M, CLOCK_111M, CLOCK_83M };
24#define DDR_HZ ram_clocks[ltq_cgu_r32(CGU_SYS) & 0x3]
25
26/* legacy xway clock */
27#define CGU_SYS			0x10
28
29/* vr9, ar10/grx390 clock */
30#define CGU_SYS_XRX		0x0c
31#define CGU_IF_CLK_AR10		0x24
32
33unsigned long ltq_danube_fpi_hz(void)
34{
35	unsigned long ddr_clock = DDR_HZ;
36
37	if (ltq_cgu_r32(CGU_SYS) & 0x40)
38		return ddr_clock >> 1;
39	return ddr_clock;
40}
41
42unsigned long ltq_danube_cpu_hz(void)
43{
44	switch (ltq_cgu_r32(CGU_SYS) & 0xc) {
45	case 0:
46		return CLOCK_333M;
47	case 4:
48		return DDR_HZ;
49	case 8:
50		return DDR_HZ << 1;
51	default:
52		return DDR_HZ >> 1;
53	}
54}
55
56unsigned long ltq_danube_pp32_hz(void)
57{
58	unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 7) & 3;
59	unsigned long clk;
60
61	switch (clksys) {
62	case 1:
63		clk = CLOCK_240M;
64		break;
65	case 2:
66		clk = CLOCK_222M;
67		break;
68	case 3:
69		clk = CLOCK_133M;
70		break;
71	default:
72		clk = CLOCK_266M;
73		break;
74	}
75
76	return clk;
77}
78
79unsigned long ltq_ar9_sys_hz(void)
80{
81	if (((ltq_cgu_r32(CGU_SYS) >> 3) & 0x3) == 0x2)
82		return CLOCK_393M;
83	return CLOCK_333M;
84}
85
86unsigned long ltq_ar9_fpi_hz(void)
87{
88	unsigned long sys = ltq_ar9_sys_hz();
89
90	if (ltq_cgu_r32(CGU_SYS) & BIT(0))
91		return sys / 3;
92	else
93		return sys / 2;
94}
95
96unsigned long ltq_ar9_cpu_hz(void)
97{
98	if (ltq_cgu_r32(CGU_SYS) & BIT(2))
99		return ltq_ar9_fpi_hz();
100	else
101		return ltq_ar9_sys_hz();
102}
103
104unsigned long ltq_vr9_cpu_hz(void)
105{
106	unsigned int cpu_sel;
107	unsigned long clk;
108
109	cpu_sel = (ltq_cgu_r32(CGU_SYS_XRX) >> 4) & 0xf;
110
111	switch (cpu_sel) {
112	case 0:
113		clk = CLOCK_600M;
114		break;
115	case 1:
116		clk = CLOCK_500M;
117		break;
118	case 2:
119		clk = CLOCK_393M;
120		break;
121	case 3:
122		clk = CLOCK_333M;
123		break;
124	case 5:
125	case 6:
126		clk = CLOCK_196_608M;
127		break;
128	case 7:
129		clk = CLOCK_167M;
130		break;
131	case 4:
132	case 8:
133	case 9:
134		clk = CLOCK_125M;
135		break;
136	default:
137		clk = 0;
138		break;
139	}
140
141	return clk;
142}
143
144unsigned long ltq_vr9_fpi_hz(void)
145{
146	unsigned int ocp_sel, cpu_clk;
147	unsigned long clk;
148
149	cpu_clk = ltq_vr9_cpu_hz();
150	ocp_sel = ltq_cgu_r32(CGU_SYS_XRX) & 0x3;
151
152	switch (ocp_sel) {
153	case 0:
154		/* OCP ratio 1 */
155		clk = cpu_clk;
156		break;
157	case 2:
158		/* OCP ratio 2 */
159		clk = cpu_clk / 2;
160		break;
161	case 3:
162		/* OCP ratio 2.5 */
163		clk = (cpu_clk * 2) / 5;
164		break;
165	case 4:
166		/* OCP ratio 3 */
167		clk = cpu_clk / 3;
168		break;
169	default:
170		clk = 0;
171		break;
172	}
173
174	return clk;
175}
176
177unsigned long ltq_vr9_pp32_hz(void)
178{
179	unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 16) & 0x7;
180	unsigned long clk;
181
182	switch (clksys) {
183	case 0:
184		clk = CLOCK_500M;
185		break;
186	case 1:
187		clk = CLOCK_432M;
188		break;
189	case 2:
190		clk = CLOCK_288M;
191		break;
192	default:
193		clk = CLOCK_500M;
194		break;
195	}
196
197	return clk;
198}
199
200unsigned long ltq_ar10_cpu_hz(void)
201{
202	unsigned int clksys;
203	int cpu_fs = (ltq_cgu_r32(CGU_SYS_XRX) >> 8) & 0x1;
204	int freq_div = (ltq_cgu_r32(CGU_SYS_XRX) >> 4) & 0x7;
205
206	switch (cpu_fs) {
207	case 0:
208		clksys = CLOCK_500M;
209		break;
210	case 1:
211		clksys = CLOCK_600M;
212		break;
213	default:
214		clksys = CLOCK_500M;
215		break;
216	}
217
218	switch (freq_div) {
219	case 0:
220		return clksys;
221	case 1:
222		return clksys >> 1;
223	case 2:
224		return clksys >> 2;
225	default:
226		return clksys;
227	}
228}
229
230unsigned long ltq_ar10_fpi_hz(void)
231{
232	int freq_fpi = (ltq_cgu_r32(CGU_IF_CLK_AR10) >> 25) & 0xf;
233
234	switch (freq_fpi) {
235	case 1:
236		return CLOCK_300M;
237	case 5:
238		return CLOCK_250M;
239	case 2:
240		return CLOCK_150M;
241	case 6:
242		return CLOCK_125M;
243
244	default:
245		return CLOCK_125M;
246	}
247}
248
249unsigned long ltq_ar10_pp32_hz(void)
250{
251	unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 16) & 0x7;
252	unsigned long clk;
253
254	switch (clksys) {
255	case 1:
256		clk = CLOCK_250M;
257		break;
258	case 4:
259		clk = CLOCK_400M;
260		break;
261	default:
262		clk = CLOCK_250M;
263		break;
264	}
265
266	return clk;
267}
268
269unsigned long ltq_grx390_cpu_hz(void)
270{
271	unsigned int clksys;
272	int cpu_fs = ((ltq_cgu_r32(CGU_SYS_XRX) >> 9) & 0x3);
273	int freq_div = ((ltq_cgu_r32(CGU_SYS_XRX) >> 4) & 0x7);
274
275	switch (cpu_fs) {
276	case 0:
277		clksys = CLOCK_600M;
278		break;
279	case 1:
280		clksys = CLOCK_666M;
281		break;
282	case 2:
283		clksys = CLOCK_720M;
284		break;
285	default:
286		clksys = CLOCK_600M;
287		break;
288	}
289
290	switch (freq_div) {
291	case 0:
292		return clksys;
293	case 1:
294		return clksys >> 1;
295	case 2:
296		return clksys >> 2;
297	default:
298		return clksys;
299	}
300}
301
302unsigned long ltq_grx390_fpi_hz(void)
303{
304	/* fpi clock is derived from ddr_clk */
305	unsigned int clksys;
306	int cpu_fs = ((ltq_cgu_r32(CGU_SYS_XRX) >> 9) & 0x3);
307	int freq_div = ((ltq_cgu_r32(CGU_SYS_XRX)) & 0x7);
308	switch (cpu_fs) {
309	case 0:
310		clksys = CLOCK_600M;
311		break;
312	case 1:
313		clksys = CLOCK_666M;
314		break;
315	case 2:
316		clksys = CLOCK_720M;
317		break;
318	default:
319		clksys = CLOCK_600M;
320		break;
321	}
322
323	switch (freq_div) {
324	case 1:
325		return clksys >> 1;
326	case 2:
327		return clksys >> 2;
328	default:
329		return clksys >> 1;
330	}
331}
332
333unsigned long ltq_grx390_pp32_hz(void)
334{
335	unsigned int clksys = (ltq_cgu_r32(CGU_SYS) >> 16) & 0x7;
336	unsigned long clk;
337
338	switch (clksys) {
339	case 1:
340		clk = CLOCK_250M;
341		break;
342	case 2:
343		clk = CLOCK_432M;
344		break;
345	case 4:
346		clk = CLOCK_400M;
347		break;
348	default:
349		clk = CLOCK_250M;
350		break;
351	}
352	return clk;
353}
354