Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cpufreq-pxa3xx.c
Go to the documentation of this file.
1 /*
2  * linux/arch/arm/mach-pxa/cpufreq-pxa3xx.c
3  *
4  * Copyright (C) 2008 Marvell International Ltd.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  */
11 
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/sched.h>
15 #include <linux/init.h>
16 #include <linux/cpufreq.h>
17 #include <linux/slab.h>
18 #include <linux/io.h>
19 
20 #include <mach/pxa3xx-regs.h>
21 
22 #include "generic.h"
23 
24 #define HSS_104M (0)
25 #define HSS_156M (1)
26 #define HSS_208M (2)
27 #define HSS_312M (3)
28 
29 #define SMCFS_78M (0)
30 #define SMCFS_104M (2)
31 #define SMCFS_208M (5)
32 
33 #define SFLFS_104M (0)
34 #define SFLFS_156M (1)
35 #define SFLFS_208M (2)
36 #define SFLFS_312M (3)
37 
38 #define XSPCLK_156M (0)
39 #define XSPCLK_NONE (3)
40 
41 #define DMCFS_26M (0)
42 #define DMCFS_260M (3)
43 
45  unsigned int cpufreq_mhz;
46  unsigned int core_xl : 5;
47  unsigned int core_xn : 3;
48  unsigned int hss : 2;
49  unsigned int dmcfs : 2;
50  unsigned int smcfs : 3;
51  unsigned int sflfs : 2;
52  unsigned int df_clkdiv : 3;
53 
54  int vcc_core; /* in mV */
55  int vcc_sram; /* in mV */
56 };
57 
58 #define OP(cpufreq, _xl, _xn, _hss, _dmc, _smc, _sfl, _dfi, vcore, vsram) \
59 { \
60  .cpufreq_mhz = cpufreq, \
61  .core_xl = _xl, \
62  .core_xn = _xn, \
63  .hss = HSS_##_hss##M, \
64  .dmcfs = DMCFS_##_dmc##M, \
65  .smcfs = SMCFS_##_smc##M, \
66  .sflfs = SFLFS_##_sfl##M, \
67  .df_clkdiv = _dfi, \
68  .vcc_core = vcore, \
69  .vcc_sram = vsram, \
70 }
71 
72 static struct pxa3xx_freq_info pxa300_freqs[] = {
73  /* CPU XL XN HSS DMEM SMEM SRAM DFI VCC_CORE VCC_SRAM */
74  OP(104, 8, 1, 104, 260, 78, 104, 3, 1000, 1100), /* 104MHz */
75  OP(208, 16, 1, 104, 260, 104, 156, 2, 1000, 1100), /* 208MHz */
76  OP(416, 16, 2, 156, 260, 104, 208, 2, 1100, 1200), /* 416MHz */
77  OP(624, 24, 2, 208, 260, 208, 312, 3, 1375, 1400), /* 624MHz */
78 };
79 
80 static struct pxa3xx_freq_info pxa320_freqs[] = {
81  /* CPU XL XN HSS DMEM SMEM SRAM DFI VCC_CORE VCC_SRAM */
82  OP(104, 8, 1, 104, 260, 78, 104, 3, 1000, 1100), /* 104MHz */
83  OP(208, 16, 1, 104, 260, 104, 156, 2, 1000, 1100), /* 208MHz */
84  OP(416, 16, 2, 156, 260, 104, 208, 2, 1100, 1200), /* 416MHz */
85  OP(624, 24, 2, 208, 260, 208, 312, 3, 1375, 1400), /* 624MHz */
86  OP(806, 31, 2, 208, 260, 208, 312, 3, 1400, 1400), /* 806MHz */
87 };
88 
89 static unsigned int pxa3xx_freqs_num;
90 static struct pxa3xx_freq_info *pxa3xx_freqs;
91 static struct cpufreq_frequency_table *pxa3xx_freqs_table;
92 
93 static int setup_freqs_table(struct cpufreq_policy *policy,
94  struct pxa3xx_freq_info *freqs, int num)
95 {
97  int i;
98 
99  table = kzalloc((num + 1) * sizeof(*table), GFP_KERNEL);
100  if (table == NULL)
101  return -ENOMEM;
102 
103  for (i = 0; i < num; i++) {
104  table[i].index = i;
105  table[i].frequency = freqs[i].cpufreq_mhz * 1000;
106  }
107  table[num].index = i;
108  table[num].frequency = CPUFREQ_TABLE_END;
109 
110  pxa3xx_freqs = freqs;
111  pxa3xx_freqs_num = num;
112  pxa3xx_freqs_table = table;
113 
114  return cpufreq_frequency_table_cpuinfo(policy, table);
115 }
116 
117 static void __update_core_freq(struct pxa3xx_freq_info *info)
118 {
120  uint32_t accr = ACCR;
121  uint32_t xclkcfg;
122 
124  accr |= ACCR_XN(info->core_xn) | ACCR_XL(info->core_xl);
125 
126  /* No clock until core PLL is re-locked */
127  accr |= ACCR_XSPCLK(XSPCLK_NONE);
128 
129  xclkcfg = (info->core_xn == 2) ? 0x3 : 0x2; /* turbo bit */
130 
131  ACCR = accr;
132  __asm__("mcr p14, 0, %0, c6, c0, 0\n" : : "r"(xclkcfg));
133 
134  while ((ACSR & mask) != (accr & mask))
135  cpu_relax();
136 }
137 
138 static void __update_bus_freq(struct pxa3xx_freq_info *info)
139 {
140  uint32_t mask;
141  uint32_t accr = ACCR;
142 
145 
146  accr &= ~mask;
147  accr |= ACCR_SMCFS(info->smcfs) | ACCR_SFLFS(info->sflfs) |
148  ACCR_HSS(info->hss) | ACCR_DMCFS(info->dmcfs);
149 
150  ACCR = accr;
151 
152  while ((ACSR & mask) != (accr & mask))
153  cpu_relax();
154 }
155 
156 static int pxa3xx_cpufreq_verify(struct cpufreq_policy *policy)
157 {
158  return cpufreq_frequency_table_verify(policy, pxa3xx_freqs_table);
159 }
160 
161 static unsigned int pxa3xx_cpufreq_get(unsigned int cpu)
162 {
164 }
165 
166 static int pxa3xx_cpufreq_set(struct cpufreq_policy *policy,
167  unsigned int target_freq,
168  unsigned int relation)
169 {
170  struct pxa3xx_freq_info *next;
171  struct cpufreq_freqs freqs;
172  unsigned long flags;
173  int idx;
174 
175  if (policy->cpu != 0)
176  return -EINVAL;
177 
178  /* Lookup the next frequency */
179  if (cpufreq_frequency_table_target(policy, pxa3xx_freqs_table,
180  target_freq, relation, &idx))
181  return -EINVAL;
182 
183  next = &pxa3xx_freqs[idx];
184 
185  freqs.old = policy->cur;
186  freqs.new = next->cpufreq_mhz * 1000;
187  freqs.cpu = policy->cpu;
188 
189  pr_debug("CPU frequency from %d MHz to %d MHz%s\n",
190  freqs.old / 1000, freqs.new / 1000,
191  (freqs.old == freqs.new) ? " (skipped)" : "");
192 
193  if (freqs.old == target_freq)
194  return 0;
195 
197 
198  local_irq_save(flags);
199  __update_core_freq(next);
200  __update_bus_freq(next);
201  local_irq_restore(flags);
202 
204 
205  return 0;
206 }
207 
208 static int pxa3xx_cpufreq_init(struct cpufreq_policy *policy)
209 {
210  int ret = -EINVAL;
211 
212  /* set default policy and cpuinfo */
213  policy->cpuinfo.min_freq = 104000;
214  policy->cpuinfo.max_freq = (cpu_is_pxa320()) ? 806000 : 624000;
215  policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */
216  policy->max = pxa3xx_get_clk_frequency_khz(0);
217  policy->cur = policy->min = policy->max;
218 
219  if (cpu_is_pxa300() || cpu_is_pxa310())
220  ret = setup_freqs_table(policy, ARRAY_AND_SIZE(pxa300_freqs));
221 
222  if (cpu_is_pxa320())
223  ret = setup_freqs_table(policy, ARRAY_AND_SIZE(pxa320_freqs));
224 
225  if (ret) {
226  pr_err("failed to setup frequency table\n");
227  return ret;
228  }
229 
230  pr_info("CPUFREQ support for PXA3xx initialized\n");
231  return 0;
232 }
233 
234 static struct cpufreq_driver pxa3xx_cpufreq_driver = {
235  .verify = pxa3xx_cpufreq_verify,
236  .target = pxa3xx_cpufreq_set,
237  .init = pxa3xx_cpufreq_init,
238  .get = pxa3xx_cpufreq_get,
239  .name = "pxa3xx-cpufreq",
240 };
241 
242 static int __init cpufreq_init(void)
243 {
244  if (cpu_is_pxa3xx())
245  return cpufreq_register_driver(&pxa3xx_cpufreq_driver);
246 
247  return 0;
248 }
249 module_init(cpufreq_init);
250 
251 static void __exit cpufreq_exit(void)
252 {
253  cpufreq_unregister_driver(&pxa3xx_cpufreq_driver);
254 }
255 module_exit(cpufreq_exit);
256 
257 MODULE_DESCRIPTION("CPU frequency scaling driver for PXA3xx");
258 MODULE_LICENSE("GPL");