~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to arch/mips/lantiq/xway/clk-xway.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 */
 
8
 
 
9
#include <linux/io.h>
 
10
#include <linux/export.h>
 
11
#include <linux/init.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
static unsigned int ltq_ram_clocks[] = {
 
21
        CLOCK_167M, CLOCK_133M, CLOCK_111M, CLOCK_83M };
 
22
#define DDR_HZ ltq_ram_clocks[ltq_cgu_r32(LTQ_CGU_SYS) & 0x3]
 
23
 
 
24
#define BASIC_FREQUENCY_1       35328000
 
25
#define BASIC_FREQUENCY_2       36000000
 
26
#define BASIS_REQUENCY_USB      12000000
 
27
 
 
28
#define GET_BITS(x, msb, lsb) \
 
29
        (((x) & ((1 << ((msb) + 1)) - 1)) >> (lsb))
 
30
 
 
31
#define LTQ_CGU_PLL0_CFG        0x0004
 
32
#define LTQ_CGU_PLL1_CFG        0x0008
 
33
#define LTQ_CGU_PLL2_CFG        0x000C
 
34
#define LTQ_CGU_SYS             0x0010
 
35
#define LTQ_CGU_UPDATE          0x0014
 
36
#define LTQ_CGU_IF_CLK          0x0018
 
37
#define LTQ_CGU_OSC_CON         0x001C
 
38
#define LTQ_CGU_SMD             0x0020
 
39
#define LTQ_CGU_CT1SR           0x0028
 
40
#define LTQ_CGU_CT2SR           0x002C
 
41
#define LTQ_CGU_PCMCR           0x0030
 
42
#define LTQ_CGU_PCI_CR          0x0034
 
43
#define LTQ_CGU_PD_PC           0x0038
 
44
#define LTQ_CGU_FMR             0x003C
 
45
 
 
46
#define CGU_PLL0_PHASE_DIVIDER_ENABLE   \
 
47
        (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 31))
 
48
#define CGU_PLL0_BYPASS                 \
 
49
        (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 30))
 
50
#define CGU_PLL0_CFG_DSMSEL             \
 
51
        (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 28))
 
52
#define CGU_PLL0_CFG_FRAC_EN            \
 
53
        (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 27))
 
54
#define CGU_PLL1_SRC                    \
 
55
        (ltq_cgu_r32(LTQ_CGU_PLL1_CFG) & (1 << 31))
 
56
#define CGU_PLL2_PHASE_DIVIDER_ENABLE   \
 
57
        (ltq_cgu_r32(LTQ_CGU_PLL2_CFG) & (1 << 20))
 
58
#define CGU_SYS_FPI_SEL                 (1 << 6)
 
59
#define CGU_SYS_DDR_SEL                 0x3
 
60
#define CGU_PLL0_SRC                    (1 << 29)
 
61
 
 
62
#define CGU_PLL0_CFG_PLLK       GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 26, 17)
 
63
#define CGU_PLL0_CFG_PLLN       GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 12, 6)
 
64
#define CGU_PLL0_CFG_PLLM       GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 5, 2)
 
65
#define CGU_PLL2_SRC            GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL2_CFG), 18, 17)
 
66
#define CGU_PLL2_CFG_INPUT_DIV  GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL2_CFG), 16, 13)
 
67
 
 
68
static unsigned int ltq_get_pll0_fdiv(void);
 
69
 
 
70
static inline unsigned int get_input_clock(int pll)
 
71
{
 
72
        switch (pll) {
 
73
        case 0:
 
74
                if (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & CGU_PLL0_SRC)
 
75
                        return BASIS_REQUENCY_USB;
 
76
                else if (CGU_PLL0_PHASE_DIVIDER_ENABLE)
 
77
                        return BASIC_FREQUENCY_1;
 
78
                else
 
79
                        return BASIC_FREQUENCY_2;
 
80
        case 1:
 
81
                if (CGU_PLL1_SRC)
 
82
                        return BASIS_REQUENCY_USB;
 
83
                else if (CGU_PLL0_PHASE_DIVIDER_ENABLE)
 
84
                        return BASIC_FREQUENCY_1;
 
85
                else
 
86
                        return BASIC_FREQUENCY_2;
 
87
        case 2:
 
88
                switch (CGU_PLL2_SRC) {
 
89
                case 0:
 
90
                        return ltq_get_pll0_fdiv();
 
91
                case 1:
 
92
                        return CGU_PLL2_PHASE_DIVIDER_ENABLE ?
 
93
                                BASIC_FREQUENCY_1 :
 
94
                                BASIC_FREQUENCY_2;
 
95
                case 2:
 
96
                        return BASIS_REQUENCY_USB;
 
97
                }
 
98
        default:
 
99
                return 0;
 
100
        }
 
101
}
 
102
 
 
103
static inline unsigned int cal_dsm(int pll, unsigned int num, unsigned int den)
 
104
{
 
105
        u64 res, clock = get_input_clock(pll);
 
106
 
 
107
        res = num * clock;
 
108
        do_div(res, den);
 
109
        return res;
 
110
}
 
111
 
 
112
static inline unsigned int mash_dsm(int pll, unsigned int M, unsigned int N,
 
113
        unsigned int K)
 
114
{
 
115
        unsigned int num = ((N + 1) << 10) + K;
 
116
        unsigned int den = (M + 1) << 10;
 
117
 
 
118
        return cal_dsm(pll, num, den);
 
119
}
 
120
 
 
121
static inline unsigned int ssff_dsm_1(int pll, unsigned int M, unsigned int N,
 
122
        unsigned int K)
 
123
{
 
124
        unsigned int num = ((N + 1) << 11) + K + 512;
 
125
        unsigned int den = (M + 1) << 11;
 
126
 
 
127
        return cal_dsm(pll, num, den);
 
128
}
 
129
 
 
130
static inline unsigned int ssff_dsm_2(int pll, unsigned int M, unsigned int N,
 
131
        unsigned int K)
 
132
{
 
133
        unsigned int num = K >= 512 ?
 
134
                ((N + 1) << 12) + K - 512 : ((N + 1) << 12) + K + 3584;
 
135
        unsigned int den = (M + 1) << 12;
 
136
 
 
137
        return cal_dsm(pll, num, den);
 
138
}
 
139
 
 
140
static inline unsigned int dsm(int pll, unsigned int M, unsigned int N,
 
141
        unsigned int K, unsigned int dsmsel, unsigned int phase_div_en)
 
142
{
 
143
        if (!dsmsel)
 
144
                return mash_dsm(pll, M, N, K);
 
145
        else if (!phase_div_en)
 
146
                return mash_dsm(pll, M, N, K);
 
147
        else
 
148
                return ssff_dsm_2(pll, M, N, K);
 
149
}
 
150
 
 
151
static inline unsigned int ltq_get_pll0_fosc(void)
 
152
{
 
153
        if (CGU_PLL0_BYPASS)
 
154
                return get_input_clock(0);
 
155
        else
 
156
                return !CGU_PLL0_CFG_FRAC_EN
 
157
                        ? dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN, 0,
 
158
                                CGU_PLL0_CFG_DSMSEL,
 
159
                                CGU_PLL0_PHASE_DIVIDER_ENABLE)
 
160
                        : dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN,
 
161
                                CGU_PLL0_CFG_PLLK, CGU_PLL0_CFG_DSMSEL,
 
162
                                CGU_PLL0_PHASE_DIVIDER_ENABLE);
 
163
}
 
164
 
 
165
static unsigned int ltq_get_pll0_fdiv(void)
 
166
{
 
167
        unsigned int div = CGU_PLL2_CFG_INPUT_DIV + 1;
 
168
 
 
169
        return (ltq_get_pll0_fosc() + (div >> 1)) / div;
 
170
}
 
171
 
 
172
unsigned int ltq_get_io_region_clock(void)
 
173
{
 
174
        unsigned int ret = ltq_get_pll0_fosc();
 
175
 
 
176
        switch (ltq_cgu_r32(LTQ_CGU_PLL2_CFG) & CGU_SYS_DDR_SEL) {
 
177
        default:
 
178
        case 0:
 
179
                return (ret + 1) / 2;
 
180
        case 1:
 
181
                return (ret * 2 + 2) / 5;
 
182
        case 2:
 
183
                return (ret + 1) / 3;
 
184
        case 3:
 
185
                return (ret + 2) / 4;
 
186
        }
 
187
}
 
188
EXPORT_SYMBOL(ltq_get_io_region_clock);
 
189
 
 
190
unsigned int ltq_get_fpi_bus_clock(int fpi)
 
191
{
 
192
        unsigned int ret = ltq_get_io_region_clock();
 
193
 
 
194
        if ((fpi == 2) && (ltq_cgu_r32(LTQ_CGU_SYS) & CGU_SYS_FPI_SEL))
 
195
                ret >>= 1;
 
196
        return ret;
 
197
}
 
198
EXPORT_SYMBOL(ltq_get_fpi_bus_clock);
 
199
 
 
200
unsigned int ltq_get_cpu_hz(void)
 
201
{
 
202
        switch (ltq_cgu_r32(LTQ_CGU_SYS) & 0xc) {
 
203
        case 0:
 
204
                return CLOCK_333M;
 
205
        case 4:
 
206
                return DDR_HZ;
 
207
        case 8:
 
208
                return DDR_HZ << 1;
 
209
        default:
 
210
                return DDR_HZ >> 1;
 
211
        }
 
212
}
 
213
EXPORT_SYMBOL(ltq_get_cpu_hz);
 
214
 
 
215
unsigned int ltq_get_fpi_hz(void)
 
216
{
 
217
        unsigned int ddr_clock = DDR_HZ;
 
218
 
 
219
        if (ltq_cgu_r32(LTQ_CGU_SYS) & 0x40)
 
220
                return ddr_clock >> 1;
 
221
        return ddr_clock;
 
222
}
 
223
EXPORT_SYMBOL(ltq_get_fpi_hz);