Commit | Line | Data |
---|---|---|
2e4ea6e8 BD |
1 | /* arch/arm/plat-s3c/include/plat/cpu-freq.h |
2 | * | |
3 | * Copyright (c) 2006,2007,2009 Simtec Electronics | |
4 | * http://armlinux.simtec.co.uk/ | |
5 | * Ben Dooks <ben@simtec.co.uk> | |
6 | * | |
7 | * S3C CPU frequency scaling support - core support | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or modify | |
10 | * it under the terms of the GNU General Public License version 2 as | |
11 | * published by the Free Software Foundation. | |
12 | */ | |
13 | ||
14 | #include <plat/cpu-freq.h> | |
15 | ||
16 | #define MAX_BANKS (8) | |
17 | #define S3C2412_MAX_IO (8) | |
18 | ||
19 | /** | |
20 | * struct s3c2410_iobank_timing - IO bank timings for S3C2410 style timings | |
21 | * @bankcon: The cached version of settings in this structure. | |
22 | * @tacp: | |
23 | * @tacs: Time from address valid to nCS asserted. | |
24 | * @tcos: Time from nCS asserted to nOE or nWE asserted. | |
25 | * @tacc: Time that nOE or nWE is asserted. | |
26 | * @tcoh: Time nCS is held after nOE or nWE are released. | |
27 | * @tcah: Time address is held for after | |
28 | * @nwait_en: Whether nWAIT is enabled for this bank. | |
29 | * | |
30 | * This structure represents the IO timings for a S3C2410 style IO bank | |
31 | * used by the CPU frequency support if it needs to change the settings | |
32 | * of the IO. | |
33 | */ | |
34 | struct s3c2410_iobank_timing { | |
35 | unsigned long bankcon; | |
36 | unsigned int tacp; | |
37 | unsigned int tacs; | |
38 | unsigned int tcos; | |
39 | unsigned int tacc; | |
40 | unsigned int tcoh; /* nCS hold afrer nOE/nWE */ | |
41 | unsigned int tcah; /* Address hold after nCS */ | |
42 | unsigned char nwait_en; /* nWait enabled for bank. */ | |
43 | }; | |
44 | ||
45 | union s3c_iobank { | |
46 | struct s3c2410_iobank_timing *io_2410; | |
47 | }; | |
48 | ||
49 | /** | |
50 | * struct s3c_iotimings - Chip IO timings holder | |
51 | * @bank: The timings for each IO bank. | |
52 | */ | |
53 | struct s3c_iotimings { | |
54 | union s3c_iobank bank[MAX_BANKS]; | |
55 | }; | |
56 | ||
57 | /** | |
58 | * struct s3c_plltab - PLL table information. | |
59 | * @vals: List of PLL values. | |
60 | * @size: Size of the PLL table @vals. | |
61 | */ | |
62 | struct s3c_plltab { | |
63 | struct s3c_pllval *vals; | |
64 | int size; | |
65 | }; | |
66 | ||
d6fc87d3 BD |
67 | /** |
68 | * struct s3c_cpufreq_config - current cpu frequency configuration | |
69 | * @freq: The current settings for the core clocks. | |
70 | * @max: Maxium settings, derived from core, board and user settings. | |
71 | * @pll: The PLL table entry for the current PLL settings. | |
72 | * @divs: The divisor settings for the core clocks. | |
73 | * @info: The current core driver information. | |
74 | * @board: The information for the board we are running on. | |
75 | * @lock_pll: Set if the PLL settings cannot be changed. | |
76 | * | |
77 | * This is for the core drivers that need to know information about | |
78 | * the current settings and values. It should not be needed by any | |
79 | * device drivers. | |
80 | */ | |
81 | struct s3c_cpufreq_config { | |
82 | struct s3c_freq freq; | |
83 | struct s3c_freq max; | |
84 | struct cpufreq_frequency_table pll; | |
85 | struct s3c_clkdivs divs; | |
86 | struct s3c_cpufreq_info *info; /* for core, not drivers */ | |
87 | struct s3c_cpufreq_board *board; | |
88 | ||
89 | unsigned int lock_pll:1; | |
90 | }; | |
91 | ||
2e4ea6e8 BD |
92 | /** |
93 | * struct s3c_cpufreq_info - Information for the CPU frequency driver. | |
94 | * @name: The name of this implementation. | |
95 | * @max: The maximum frequencies for the system. | |
96 | * @latency: Transition latency to give to cpufreq. | |
97 | * @locktime_m: The lock-time in uS for the MPLL. | |
98 | * @locktime_u: The lock-time in uS for the UPLL. | |
99 | * @locttime_bits: The number of bits each LOCKTIME field. | |
100 | * @need_pll: Set if this driver needs to change the PLL values to acheive | |
101 | * any frequency changes. This is really only need by devices like the | |
102 | * S3C2410 where there is no or limited divider between the PLL and the | |
103 | * ARMCLK. | |
104 | * @resume_clocks: Update the clocks on resume. | |
105 | * @get_iotiming: Get the current IO timing data, mainly for use at start. | |
106 | * @set_iotiming: Update the IO timings from the cached copies calculated | |
107 | * from the @calc_iotiming entry when changing the frequency. | |
108 | * @calc_iotiming: Calculate and update the cached copies of the IO timings | |
109 | * from the newly calculated frequencies. | |
110 | * @calc_freqtable: Calculate (fill in) the given frequency table from the | |
111 | * current frequency configuration. If the table passed in is NULL, | |
112 | * then the return is the number of elements to be filled for allocation | |
113 | * of the table. | |
114 | * @set_refresh: Set the memory refresh configuration. | |
115 | * @set_fvco: Set the PLL frequencies. | |
116 | * @set_divs: Update the clock divisors. | |
117 | * @calc_divs: Calculate the clock divisors. | |
118 | */ | |
119 | struct s3c_cpufreq_info { | |
120 | const char *name; | |
121 | struct s3c_freq max; | |
122 | ||
123 | unsigned int latency; | |
124 | ||
125 | unsigned int locktime_m; | |
126 | unsigned int locktime_u; | |
127 | unsigned char locktime_bits; | |
128 | ||
129 | unsigned int need_pll:1; | |
130 | ||
131 | /* driver routines */ | |
132 | ||
133 | void (*resume_clocks)(void); | |
134 | ||
135 | int (*get_iotiming)(struct s3c_cpufreq_config *cfg, | |
136 | struct s3c_iotimings *timings); | |
137 | ||
138 | void (*set_iotiming)(struct s3c_cpufreq_config *cfg, | |
139 | struct s3c_iotimings *timings); | |
140 | ||
141 | int (*calc_iotiming)(struct s3c_cpufreq_config *cfg, | |
142 | struct s3c_iotimings *timings); | |
143 | ||
144 | int (*calc_freqtable)(struct s3c_cpufreq_config *cfg, | |
145 | struct cpufreq_frequency_table *t, | |
146 | size_t table_size); | |
147 | ||
148 | void (*set_refresh)(struct s3c_cpufreq_config *cfg); | |
149 | void (*set_fvco)(struct s3c_cpufreq_config *cfg); | |
150 | void (*set_divs)(struct s3c_cpufreq_config *cfg); | |
151 | int (*calc_divs)(struct s3c_cpufreq_config *cfg); | |
152 | }; | |
153 | ||
154 | extern int s3c_cpufreq_register(struct s3c_cpufreq_info *info); | |
155 | ||
156 | extern int s3c_plltab_register(struct cpufreq_frequency_table *plls, unsigned int plls_no); | |
157 | ||
158 | /* Useful utility functions. */ | |
159 | ||
160 | extern struct clk *s3c_cpufreq_clk_get(struct device *, const char *); | |
161 | ||
162 | /* S3C2410 and compatible exported functions */ | |
163 | ||
164 | extern void s3c2410_cpufreq_setrefresh(struct s3c_cpufreq_config *cfg); | |
165 | ||
166 | extern int s3c2410_iotiming_calc(struct s3c_cpufreq_config *cfg, | |
167 | struct s3c_iotimings *iot); | |
168 | ||
169 | extern int s3c2410_iotiming_get(struct s3c_cpufreq_config *cfg, | |
170 | struct s3c_iotimings *timings); | |
171 | ||
172 | extern void s3c2410_iotiming_set(struct s3c_cpufreq_config *cfg, | |
173 | struct s3c_iotimings *iot); | |
174 | ||
175 | extern void s3c2410_set_fvco(struct s3c_cpufreq_config *cfg); | |
176 | ||
177 | #ifdef CONFIG_CPU_FREQ_S3C24XX_DEBUG | |
178 | #define s3c_freq_dbg(x...) printk(KERN_INFO x) | |
179 | #else | |
180 | #define s3c_freq_dbg(x...) do { if (0) printk(x); } while (0) | |
181 | #endif /* CONFIG_CPU_FREQ_S3C24XX_DEBUG */ | |
182 | ||
183 | #ifdef CONFIG_CPU_FREQ_S3C24XX_IODEBUG | |
184 | #define s3c_freq_iodbg(x...) printk(KERN_INFO x) | |
185 | #else | |
186 | #define s3c_freq_iodbg(x...) do { if (0) printk(x); } while (0) | |
187 | #endif /* CONFIG_CPU_FREQ_S3C24XX_IODEBUG */ | |
188 | ||
189 | static inline int s3c_cpufreq_addfreq(struct cpufreq_frequency_table *table, | |
190 | int index, size_t table_size, | |
191 | unsigned int freq) | |
192 | { | |
193 | if (index < 0) | |
194 | return index; | |
195 | ||
196 | if (table) { | |
197 | if (index >= table_size) | |
198 | return -ENOMEM; | |
199 | ||
200 | s3c_freq_dbg("%s: { %d = %u kHz }\n", | |
201 | __func__, index, freq); | |
202 | ||
203 | table[index].index = index; | |
204 | table[index].frequency = freq; | |
205 | } | |
206 | ||
207 | return index + 1; | |
208 | } |