aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-sa1100
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2013-04-04 08:54:16 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-04-10 07:19:24 -0400
commit59a2e613d07fbd592ff711c87458eabcf9c98902 (patch)
tree18ebcdccafa518791a17c94133144d17e73f6807 /arch/arm/mach-sa1100
parentb7e614c8bf5c898b172d7dfed9853fdda35be5cc (diff)
cpufreq: sa11x0: move cpufreq driver to drivers/cpufreq
This patch moves cpufreq driver of ARM based sa11x0 platform to drivers/cpufreq. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Acked-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'arch/arm/mach-sa1100')
-rw-r--r--arch/arm/mach-sa1100/Kconfig26
-rw-r--r--arch/arm/mach-sa1100/Makefile3
-rw-r--r--arch/arm/mach-sa1100/cpu-sa1100.c248
-rw-r--r--arch/arm/mach-sa1100/cpu-sa1110.c407
-rw-r--r--arch/arm/mach-sa1100/include/mach/generic.h1
5 files changed, 14 insertions, 671 deletions
diff --git a/arch/arm/mach-sa1100/Kconfig b/arch/arm/mach-sa1100/Kconfig
index ca14dbdcfb22..04f9784ff0ed 100644
--- a/arch/arm/mach-sa1100/Kconfig
+++ b/arch/arm/mach-sa1100/Kconfig
@@ -4,7 +4,7 @@ menu "SA11x0 Implementations"
4 4
5config SA1100_ASSABET 5config SA1100_ASSABET
6 bool "Assabet" 6 bool "Assabet"
7 select CPU_FREQ_SA1110 7 select ARM_SA1110_CPUFREQ
8 help 8 help
9 Say Y here if you are using the Intel(R) StrongARM(R) SA-1110 9 Say Y here if you are using the Intel(R) StrongARM(R) SA-1110
10 Microprocessor Development Board (also known as the Assabet). 10 Microprocessor Development Board (also known as the Assabet).
@@ -20,7 +20,7 @@ config ASSABET_NEPONSET
20 20
21config SA1100_CERF 21config SA1100_CERF
22 bool "CerfBoard" 22 bool "CerfBoard"
23 select CPU_FREQ_SA1110 23 select ARM_SA1110_CPUFREQ
24 help 24 help
25 The Intrinsyc CerfBoard is based on the StrongARM 1110 (Discontinued). 25 The Intrinsyc CerfBoard is based on the StrongARM 1110 (Discontinued).
26 More information is available at: 26 More information is available at:
@@ -47,7 +47,7 @@ endchoice
47 47
48config SA1100_COLLIE 48config SA1100_COLLIE
49 bool "Sharp Zaurus SL5500" 49 bool "Sharp Zaurus SL5500"
50 # FIXME: select CPU_FREQ_SA11x0 50 # FIXME: select ARM_SA11x0_CPUFREQ
51 select SHARP_LOCOMO 51 select SHARP_LOCOMO
52 select SHARP_PARAM 52 select SHARP_PARAM
53 select SHARP_SCOOP 53 select SHARP_SCOOP
@@ -56,7 +56,7 @@ config SA1100_COLLIE
56 56
57config SA1100_H3100 57config SA1100_H3100
58 bool "Compaq iPAQ H3100" 58 bool "Compaq iPAQ H3100"
59 select CPU_FREQ_SA1110 59 select ARM_SA1110_CPUFREQ
60 select HTC_EGPIO 60 select HTC_EGPIO
61 help 61 help
62 Say Y here if you intend to run this kernel on the Compaq iPAQ 62 Say Y here if you intend to run this kernel on the Compaq iPAQ
@@ -67,7 +67,7 @@ config SA1100_H3100
67 67
68config SA1100_H3600 68config SA1100_H3600
69 bool "Compaq iPAQ H3600/H3700" 69 bool "Compaq iPAQ H3600/H3700"
70 select CPU_FREQ_SA1110 70 select ARM_SA1110_CPUFREQ
71 select HTC_EGPIO 71 select HTC_EGPIO
72 help 72 help
73 Say Y here if you intend to run this kernel on the Compaq iPAQ 73 Say Y here if you intend to run this kernel on the Compaq iPAQ
@@ -78,7 +78,7 @@ config SA1100_H3600
78 78
79config SA1100_BADGE4 79config SA1100_BADGE4
80 bool "HP Labs BadgePAD 4" 80 bool "HP Labs BadgePAD 4"
81 select CPU_FREQ_SA1100 81 select ARM_SA1100_CPUFREQ
82 select SA1111 82 select SA1111
83 help 83 help
84 Say Y here if you want to build a kernel for the HP Laboratories 84 Say Y here if you want to build a kernel for the HP Laboratories
@@ -86,7 +86,7 @@ config SA1100_BADGE4
86 86
87config SA1100_JORNADA720 87config SA1100_JORNADA720
88 bool "HP Jornada 720" 88 bool "HP Jornada 720"
89 # FIXME: select CPU_FREQ_SA11x0 89 # FIXME: select ARM_SA11x0_CPUFREQ
90 select SA1111 90 select SA1111
91 help 91 help
92 Say Y here if you want to build a kernel for the HP Jornada 720 92 Say Y here if you want to build a kernel for the HP Jornada 720
@@ -105,14 +105,14 @@ config SA1100_JORNADA720_SSP
105 105
106config SA1100_HACKKIT 106config SA1100_HACKKIT
107 bool "HackKit Core CPU Board" 107 bool "HackKit Core CPU Board"
108 select CPU_FREQ_SA1100 108 select ARM_SA1100_CPUFREQ
109 help 109 help
110 Say Y here to support the HackKit Core CPU Board 110 Say Y here to support the HackKit Core CPU Board
111 <http://hackkit.eletztrick.de>; 111 <http://hackkit.eletztrick.de>;
112 112
113config SA1100_LART 113config SA1100_LART
114 bool "LART" 114 bool "LART"
115 select CPU_FREQ_SA1100 115 select ARM_SA1100_CPUFREQ
116 help 116 help
117 Say Y here if you are using the Linux Advanced Radio Terminal 117 Say Y here if you are using the Linux Advanced Radio Terminal
118 (also known as the LART). See <http://www.lartmaker.nl/> for 118 (also known as the LART). See <http://www.lartmaker.nl/> for
@@ -120,7 +120,7 @@ config SA1100_LART
120 120
121config SA1100_NANOENGINE 121config SA1100_NANOENGINE
122 bool "nanoEngine" 122 bool "nanoEngine"
123 select CPU_FREQ_SA1110 123 select ARM_SA1110_CPUFREQ
124 select PCI 124 select PCI
125 select PCI_NANOENGINE 125 select PCI_NANOENGINE
126 help 126 help
@@ -130,7 +130,7 @@ config SA1100_NANOENGINE
130 130
131config SA1100_PLEB 131config SA1100_PLEB
132 bool "PLEB" 132 bool "PLEB"
133 select CPU_FREQ_SA1100 133 select ARM_SA1100_CPUFREQ
134 help 134 help
135 Say Y here if you are using version 1 of the Portable Linux 135 Say Y here if you are using version 1 of the Portable Linux
136 Embedded Board (also known as PLEB). 136 Embedded Board (also known as PLEB).
@@ -139,7 +139,7 @@ config SA1100_PLEB
139 139
140config SA1100_SHANNON 140config SA1100_SHANNON
141 bool "Shannon" 141 bool "Shannon"
142 select CPU_FREQ_SA1100 142 select ARM_SA1100_CPUFREQ
143 help 143 help
144 The Shannon (also known as a Tuxscreen, and also as a IS2630) was a 144 The Shannon (also known as a Tuxscreen, and also as a IS2630) was a
145 limited edition webphone produced by Philips. The Shannon is a SA1100 145 limited edition webphone produced by Philips. The Shannon is a SA1100
@@ -148,7 +148,7 @@ config SA1100_SHANNON
148 148
149config SA1100_SIMPAD 149config SA1100_SIMPAD
150 bool "Simpad" 150 bool "Simpad"
151 select CPU_FREQ_SA1110 151 select ARM_SA1110_CPUFREQ
152 help 152 help
153 The SIEMENS webpad SIMpad is based on the StrongARM 1110. There 153 The SIEMENS webpad SIMpad is based on the StrongARM 1110. There
154 are two different versions CL4 and SL4. CL4 has 32MB RAM and 16MB 154 are two different versions CL4 and SL4. CL4 has 32MB RAM and 16MB
diff --git a/arch/arm/mach-sa1100/Makefile b/arch/arm/mach-sa1100/Makefile
index 1aed9e70465d..2732eef48966 100644
--- a/arch/arm/mach-sa1100/Makefile
+++ b/arch/arm/mach-sa1100/Makefile
@@ -8,9 +8,6 @@ obj-m :=
8obj-n := 8obj-n :=
9obj- := 9obj- :=
10 10
11obj-$(CONFIG_CPU_FREQ_SA1100) += cpu-sa1100.o
12obj-$(CONFIG_CPU_FREQ_SA1110) += cpu-sa1110.o
13
14# Specific board support 11# Specific board support
15obj-$(CONFIG_SA1100_ASSABET) += assabet.o 12obj-$(CONFIG_SA1100_ASSABET) += assabet.o
16obj-$(CONFIG_ASSABET_NEPONSET) += neponset.o 13obj-$(CONFIG_ASSABET_NEPONSET) += neponset.o
diff --git a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c
deleted file mode 100644
index 32687617c7a5..000000000000
--- a/arch/arm/mach-sa1100/cpu-sa1100.c
+++ /dev/null
@@ -1,248 +0,0 @@
1/*
2 * cpu-sa1100.c: clock scaling for the SA1100
3 *
4 * Copyright (C) 2000 2001, The Delft University of Technology
5 *
6 * Authors:
7 * - Johan Pouwelse (J.A.Pouwelse@its.tudelft.nl): initial version
8 * - Erik Mouw (J.A.K.Mouw@its.tudelft.nl):
9 * - major rewrite for linux-2.3.99
10 * - rewritten for the more generic power management scheme in
11 * linux-2.4.5-rmk1
12 *
13 * This software has been developed while working on the LART
14 * computing board (http://www.lartmaker.nl/), which is
15 * sponsored by the Mobile Multi-media Communications
16 * (http://www.mobimedia.org/) and Ubiquitous Communications
17 * (http://www.ubicom.tudelft.nl/) projects.
18 *
19 * The authors can be reached at:
20 *
21 * Erik Mouw
22 * Information and Communication Theory Group
23 * Faculty of Information Technology and Systems
24 * Delft University of Technology
25 * P.O. Box 5031
26 * 2600 GA Delft
27 * The Netherlands
28 *
29 *
30 * This program is free software; you can redistribute it and/or modify
31 * it under the terms of the GNU General Public License as published by
32 * the Free Software Foundation; either version 2 of the License, or
33 * (at your option) any later version.
34 *
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
39 *
40 * You should have received a copy of the GNU General Public License
41 * along with this program; if not, write to the Free Software
42 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
43 *
44 *
45 * Theory of operations
46 * ====================
47 *
48 * Clock scaling can be used to lower the power consumption of the CPU
49 * core. This will give you a somewhat longer running time.
50 *
51 * The SA-1100 has a single register to change the core clock speed:
52 *
53 * PPCR 0x90020014 PLL config
54 *
55 * However, the DRAM timings are closely related to the core clock
56 * speed, so we need to change these, too. The used registers are:
57 *
58 * MDCNFG 0xA0000000 DRAM config
59 * MDCAS0 0xA0000004 Access waveform
60 * MDCAS1 0xA0000008 Access waveform
61 * MDCAS2 0xA000000C Access waveform
62 *
63 * Care must be taken to change the DRAM parameters the correct way,
64 * because otherwise the DRAM becomes unusable and the kernel will
65 * crash.
66 *
67 * The simple solution to avoid a kernel crash is to put the actual
68 * clock change in ROM and jump to that code from the kernel. The main
69 * disadvantage is that the ROM has to be modified, which is not
70 * possible on all SA-1100 platforms. Another disadvantage is that
71 * jumping to ROM makes clock switching unnecessary complicated.
72 *
73 * The idea behind this driver is that the memory configuration can be
74 * changed while running from DRAM (even with interrupts turned on!)
75 * as long as all re-configuration steps yield a valid DRAM
76 * configuration. The advantages are clear: it will run on all SA-1100
77 * platforms, and the code is very simple.
78 *
79 * If you really want to understand what is going on in
80 * sa1100_update_dram_timings(), you'll have to read sections 8.2,
81 * 9.5.7.3, and 10.2 from the "Intel StrongARM SA-1100 Microprocessor
82 * Developers Manual" (available for free from Intel).
83 *
84 */
85
86#include <linux/kernel.h>
87#include <linux/types.h>
88#include <linux/init.h>
89#include <linux/cpufreq.h>
90#include <linux/io.h>
91
92#include <asm/cputype.h>
93
94#include <mach/hardware.h>
95
96#include "generic.h"
97
98struct sa1100_dram_regs {
99 int speed;
100 u32 mdcnfg;
101 u32 mdcas0;
102 u32 mdcas1;
103 u32 mdcas2;
104};
105
106
107static struct cpufreq_driver sa1100_driver;
108
109static struct sa1100_dram_regs sa1100_dram_settings[] = {
110 /*speed, mdcnfg, mdcas0, mdcas1, mdcas2, clock freq */
111 { 59000, 0x00dc88a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/* 59.0 MHz */
112 { 73700, 0x011490a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/* 73.7 MHz */
113 { 88500, 0x014e90a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/* 88.5 MHz */
114 {103200, 0x01889923, 0xcccccccf, 0xfffffffc, 0xffffffff},/* 103.2 MHz */
115 {118000, 0x01c29923, 0x9999998f, 0xfffffff9, 0xffffffff},/* 118.0 MHz */
116 {132700, 0x01fb2123, 0x9999998f, 0xfffffff9, 0xffffffff},/* 132.7 MHz */
117 {147500, 0x02352123, 0x3333330f, 0xfffffff3, 0xffffffff},/* 147.5 MHz */
118 {162200, 0x026b29a3, 0x38e38e1f, 0xfff8e38e, 0xffffffff},/* 162.2 MHz */
119 {176900, 0x02a329a3, 0x71c71c1f, 0xfff1c71c, 0xffffffff},/* 176.9 MHz */
120 {191700, 0x02dd31a3, 0xe38e383f, 0xffe38e38, 0xffffffff},/* 191.7 MHz */
121 {206400, 0x03153223, 0xc71c703f, 0xffc71c71, 0xffffffff},/* 206.4 MHz */
122 {221200, 0x034fba23, 0xc71c703f, 0xffc71c71, 0xffffffff},/* 221.2 MHz */
123 {235900, 0x03853a23, 0xe1e1e07f, 0xe1e1e1e1, 0xffffffe1},/* 235.9 MHz */
124 {250700, 0x03bf3aa3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3},/* 250.7 MHz */
125 {265400, 0x03f7c2a3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3},/* 265.4 MHz */
126 {280200, 0x0431c2a3, 0x878780ff, 0x87878787, 0xffffff87},/* 280.2 MHz */
127 { 0, 0, 0, 0, 0 } /* last entry */
128};
129
130static void sa1100_update_dram_timings(int current_speed, int new_speed)
131{
132 struct sa1100_dram_regs *settings = sa1100_dram_settings;
133
134 /* find speed */
135 while (settings->speed != 0) {
136 if (new_speed == settings->speed)
137 break;
138
139 settings++;
140 }
141
142 if (settings->speed == 0) {
143 panic("%s: couldn't find dram setting for speed %d\n",
144 __func__, new_speed);
145 }
146
147 /* No risk, no fun: run with interrupts on! */
148 if (new_speed > current_speed) {
149 /* We're going FASTER, so first relax the memory
150 * timings before changing the core frequency
151 */
152
153 /* Half the memory access clock */
154 MDCNFG |= MDCNFG_CDB2;
155
156 /* The order of these statements IS important, keep 8
157 * pulses!!
158 */
159 MDCAS2 = settings->mdcas2;
160 MDCAS1 = settings->mdcas1;
161 MDCAS0 = settings->mdcas0;
162 MDCNFG = settings->mdcnfg;
163 } else {
164 /* We're going SLOWER: first decrease the core
165 * frequency and then tighten the memory settings.
166 */
167
168 /* Half the memory access clock */
169 MDCNFG |= MDCNFG_CDB2;
170
171 /* The order of these statements IS important, keep 8
172 * pulses!!
173 */
174 MDCAS0 = settings->mdcas0;
175 MDCAS1 = settings->mdcas1;
176 MDCAS2 = settings->mdcas2;
177 MDCNFG = settings->mdcnfg;
178 }
179}
180
181static int sa1100_target(struct cpufreq_policy *policy,
182 unsigned int target_freq,
183 unsigned int relation)
184{
185 unsigned int cur = sa11x0_getspeed(0);
186 unsigned int new_ppcr;
187 struct cpufreq_freqs freqs;
188
189 new_ppcr = sa11x0_freq_to_ppcr(target_freq);
190 switch (relation) {
191 case CPUFREQ_RELATION_L:
192 if (sa11x0_ppcr_to_freq(new_ppcr) > policy->max)
193 new_ppcr--;
194 break;
195 case CPUFREQ_RELATION_H:
196 if ((sa11x0_ppcr_to_freq(new_ppcr) > target_freq) &&
197 (sa11x0_ppcr_to_freq(new_ppcr - 1) >= policy->min))
198 new_ppcr--;
199 break;
200 }
201
202 freqs.old = cur;
203 freqs.new = sa11x0_ppcr_to_freq(new_ppcr);
204
205 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
206
207 if (freqs.new > cur)
208 sa1100_update_dram_timings(cur, freqs.new);
209
210 PPCR = new_ppcr;
211
212 if (freqs.new < cur)
213 sa1100_update_dram_timings(cur, freqs.new);
214
215 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
216
217 return 0;
218}
219
220static int __init sa1100_cpu_init(struct cpufreq_policy *policy)
221{
222 if (policy->cpu != 0)
223 return -EINVAL;
224 policy->cur = policy->min = policy->max = sa11x0_getspeed(0);
225 policy->cpuinfo.min_freq = 59000;
226 policy->cpuinfo.max_freq = 287000;
227 policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
228 return 0;
229}
230
231static struct cpufreq_driver sa1100_driver __refdata = {
232 .flags = CPUFREQ_STICKY,
233 .verify = sa11x0_verify_speed,
234 .target = sa1100_target,
235 .get = sa11x0_getspeed,
236 .init = sa1100_cpu_init,
237 .name = "sa1100",
238};
239
240static int __init sa1100_dram_init(void)
241{
242 if (cpu_is_sa1100())
243 return cpufreq_register_driver(&sa1100_driver);
244 else
245 return -ENODEV;
246}
247
248arch_initcall(sa1100_dram_init);
diff --git a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c
deleted file mode 100644
index 38a77330dc16..000000000000
--- a/arch/arm/mach-sa1100/cpu-sa1110.c
+++ /dev/null
@@ -1,407 +0,0 @@
1/*
2 * linux/arch/arm/mach-sa1100/cpu-sa1110.c
3 *
4 * Copyright (C) 2001 Russell King
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 version 2 as
8 * published by the Free Software Foundation.
9 *
10 * Note: there are two erratas that apply to the SA1110 here:
11 * 7 - SDRAM auto-power-up failure (rev A0)
12 * 13 - Corruption of internal register reads/writes following
13 * SDRAM reads (rev A0, B0, B1)
14 *
15 * We ignore rev. A0 and B0 devices; I don't think they're worth supporting.
16 *
17 * The SDRAM type can be passed on the command line as cpu_sa1110.sdram=type
18 */
19#include <linux/cpufreq.h>
20#include <linux/delay.h>
21#include <linux/init.h>
22#include <linux/io.h>
23#include <linux/kernel.h>
24#include <linux/moduleparam.h>
25#include <linux/types.h>
26
27#include <asm/cputype.h>
28#include <asm/mach-types.h>
29
30#include <mach/hardware.h>
31
32#include "generic.h"
33
34#undef DEBUG
35
36struct sdram_params {
37 const char name[20];
38 u_char rows; /* bits */
39 u_char cas_latency; /* cycles */
40 u_char tck; /* clock cycle time (ns) */
41 u_char trcd; /* activate to r/w (ns) */
42 u_char trp; /* precharge to activate (ns) */
43 u_char twr; /* write recovery time (ns) */
44 u_short refresh; /* refresh time for array (us) */
45};
46
47struct sdram_info {
48 u_int mdcnfg;
49 u_int mdrefr;
50 u_int mdcas[3];
51};
52
53static struct sdram_params sdram_tbl[] __initdata = {
54 { /* Toshiba TC59SM716 CL2 */
55 .name = "TC59SM716-CL2",
56 .rows = 12,
57 .tck = 10,
58 .trcd = 20,
59 .trp = 20,
60 .twr = 10,
61 .refresh = 64000,
62 .cas_latency = 2,
63 }, { /* Toshiba TC59SM716 CL3 */
64 .name = "TC59SM716-CL3",
65 .rows = 12,
66 .tck = 8,
67 .trcd = 20,
68 .trp = 20,
69 .twr = 8,
70 .refresh = 64000,
71 .cas_latency = 3,
72 }, { /* Samsung K4S641632D TC75 */
73 .name = "K4S641632D",
74 .rows = 14,
75 .tck = 9,
76 .trcd = 27,
77 .trp = 20,
78 .twr = 9,
79 .refresh = 64000,
80 .cas_latency = 3,
81 }, { /* Samsung K4S281632B-1H */
82 .name = "K4S281632B-1H",
83 .rows = 12,
84 .tck = 10,
85 .trp = 20,
86 .twr = 10,
87 .refresh = 64000,
88 .cas_latency = 3,
89 }, { /* Samsung KM416S4030CT */
90 .name = "KM416S4030CT",
91 .rows = 13,
92 .tck = 8,
93 .trcd = 24, /* 3 CLKs */
94 .trp = 24, /* 3 CLKs */
95 .twr = 16, /* Trdl: 2 CLKs */
96 .refresh = 64000,
97 .cas_latency = 3,
98 }, { /* Winbond W982516AH75L CL3 */
99 .name = "W982516AH75L",
100 .rows = 16,
101 .tck = 8,
102 .trcd = 20,
103 .trp = 20,
104 .twr = 8,
105 .refresh = 64000,
106 .cas_latency = 3,
107 }, { /* Micron MT48LC8M16A2TG-75 */
108 .name = "MT48LC8M16A2TG-75",
109 .rows = 12,
110 .tck = 8,
111 .trcd = 20,
112 .trp = 20,
113 .twr = 8,
114 .refresh = 64000,
115 .cas_latency = 3,
116 },
117};
118
119static struct sdram_params sdram_params;
120
121/*
122 * Given a period in ns and frequency in khz, calculate the number of
123 * cycles of frequency in period. Note that we round up to the next
124 * cycle, even if we are only slightly over.
125 */
126static inline u_int ns_to_cycles(u_int ns, u_int khz)
127{
128 return (ns * khz + 999999) / 1000000;
129}
130
131/*
132 * Create the MDCAS register bit pattern.
133 */
134static inline void set_mdcas(u_int *mdcas, int delayed, u_int rcd)
135{
136 u_int shift;
137
138 rcd = 2 * rcd - 1;
139 shift = delayed + 1 + rcd;
140
141 mdcas[0] = (1 << rcd) - 1;
142 mdcas[0] |= 0x55555555 << shift;
143 mdcas[1] = mdcas[2] = 0x55555555 << (shift & 1);
144}
145
146static void
147sdram_calculate_timing(struct sdram_info *sd, u_int cpu_khz,
148 struct sdram_params *sdram)
149{
150 u_int mem_khz, sd_khz, trp, twr;
151
152 mem_khz = cpu_khz / 2;
153 sd_khz = mem_khz;
154
155 /*
156 * If SDCLK would invalidate the SDRAM timings,
157 * run SDCLK at half speed.
158 *
159 * CPU steppings prior to B2 must either run the memory at
160 * half speed or use delayed read latching (errata 13).
161 */
162 if ((ns_to_cycles(sdram->tck, sd_khz) > 1) ||
163 (CPU_REVISION < CPU_SA1110_B2 && sd_khz < 62000))
164 sd_khz /= 2;
165
166 sd->mdcnfg = MDCNFG & 0x007f007f;
167
168 twr = ns_to_cycles(sdram->twr, mem_khz);
169
170 /* trp should always be >1 */
171 trp = ns_to_cycles(sdram->trp, mem_khz) - 1;
172 if (trp < 1)
173 trp = 1;
174
175 sd->mdcnfg |= trp << 8;
176 sd->mdcnfg |= trp << 24;
177 sd->mdcnfg |= sdram->cas_latency << 12;
178 sd->mdcnfg |= sdram->cas_latency << 28;
179 sd->mdcnfg |= twr << 14;
180 sd->mdcnfg |= twr << 30;
181
182 sd->mdrefr = MDREFR & 0xffbffff0;
183 sd->mdrefr |= 7;
184
185 if (sd_khz != mem_khz)
186 sd->mdrefr |= MDREFR_K1DB2;
187
188 /* initial number of '1's in MDCAS + 1 */
189 set_mdcas(sd->mdcas, sd_khz >= 62000,
190 ns_to_cycles(sdram->trcd, mem_khz));
191
192#ifdef DEBUG
193 printk(KERN_DEBUG "MDCNFG: %08x MDREFR: %08x MDCAS0: %08x MDCAS1: %08x MDCAS2: %08x\n",
194 sd->mdcnfg, sd->mdrefr, sd->mdcas[0], sd->mdcas[1],
195 sd->mdcas[2]);
196#endif
197}
198
199/*
200 * Set the SDRAM refresh rate.
201 */
202static inline void sdram_set_refresh(u_int dri)
203{
204 MDREFR = (MDREFR & 0xffff000f) | (dri << 4);
205 (void) MDREFR;
206}
207
208/*
209 * Update the refresh period. We do this such that we always refresh
210 * the SDRAMs within their permissible period. The refresh period is
211 * always a multiple of the memory clock (fixed at cpu_clock / 2).
212 *
213 * FIXME: we don't currently take account of burst accesses here,
214 * but neither do Intels DM nor Angel.
215 */
216static void
217sdram_update_refresh(u_int cpu_khz, struct sdram_params *sdram)
218{
219 u_int ns_row = (sdram->refresh * 1000) >> sdram->rows;
220 u_int dri = ns_to_cycles(ns_row, cpu_khz / 2) / 32;
221
222#ifdef DEBUG
223 mdelay(250);
224 printk(KERN_DEBUG "new dri value = %d\n", dri);
225#endif
226
227 sdram_set_refresh(dri);
228}
229
230/*
231 * Ok, set the CPU frequency.
232 */
233static int sa1110_target(struct cpufreq_policy *policy,
234 unsigned int target_freq,
235 unsigned int relation)
236{
237 struct sdram_params *sdram = &sdram_params;
238 struct cpufreq_freqs freqs;
239 struct sdram_info sd;
240 unsigned long flags;
241 unsigned int ppcr, unused;
242
243 switch (relation) {
244 case CPUFREQ_RELATION_L:
245 ppcr = sa11x0_freq_to_ppcr(target_freq);
246 if (sa11x0_ppcr_to_freq(ppcr) > policy->max)
247 ppcr--;
248 break;
249 case CPUFREQ_RELATION_H:
250 ppcr = sa11x0_freq_to_ppcr(target_freq);
251 if (ppcr && (sa11x0_ppcr_to_freq(ppcr) > target_freq) &&
252 (sa11x0_ppcr_to_freq(ppcr-1) >= policy->min))
253 ppcr--;
254 break;
255 default:
256 return -EINVAL;
257 }
258
259 freqs.old = sa11x0_getspeed(0);
260 freqs.new = sa11x0_ppcr_to_freq(ppcr);
261
262 sdram_calculate_timing(&sd, freqs.new, sdram);
263
264#if 0
265 /*
266 * These values are wrong according to the SA1110 documentation
267 * and errata, but they seem to work. Need to get a storage
268 * scope on to the SDRAM signals to work out why.
269 */
270 if (policy->max < 147500) {
271 sd.mdrefr |= MDREFR_K1DB2;
272 sd.mdcas[0] = 0xaaaaaa7f;
273 } else {
274 sd.mdrefr &= ~MDREFR_K1DB2;
275 sd.mdcas[0] = 0xaaaaaa9f;
276 }
277 sd.mdcas[1] = 0xaaaaaaaa;
278 sd.mdcas[2] = 0xaaaaaaaa;
279#endif
280
281 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
282
283 /*
284 * The clock could be going away for some time. Set the SDRAMs
285 * to refresh rapidly (every 64 memory clock cycles). To get
286 * through the whole array, we need to wait 262144 mclk cycles.
287 * We wait 20ms to be safe.
288 */
289 sdram_set_refresh(2);
290 if (!irqs_disabled())
291 msleep(20);
292 else
293 mdelay(20);
294
295 /*
296 * Reprogram the DRAM timings with interrupts disabled, and
297 * ensure that we are doing this within a complete cache line.
298 * This means that we won't access SDRAM for the duration of
299 * the programming.
300 */
301 local_irq_save(flags);
302 asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
303 udelay(10);
304 __asm__ __volatile__("\n\
305 b 2f \n\
306 .align 5 \n\
3071: str %3, [%1, #0] @ MDCNFG \n\
308 str %4, [%1, #28] @ MDREFR \n\
309 str %5, [%1, #4] @ MDCAS0 \n\
310 str %6, [%1, #8] @ MDCAS1 \n\
311 str %7, [%1, #12] @ MDCAS2 \n\
312 str %8, [%2, #0] @ PPCR \n\
313 ldr %0, [%1, #0] \n\
314 b 3f \n\
3152: b 1b \n\
3163: nop \n\
317 nop"
318 : "=&r" (unused)
319 : "r" (&MDCNFG), "r" (&PPCR), "0" (sd.mdcnfg),
320 "r" (sd.mdrefr), "r" (sd.mdcas[0]),
321 "r" (sd.mdcas[1]), "r" (sd.mdcas[2]), "r" (ppcr));
322 local_irq_restore(flags);
323
324 /*
325 * Now, return the SDRAM refresh back to normal.
326 */
327 sdram_update_refresh(freqs.new, sdram);
328
329 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
330
331 return 0;
332}
333
334static int __init sa1110_cpu_init(struct cpufreq_policy *policy)
335{
336 if (policy->cpu != 0)
337 return -EINVAL;
338 policy->cur = policy->min = policy->max = sa11x0_getspeed(0);
339 policy->cpuinfo.min_freq = 59000;
340 policy->cpuinfo.max_freq = 287000;
341 policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
342 return 0;
343}
344
345/* sa1110_driver needs __refdata because it must remain after init registers
346 * it with cpufreq_register_driver() */
347static struct cpufreq_driver sa1110_driver __refdata = {
348 .flags = CPUFREQ_STICKY,
349 .verify = sa11x0_verify_speed,
350 .target = sa1110_target,
351 .get = sa11x0_getspeed,
352 .init = sa1110_cpu_init,
353 .name = "sa1110",
354};
355
356static struct sdram_params *sa1110_find_sdram(const char *name)
357{
358 struct sdram_params *sdram;
359
360 for (sdram = sdram_tbl; sdram < sdram_tbl + ARRAY_SIZE(sdram_tbl);
361 sdram++)
362 if (strcmp(name, sdram->name) == 0)
363 return sdram;
364
365 return NULL;
366}
367
368static char sdram_name[16];
369
370static int __init sa1110_clk_init(void)
371{
372 struct sdram_params *sdram;
373 const char *name = sdram_name;
374
375 if (!cpu_is_sa1110())
376 return -ENODEV;
377
378 if (!name[0]) {
379 if (machine_is_assabet())
380 name = "TC59SM716-CL3";
381 if (machine_is_pt_system3())
382 name = "K4S641632D";
383 if (machine_is_h3100())
384 name = "KM416S4030CT";
385 if (machine_is_jornada720())
386 name = "K4S281632B-1H";
387 if (machine_is_nanoengine())
388 name = "MT48LC8M16A2TG-75";
389 }
390
391 sdram = sa1110_find_sdram(name);
392 if (sdram) {
393 printk(KERN_DEBUG "SDRAM: tck: %d trcd: %d trp: %d"
394 " twr: %d refresh: %d cas_latency: %d\n",
395 sdram->tck, sdram->trcd, sdram->trp,
396 sdram->twr, sdram->refresh, sdram->cas_latency);
397
398 memcpy(&sdram_params, sdram, sizeof(sdram_params));
399
400 return cpufreq_register_driver(&sa1110_driver);
401 }
402
403 return 0;
404}
405
406module_param_string(sdram, sdram_name, sizeof(sdram_name), 0);
407arch_initcall(sa1110_clk_init);
diff --git a/arch/arm/mach-sa1100/include/mach/generic.h b/arch/arm/mach-sa1100/include/mach/generic.h
new file mode 100644
index 000000000000..665542e0c9e2
--- /dev/null
+++ b/arch/arm/mach-sa1100/include/mach/generic.h
@@ -0,0 +1 @@
#include "../../generic.h"