f14c279866e9788e7ac69de803d4c6967d4bc330
[openwrt.git] / target / linux / lantiq / patches-3.2 / 0025-MIPS-lantiq-convert-xway-to-clkdev-api.patch
1 From b6a73eaeb10726bb30584aa8aa4620061db653ba Mon Sep 17 00:00:00 2001
2 From: John Crispin <blogic@openwrt.org>
3 Date: Thu, 8 Mar 2012 11:18:22 +0100
4 Subject: [PATCH 25/73] MIPS: lantiq: convert xway to clkdev api
5
6 Unify xway/ase clock code and add clkdev hooks to sysctrl.c
7
8 Signed-off-by: John Crispin <blogic@openwrt.org>
9 ---
10  .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h |   13 --
11  arch/mips/lantiq/xway/Makefile                     |    6 +-
12  arch/mips/lantiq/xway/clk-ase.c                    |   48 ----
13  arch/mips/lantiq/xway/clk-xway.c                   |  223 -------------------
14  arch/mips/lantiq/xway/clk.c                        |  227 ++++++++++++++++++++
15  arch/mips/lantiq/xway/sysctrl.c                    |  104 ++++++++-
16  6 files changed, 325 insertions(+), 296 deletions(-)
17  delete mode 100644 arch/mips/lantiq/xway/clk-ase.c
18  delete mode 100644 arch/mips/lantiq/xway/clk-xway.c
19  create mode 100644 arch/mips/lantiq/xway/clk.c
20
21 diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
22 index 45e480c..e9d2dd4 100644
23 --- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
24 +++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
25 @@ -81,15 +81,6 @@
26  #define LTQ_PMU_BASE_ADDR      0x1F102000
27  #define LTQ_PMU_SIZE           0x1000
28  
29 -#define PMU_DMA                        0x0020
30 -#define PMU_EPHY               0x0080
31 -#define PMU_USB                        0x8041
32 -#define PMU_LED                        0x0800
33 -#define PMU_GPT                        0x1000
34 -#define PMU_PPE                        0x2000
35 -#define PMU_FPI                        0x4000
36 -#define PMU_SWITCH             0x10000000
37 -
38  /* ETOP - ethernet */
39  #define LTQ_ETOP_BASE_ADDR     0x1E180000
40  #define LTQ_ETOP_SIZE          0x40000
41 @@ -145,10 +136,6 @@
42  extern __iomem void *ltq_ebu_membase;
43  extern __iomem void *ltq_cgu_membase;
44  
45 -extern void ltq_pmu_enable(unsigned int module);
46 -extern void ltq_pmu_disable(unsigned int module);
47 -extern void ltq_cgu_enable(unsigned int clk);
48 -
49  static inline int ltq_is_ase(void)
50  {
51         return (ltq_get_soc_type() == SOC_TYPE_AMAZON_SE);
52 diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
53 index 6678402..4dcb96f 100644
54 --- a/arch/mips/lantiq/xway/Makefile
55 +++ b/arch/mips/lantiq/xway/Makefile
56 @@ -1,7 +1,7 @@
57 -obj-y := sysctrl.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o
58 +obj-y := sysctrl.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o clk.o
59  
60 -obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o
61 -obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o
62 +obj-$(CONFIG_SOC_XWAY) += prom-xway.o
63 +obj-$(CONFIG_SOC_AMAZON_SE) += prom-ase.o
64  
65  obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o
66  obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o
67 diff --git a/arch/mips/lantiq/xway/clk-ase.c b/arch/mips/lantiq/xway/clk-ase.c
68 deleted file mode 100644
69 index 6522583..0000000
70 --- a/arch/mips/lantiq/xway/clk-ase.c
71 +++ /dev/null
72 @@ -1,48 +0,0 @@
73 -/*
74 - *  This program is free software; you can redistribute it and/or modify it
75 - *  under the terms of the GNU General Public License version 2 as published
76 - *  by the Free Software Foundation.
77 - *
78 - *  Copyright (C) 2011 John Crispin <blogic@openwrt.org>
79 - */
80 -
81 -#include <linux/io.h>
82 -#include <linux/export.h>
83 -#include <linux/init.h>
84 -#include <linux/clk.h>
85 -
86 -#include <asm/time.h>
87 -#include <asm/irq.h>
88 -#include <asm/div64.h>
89 -
90 -#include <lantiq_soc.h>
91 -
92 -/* cgu registers */
93 -#define LTQ_CGU_SYS    0x0010
94 -
95 -unsigned int ltq_get_io_region_clock(void)
96 -{
97 -       return CLOCK_133M;
98 -}
99 -EXPORT_SYMBOL(ltq_get_io_region_clock);
100 -
101 -unsigned int ltq_get_fpi_bus_clock(int fpi)
102 -{
103 -       return CLOCK_133M;
104 -}
105 -EXPORT_SYMBOL(ltq_get_fpi_bus_clock);
106 -
107 -unsigned int ltq_get_cpu_hz(void)
108 -{
109 -       if (ltq_cgu_r32(LTQ_CGU_SYS) & (1 << 5))
110 -               return CLOCK_266M;
111 -       else
112 -               return CLOCK_133M;
113 -}
114 -EXPORT_SYMBOL(ltq_get_cpu_hz);
115 -
116 -unsigned int ltq_get_fpi_hz(void)
117 -{
118 -       return CLOCK_133M;
119 -}
120 -EXPORT_SYMBOL(ltq_get_fpi_hz);
121 diff --git a/arch/mips/lantiq/xway/clk-xway.c b/arch/mips/lantiq/xway/clk-xway.c
122 deleted file mode 100644
123 index 696b1a3..0000000
124 --- a/arch/mips/lantiq/xway/clk-xway.c
125 +++ /dev/null
126 @@ -1,223 +0,0 @@
127 -/*
128 - *  This program is free software; you can redistribute it and/or modify it
129 - *  under the terms of the GNU General Public License version 2 as published
130 - *  by the Free Software Foundation.
131 - *
132 - *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
133 - */
134 -
135 -#include <linux/io.h>
136 -#include <linux/export.h>
137 -#include <linux/init.h>
138 -#include <linux/clk.h>
139 -
140 -#include <asm/time.h>
141 -#include <asm/irq.h>
142 -#include <asm/div64.h>
143 -
144 -#include <lantiq_soc.h>
145 -
146 -static unsigned int ltq_ram_clocks[] = {
147 -       CLOCK_167M, CLOCK_133M, CLOCK_111M, CLOCK_83M };
148 -#define DDR_HZ ltq_ram_clocks[ltq_cgu_r32(LTQ_CGU_SYS) & 0x3]
149 -
150 -#define BASIC_FREQUENCY_1      35328000
151 -#define BASIC_FREQUENCY_2      36000000
152 -#define BASIS_REQUENCY_USB     12000000
153 -
154 -#define GET_BITS(x, msb, lsb) \
155 -       (((x) & ((1 << ((msb) + 1)) - 1)) >> (lsb))
156 -
157 -#define LTQ_CGU_PLL0_CFG       0x0004
158 -#define LTQ_CGU_PLL1_CFG       0x0008
159 -#define LTQ_CGU_PLL2_CFG       0x000C
160 -#define LTQ_CGU_SYS            0x0010
161 -#define LTQ_CGU_UPDATE         0x0014
162 -#define LTQ_CGU_IF_CLK         0x0018
163 -#define LTQ_CGU_OSC_CON                0x001C
164 -#define LTQ_CGU_SMD            0x0020
165 -#define LTQ_CGU_CT1SR          0x0028
166 -#define LTQ_CGU_CT2SR          0x002C
167 -#define LTQ_CGU_PCMCR          0x0030
168 -#define LTQ_CGU_PCI_CR         0x0034
169 -#define LTQ_CGU_PD_PC          0x0038
170 -#define LTQ_CGU_FMR            0x003C
171 -
172 -#define CGU_PLL0_PHASE_DIVIDER_ENABLE  \
173 -       (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 31))
174 -#define CGU_PLL0_BYPASS                        \
175 -       (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 30))
176 -#define CGU_PLL0_CFG_DSMSEL            \
177 -       (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 28))
178 -#define CGU_PLL0_CFG_FRAC_EN           \
179 -       (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 27))
180 -#define CGU_PLL1_SRC                   \
181 -       (ltq_cgu_r32(LTQ_CGU_PLL1_CFG) & (1 << 31))
182 -#define CGU_PLL2_PHASE_DIVIDER_ENABLE  \
183 -       (ltq_cgu_r32(LTQ_CGU_PLL2_CFG) & (1 << 20))
184 -#define CGU_SYS_FPI_SEL                        (1 << 6)
185 -#define CGU_SYS_DDR_SEL                        0x3
186 -#define CGU_PLL0_SRC                   (1 << 29)
187 -
188 -#define CGU_PLL0_CFG_PLLK      GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 26, 17)
189 -#define CGU_PLL0_CFG_PLLN      GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 12, 6)
190 -#define CGU_PLL0_CFG_PLLM      GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 5, 2)
191 -#define CGU_PLL2_SRC           GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL2_CFG), 18, 17)
192 -#define CGU_PLL2_CFG_INPUT_DIV GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL2_CFG), 16, 13)
193 -
194 -static unsigned int ltq_get_pll0_fdiv(void);
195 -
196 -static inline unsigned int get_input_clock(int pll)
197 -{
198 -       switch (pll) {
199 -       case 0:
200 -               if (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & CGU_PLL0_SRC)
201 -                       return BASIS_REQUENCY_USB;
202 -               else if (CGU_PLL0_PHASE_DIVIDER_ENABLE)
203 -                       return BASIC_FREQUENCY_1;
204 -               else
205 -                       return BASIC_FREQUENCY_2;
206 -       case 1:
207 -               if (CGU_PLL1_SRC)
208 -                       return BASIS_REQUENCY_USB;
209 -               else if (CGU_PLL0_PHASE_DIVIDER_ENABLE)
210 -                       return BASIC_FREQUENCY_1;
211 -               else
212 -                       return BASIC_FREQUENCY_2;
213 -       case 2:
214 -               switch (CGU_PLL2_SRC) {
215 -               case 0:
216 -                       return ltq_get_pll0_fdiv();
217 -               case 1:
218 -                       return CGU_PLL2_PHASE_DIVIDER_ENABLE ?
219 -                               BASIC_FREQUENCY_1 :
220 -                               BASIC_FREQUENCY_2;
221 -               case 2:
222 -                       return BASIS_REQUENCY_USB;
223 -               }
224 -       default:
225 -               return 0;
226 -       }
227 -}
228 -
229 -static inline unsigned int cal_dsm(int pll, unsigned int num, unsigned int den)
230 -{
231 -       u64 res, clock = get_input_clock(pll);
232 -
233 -       res = num * clock;
234 -       do_div(res, den);
235 -       return res;
236 -}
237 -
238 -static inline unsigned int mash_dsm(int pll, unsigned int M, unsigned int N,
239 -       unsigned int K)
240 -{
241 -       unsigned int num = ((N + 1) << 10) + K;
242 -       unsigned int den = (M + 1) << 10;
243 -
244 -       return cal_dsm(pll, num, den);
245 -}
246 -
247 -static inline unsigned int ssff_dsm_1(int pll, unsigned int M, unsigned int N,
248 -       unsigned int K)
249 -{
250 -       unsigned int num = ((N + 1) << 11) + K + 512;
251 -       unsigned int den = (M + 1) << 11;
252 -
253 -       return cal_dsm(pll, num, den);
254 -}
255 -
256 -static inline unsigned int ssff_dsm_2(int pll, unsigned int M, unsigned int N,
257 -       unsigned int K)
258 -{
259 -       unsigned int num = K >= 512 ?
260 -               ((N + 1) << 12) + K - 512 : ((N + 1) << 12) + K + 3584;
261 -       unsigned int den = (M + 1) << 12;
262 -
263 -       return cal_dsm(pll, num, den);
264 -}
265 -
266 -static inline unsigned int dsm(int pll, unsigned int M, unsigned int N,
267 -       unsigned int K, unsigned int dsmsel, unsigned int phase_div_en)
268 -{
269 -       if (!dsmsel)
270 -               return mash_dsm(pll, M, N, K);
271 -       else if (!phase_div_en)
272 -               return mash_dsm(pll, M, N, K);
273 -       else
274 -               return ssff_dsm_2(pll, M, N, K);
275 -}
276 -
277 -static inline unsigned int ltq_get_pll0_fosc(void)
278 -{
279 -       if (CGU_PLL0_BYPASS)
280 -               return get_input_clock(0);
281 -       else
282 -               return !CGU_PLL0_CFG_FRAC_EN
283 -                       ? dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN, 0,
284 -                               CGU_PLL0_CFG_DSMSEL,
285 -                               CGU_PLL0_PHASE_DIVIDER_ENABLE)
286 -                       : dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN,
287 -                               CGU_PLL0_CFG_PLLK, CGU_PLL0_CFG_DSMSEL,
288 -                               CGU_PLL0_PHASE_DIVIDER_ENABLE);
289 -}
290 -
291 -static unsigned int ltq_get_pll0_fdiv(void)
292 -{
293 -       unsigned int div = CGU_PLL2_CFG_INPUT_DIV + 1;
294 -
295 -       return (ltq_get_pll0_fosc() + (div >> 1)) / div;
296 -}
297 -
298 -unsigned int ltq_get_io_region_clock(void)
299 -{
300 -       unsigned int ret = ltq_get_pll0_fosc();
301 -
302 -       switch (ltq_cgu_r32(LTQ_CGU_PLL2_CFG) & CGU_SYS_DDR_SEL) {
303 -       default:
304 -       case 0:
305 -               return (ret + 1) / 2;
306 -       case 1:
307 -               return (ret * 2 + 2) / 5;
308 -       case 2:
309 -               return (ret + 1) / 3;
310 -       case 3:
311 -               return (ret + 2) / 4;
312 -       }
313 -}
314 -EXPORT_SYMBOL(ltq_get_io_region_clock);
315 -
316 -unsigned int ltq_get_fpi_bus_clock(int fpi)
317 -{
318 -       unsigned int ret = ltq_get_io_region_clock();
319 -
320 -       if ((fpi == 2) && (ltq_cgu_r32(LTQ_CGU_SYS) & CGU_SYS_FPI_SEL))
321 -               ret >>= 1;
322 -       return ret;
323 -}
324 -EXPORT_SYMBOL(ltq_get_fpi_bus_clock);
325 -
326 -unsigned int ltq_get_cpu_hz(void)
327 -{
328 -       switch (ltq_cgu_r32(LTQ_CGU_SYS) & 0xc) {
329 -       case 0:
330 -               return CLOCK_333M;
331 -       case 4:
332 -               return DDR_HZ;
333 -       case 8:
334 -               return DDR_HZ << 1;
335 -       default:
336 -               return DDR_HZ >> 1;
337 -       }
338 -}
339 -EXPORT_SYMBOL(ltq_get_cpu_hz);
340 -
341 -unsigned int ltq_get_fpi_hz(void)
342 -{
343 -       unsigned int ddr_clock = DDR_HZ;
344 -
345 -       if (ltq_cgu_r32(LTQ_CGU_SYS) & 0x40)
346 -               return ddr_clock >> 1;
347 -       return ddr_clock;
348 -}
349 -EXPORT_SYMBOL(ltq_get_fpi_hz);
350 diff --git a/arch/mips/lantiq/xway/clk.c b/arch/mips/lantiq/xway/clk.c
351 new file mode 100644
352 index 0000000..f3b50fc
353 --- /dev/null
354 +++ b/arch/mips/lantiq/xway/clk.c
355 @@ -0,0 +1,227 @@
356 +/*
357 + *  This program is free software; you can redistribute it and/or modify it
358 + *  under the terms of the GNU General Public License version 2 as published
359 + *  by the Free Software Foundation.
360 + *
361 + *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
362 + */
363 +
364 +#include <linux/io.h>
365 +#include <linux/export.h>
366 +#include <linux/init.h>
367 +#include <linux/clk.h>
368 +
369 +#include <asm/time.h>
370 +#include <asm/irq.h>
371 +#include <asm/div64.h>
372 +
373 +#include <lantiq_soc.h>
374 +
375 +#include "../clk.h"
376 +
377 +static unsigned int ltq_ram_clocks[] = {
378 +       CLOCK_167M, CLOCK_133M, CLOCK_111M, CLOCK_83M };
379 +#define DDR_HZ ltq_ram_clocks[ltq_cgu_r32(LTQ_CGU_SYS) & 0x3]
380 +
381 +#define BASIC_FREQUENCY_1      35328000
382 +#define BASIC_FREQUENCY_2      36000000
383 +#define BASIS_REQUENCY_USB     12000000
384 +
385 +#define GET_BITS(x, msb, lsb) \
386 +       (((x) & ((1 << ((msb) + 1)) - 1)) >> (lsb))
387 +
388 +/* legacy xway clock */
389 +#define LTQ_CGU_PLL0_CFG       0x0004
390 +#define LTQ_CGU_PLL1_CFG       0x0008
391 +#define LTQ_CGU_PLL2_CFG       0x000C
392 +#define LTQ_CGU_SYS            0x0010
393 +#define LTQ_CGU_UPDATE         0x0014
394 +#define LTQ_CGU_IF_CLK         0x0018
395 +#define LTQ_CGU_OSC_CON                0x001C
396 +#define LTQ_CGU_SMD            0x0020
397 +#define LTQ_CGU_CT1SR          0x0028
398 +#define LTQ_CGU_CT2SR          0x002C
399 +#define LTQ_CGU_PCMCR          0x0030
400 +#define LTQ_CGU_PCI_CR         0x0034
401 +#define LTQ_CGU_PD_PC          0x0038
402 +#define LTQ_CGU_FMR            0x003C
403 +
404 +#define CGU_PLL0_PHASE_DIVIDER_ENABLE  \
405 +       (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 31))
406 +#define CGU_PLL0_BYPASS                        \
407 +       (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 30))
408 +#define CGU_PLL0_CFG_DSMSEL            \
409 +       (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 28))
410 +#define CGU_PLL0_CFG_FRAC_EN           \
411 +       (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 27))
412 +#define CGU_PLL1_SRC                   \
413 +       (ltq_cgu_r32(LTQ_CGU_PLL1_CFG) & (1 << 31))
414 +#define CGU_PLL2_PHASE_DIVIDER_ENABLE  \
415 +       (ltq_cgu_r32(LTQ_CGU_PLL2_CFG) & (1 << 20))
416 +#define CGU_SYS_FPI_SEL                        (1 << 6)
417 +#define CGU_SYS_DDR_SEL                        0x3
418 +#define CGU_PLL0_SRC                   (1 << 29)
419 +
420 +#define CGU_PLL0_CFG_PLLK      GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 26, 17)
421 +#define CGU_PLL0_CFG_PLLN      GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 12, 6)
422 +#define CGU_PLL0_CFG_PLLM      GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 5, 2)
423 +#define CGU_PLL2_SRC           GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL2_CFG), 18, 17)
424 +#define CGU_PLL2_CFG_INPUT_DIV GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL2_CFG), 16, 13)
425 +
426 +/* vr9 clock */
427 +#define LTQ_CGU_SYS_VR9        0x0c
428 +#define LTQ_CGU_IF_CLK_VR9     0x24
429 +
430 +
431 +static unsigned int ltq_get_pll0_fdiv(void);
432 +
433 +static inline unsigned int get_input_clock(int pll)
434 +{
435 +       switch (pll) {
436 +       case 0:
437 +               if (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & CGU_PLL0_SRC)
438 +                       return BASIS_REQUENCY_USB;
439 +               else if (CGU_PLL0_PHASE_DIVIDER_ENABLE)
440 +                       return BASIC_FREQUENCY_1;
441 +               else
442 +                       return BASIC_FREQUENCY_2;
443 +       case 1:
444 +               if (CGU_PLL1_SRC)
445 +                       return BASIS_REQUENCY_USB;
446 +               else if (CGU_PLL0_PHASE_DIVIDER_ENABLE)
447 +                       return BASIC_FREQUENCY_1;
448 +               else
449 +                       return BASIC_FREQUENCY_2;
450 +       case 2:
451 +               switch (CGU_PLL2_SRC) {
452 +               case 0:
453 +                       return ltq_get_pll0_fdiv();
454 +               case 1:
455 +                       return CGU_PLL2_PHASE_DIVIDER_ENABLE ?
456 +                               BASIC_FREQUENCY_1 :
457 +                               BASIC_FREQUENCY_2;
458 +               case 2:
459 +                       return BASIS_REQUENCY_USB;
460 +               }
461 +       default:
462 +               return 0;
463 +       }
464 +}
465 +
466 +static inline unsigned int cal_dsm(int pll, unsigned int num, unsigned int den)
467 +{
468 +       u64 res, clock = get_input_clock(pll);
469 +
470 +       res = num * clock;
471 +       do_div(res, den);
472 +       return res;
473 +}
474 +
475 +static inline unsigned int mash_dsm(int pll, unsigned int M, unsigned int N,
476 +       unsigned int K)
477 +{
478 +       unsigned int num = ((N + 1) << 10) + K;
479 +       unsigned int den = (M + 1) << 10;
480 +
481 +       return cal_dsm(pll, num, den);
482 +}
483 +
484 +static inline unsigned int ssff_dsm_1(int pll, unsigned int M, unsigned int N,
485 +       unsigned int K)
486 +{
487 +       unsigned int num = ((N + 1) << 11) + K + 512;
488 +       unsigned int den = (M + 1) << 11;
489 +
490 +       return cal_dsm(pll, num, den);
491 +}
492 +
493 +static inline unsigned int ssff_dsm_2(int pll, unsigned int M, unsigned int N,
494 +       unsigned int K)
495 +{
496 +       unsigned int num = K >= 512 ?
497 +               ((N + 1) << 12) + K - 512 : ((N + 1) << 12) + K + 3584;
498 +       unsigned int den = (M + 1) << 12;
499 +
500 +       return cal_dsm(pll, num, den);
501 +}
502 +
503 +static inline unsigned int dsm(int pll, unsigned int M, unsigned int N,
504 +       unsigned int K, unsigned int dsmsel, unsigned int phase_div_en)
505 +{
506 +       if (!dsmsel)
507 +               return mash_dsm(pll, M, N, K);
508 +       else if (!phase_div_en)
509 +               return mash_dsm(pll, M, N, K);
510 +       else
511 +               return ssff_dsm_2(pll, M, N, K);
512 +}
513 +
514 +static inline unsigned int ltq_get_pll0_fosc(void)
515 +{
516 +       if (CGU_PLL0_BYPASS)
517 +               return get_input_clock(0);
518 +       else
519 +               return !CGU_PLL0_CFG_FRAC_EN
520 +                       ? dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN, 0,
521 +                               CGU_PLL0_CFG_DSMSEL,
522 +                               CGU_PLL0_PHASE_DIVIDER_ENABLE)
523 +                       : dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN,
524 +                               CGU_PLL0_CFG_PLLK, CGU_PLL0_CFG_DSMSEL,
525 +                               CGU_PLL0_PHASE_DIVIDER_ENABLE);
526 +}
527 +
528 +static unsigned int ltq_get_pll0_fdiv(void)
529 +{
530 +       unsigned int div = CGU_PLL2_CFG_INPUT_DIV + 1;
531 +
532 +       return (ltq_get_pll0_fosc() + (div >> 1)) / div;
533 +}
534 +
535 +unsigned long ltq_danube_io_region_clock(void)
536 +{
537 +       unsigned int ret = ltq_get_pll0_fosc();
538 +
539 +       switch (ltq_cgu_r32(LTQ_CGU_PLL2_CFG) & CGU_SYS_DDR_SEL) {
540 +       default:
541 +       case 0:
542 +               return (ret + 1) / 2;
543 +       case 1:
544 +               return (ret * 2 + 2) / 5;
545 +       case 2:
546 +               return (ret + 1) / 3;
547 +       case 3:
548 +               return (ret + 2) / 4;
549 +       }
550 +}
551 +
552 +unsigned long ltq_danube_fpi_bus_clock(int fpi)
553 +{
554 +       unsigned long ret = ltq_danube_io_region_clock();
555 +
556 +       if ((fpi == 2) && (ltq_cgu_r32(LTQ_CGU_SYS) & CGU_SYS_FPI_SEL))
557 +               ret >>= 1;
558 +       return ret;
559 +}
560 +
561 +unsigned long ltq_danube_cpu_hz(void)
562 +{
563 +       switch (ltq_cgu_r32(LTQ_CGU_SYS) & 0xc) {
564 +       case 0:
565 +               return CLOCK_333M;
566 +       case 4:
567 +               return DDR_HZ;
568 +       case 8:
569 +               return DDR_HZ << 1;
570 +       default:
571 +               return DDR_HZ >> 1;
572 +       }
573 +}
574 +
575 +unsigned long ltq_danube_fpi_hz(void)
576 +{
577 +       unsigned long ddr_clock = DDR_HZ;
578 +
579 +       if (ltq_cgu_r32(LTQ_CGU_SYS) & 0x40)
580 +               return ddr_clock >> 1;
581 +       return ddr_clock;
582 +}
583 diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
584 index 8fd13a1..c5782b5 100644
585 --- a/arch/mips/lantiq/xway/sysctrl.c
586 +++ b/arch/mips/lantiq/xway/sysctrl.c
587 @@ -8,17 +8,48 @@
588  
589  #include <linux/ioport.h>
590  #include <linux/export.h>
591 +#include <linux/clkdev.h>
592  
593  #include <lantiq_soc.h>
594  
595 +#include "../clk.h"
596  #include "../devices.h"
597  
598  /* clock control register */
599  #define LTQ_CGU_IFCCR  0x0018
600 +/* system clock register */
601 +#define LTQ_CGU_SYS     0x0010
602  
603  /* the enable / disable registers */
604  #define LTQ_PMU_PWDCR  0x1C
605  #define LTQ_PMU_PWDSR  0x20
606 +#define LTQ_PMU_PWDCR1 0x24
607 +#define LTQ_PMU_PWDSR1 0x28
608 +
609 +#define PWDCR(x) ((x) ? (LTQ_PMU_PWDCR1) : (LTQ_PMU_PWDCR))
610 +#define PWDSR(x) ((x) ? (LTQ_PMU_PWDSR1) : (LTQ_PMU_PWDSR))
611 +
612 +/* CGU - clock generation unit */
613 +#define CGU_EPHY               0x10
614 +
615 +/* PMU - power management unit */
616 +#define PMU_DMA                        0x0020
617 +#define PMU_SPI                        0x0100
618 +#define PMU_EPHY               0x0080
619 +#define PMU_USB                        0x8041
620 +#define PMU_STP                        0x0800
621 +#define PMU_GPT                        0x1000
622 +#define PMU_PPE                        0x2000
623 +#define PMU_FPI                        0x4000
624 +#define PMU_SWITCH             0x10000000
625 +#define PMU_AHBS               0x2000
626 +#define PMU_AHBM               0x8000
627 +#define PMU_PCIE_CLK            0x80000000
628 +
629 +#define PMU1_PCIE_PHY          0x0001
630 +#define PMU1_PCIE_CTL          0x0002
631 +#define PMU1_PCIE_MSI          0x0020
632 +#define PMU1_PCIE_PDI          0x0010
633  
634  #define ltq_pmu_w32(x, y)      ltq_w32((x), ltq_pmu_membase + (y))
635  #define ltq_pmu_r32(x)         ltq_r32(ltq_pmu_membase + (x))
636 @@ -36,28 +67,64 @@ void __iomem *ltq_cgu_membase;
637  void __iomem *ltq_ebu_membase;
638  static void __iomem *ltq_pmu_membase;
639  
640 -void ltq_cgu_enable(unsigned int clk)
641 +static int ltq_cgu_enable(struct clk *clk)
642  {
643 -       ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | clk, LTQ_CGU_IFCCR);
644 +       ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | clk->bits, LTQ_CGU_IFCCR);
645 +       return 0;
646  }
647  
648 -void ltq_pmu_enable(unsigned int module)
649 +static void ltq_cgu_disable(struct clk *clk)
650 +{
651 +       ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~clk->bits, LTQ_CGU_IFCCR);
652 +}
653 +
654 +static int ltq_pmu_enable(struct clk *clk)
655  {
656         int err = 1000000;
657  
658 -       ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) & ~module, LTQ_PMU_PWDCR);
659 -       do {} while (--err && (ltq_pmu_r32(LTQ_PMU_PWDSR) & module));
660 +       ltq_pmu_w32(ltq_pmu_r32(PWDCR(clk->module)) & ~clk->bits,
661 +               PWDCR(clk->module));
662 +       do {} while (--err && (ltq_pmu_r32(PWDSR(clk->module)) & clk->bits));
663  
664         if (!err)
665                 panic("activating PMU module failed!\n");
666 +
667 +       return 0;
668  }
669 -EXPORT_SYMBOL(ltq_pmu_enable);
670  
671 -void ltq_pmu_disable(unsigned int module)
672 +static void ltq_pmu_disable(struct clk *clk)
673  {
674 -       ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) | module, LTQ_PMU_PWDCR);
675 +       ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) | clk->bits, LTQ_PMU_PWDCR);
676 +}
677 +
678 +static inline void clkdev_add_pmu(const char *dev, const char *con,
679 +                                       unsigned int module, unsigned int bits)
680 +{
681 +       struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
682 +
683 +       clk->cl.dev_id = dev;
684 +       clk->cl.con_id = con;
685 +       clk->cl.clk = clk;
686 +       clk->enable = ltq_pmu_enable;
687 +       clk->disable = ltq_pmu_disable;
688 +       clk->module = module;
689 +       clk->bits = bits;
690 +       clkdev_add(&clk->cl);
691 +}
692 +
693 +static inline void clkdev_add_cgu(const char *dev, const char *con,
694 +                                       unsigned int bits)
695 +{
696 +       struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
697 +
698 +       clk->cl.dev_id = dev;
699 +       clk->cl.con_id = con;
700 +       clk->cl.clk = clk;
701 +       clk->enable = ltq_cgu_enable;
702 +       clk->disable = ltq_cgu_disable;
703 +       clk->bits = bits;
704 +       clkdev_add(&clk->cl);
705  }
706 -EXPORT_SYMBOL(ltq_pmu_disable);
707  
708  void __init ltq_soc_init(void)
709  {
710 @@ -75,4 +142,23 @@ void __init ltq_soc_init(void)
711  
712         /* make sure to unprotect the memory region where flash is located */
713         ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_BUSCON0) & ~EBU_WRDIS, LTQ_EBU_BUSCON0);
714 +
715 +       /* add our clocks */
716 +       clkdev_add_pmu("ltq_dma", NULL, 0, PMU_DMA);
717 +       clkdev_add_pmu("ltq_stp", NULL, 0, PMU_STP);
718 +       clkdev_add_pmu("ltq_spi", NULL, 0, PMU_SPI);
719 +       clkdev_add_pmu("ltq_etop", NULL, 0, PMU_PPE);
720 +       if (ltq_is_ase()) {
721 +               if (ltq_cgu_r32(LTQ_CGU_SYS) & (1 << 5))
722 +                       clkdev_add_static(CLOCK_266M, CLOCK_133M, CLOCK_133M);
723 +               else
724 +                       clkdev_add_static(CLOCK_133M, CLOCK_133M, CLOCK_133M);
725 +               clkdev_add_cgu("ltq_etop", "ephycgu", CGU_EPHY),
726 +               clkdev_add_pmu("ltq_etop", "ephy", 0, PMU_EPHY);
727 +       } else {
728 +               clkdev_add_static(ltq_danube_cpu_hz(), ltq_danube_fpi_hz(),
729 +                                       ltq_danube_io_region_clock());
730 +               if (ltq_is_ar9())
731 +                       clkdev_add_pmu("ltq_etop", "switch", 0, PMU_SWITCH);
732 +       }
733  }
734 -- 
735 1.7.9.1
736