]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - arch/arm/mach-mx5/cpu.c
ENGR00139280: MX6: Add CPUFREQ support
[karo-tx-linux.git] / arch / arm / mach-mx5 / cpu.c
1 /*
2  * Copyright 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
3  *
4  * The code contained herein is licensed under the GNU General Public
5  * License. You may obtain a copy of the GNU General Public License
6  * Version 2 or later at the following locations:
7  *
8  * http://www.opensource.org/licenses/gpl-license.html
9  * http://www.gnu.org/copyleft/gpl.html
10  *
11  * This file contains the CPU initialization code.
12  */
13
14 #include <linux/types.h>
15 #include <linux/kernel.h>
16 #include <linux/init.h>
17 #include <linux/clk.h>
18 #include <linux/module.h>
19 #include <linux/iram_alloc.h>
20 #include <linux/regulator/consumer.h>
21 #include <linux/err.h>
22
23 #include <mach/hardware.h>
24 #include <asm/io.h>
25
26 #define CORTEXA8_PLAT_AMC       0x18
27 #define SRPG_NEON_PUPSCR        0x284
28 #define SRPG_NEON_PDNSCR        0x288
29 #define SRPG_ARM_PUPSCR         0x2A4
30 #define SRPG_ARM_PDNSCR         0x2A8
31 #define SRPG_EMPGC0_PUPSCR      0x2E4
32 #define SRPG_EMPGC0_PDNSCR      0x2E8
33 #define SRPG_EMPGC1_PUPSCR      0x304
34 #define SRPG_EMPGC1_PDNSCR      0x308
35
36 void __iomem *arm_plat_base;
37 void __iomem *gpc_base;
38 void __iomem *ccm_base;
39 struct cpu_op *(*get_cpu_op)(int *op);
40
41 extern void init_ddr_settings(void);
42
43 static int cpu_silicon_rev = -1;
44
45 #define IIM_SREV 0x24
46 #define MX50_HW_ADADIG_DIGPROG  0xB0
47
48 static int get_mx51_srev(void)
49 {
50         void __iomem *iim_base = MX51_IO_ADDRESS(MX51_IIM_BASE_ADDR);
51         u32 rev = readl(iim_base + IIM_SREV) & 0xff;
52
53         if (rev == 0x0)
54                 return IMX_CHIP_REVISION_2_0;
55         else if (rev == 0x10)
56                 return IMX_CHIP_REVISION_3_0;
57         return 0;
58 }
59
60 /*
61  * Returns:
62  *      the silicon revision of the cpu
63  *      -EINVAL - not a mx51
64  */
65 int mx51_revision(void)
66 {
67         if (!cpu_is_mx51())
68                 return -EINVAL;
69
70         if (cpu_silicon_rev == -1)
71                 cpu_silicon_rev = get_mx51_srev();
72
73         return cpu_silicon_rev;
74 }
75 EXPORT_SYMBOL(mx51_revision);
76
77 void mx51_display_revision(void)
78 {
79         int rev;
80         char *srev;
81         rev = mx51_revision();
82
83         switch (rev) {
84         case IMX_CHIP_REVISION_2_0:
85                 srev = IMX_CHIP_REVISION_2_0_STRING;
86                 break;
87         case IMX_CHIP_REVISION_3_0:
88                 srev = IMX_CHIP_REVISION_3_0_STRING;
89                 break;
90         default:
91                 srev = IMX_CHIP_REVISION_UNKNOWN_STRING;
92         }
93         printk(KERN_INFO "CPU identified as i.MX51, silicon rev %s\n", srev);
94 }
95 EXPORT_SYMBOL(mx51_display_revision);
96
97 #ifdef CONFIG_NEON
98
99 /*
100  * All versions of the silicon before Rev. 3 have broken NEON implementations.
101  * Dependent on link order - so the assumption is that vfp_init is called
102  * before us.
103  */
104 static int __init mx51_neon_fixup(void)
105 {
106         if (!cpu_is_mx51())
107                 return 0;
108
109         if (mx51_revision() < IMX_CHIP_REVISION_3_0 && (elf_hwcap & HWCAP_NEON)) {
110                 elf_hwcap &= ~HWCAP_NEON;
111                 pr_info("Turning off NEON support, detected broken NEON implementation\n");
112         }
113         return 0;
114 }
115
116 late_initcall(mx51_neon_fixup);
117 #endif
118
119 static int get_mx53_srev(void)
120 {
121         void __iomem *iim_base = MX51_IO_ADDRESS(MX53_IIM_BASE_ADDR);
122         u32 rev = readl(iim_base + IIM_SREV) & 0xff;
123
124         switch (rev) {
125         case 0x0:
126                 return IMX_CHIP_REVISION_1_0;
127         case 0x2:
128                 return IMX_CHIP_REVISION_2_0;
129         case 0x3:
130                 return IMX_CHIP_REVISION_2_1;
131         default:
132                 return IMX_CHIP_REVISION_UNKNOWN;
133         }
134 }
135
136 /*
137  * Returns:
138  *      the silicon revision of the cpu
139  *      -EINVAL - not a mx53
140  */
141 int mx53_revision(void)
142 {
143         if (!cpu_is_mx53())
144                 return -EINVAL;
145
146         if (cpu_silicon_rev == -1)
147                 cpu_silicon_rev = get_mx53_srev();
148
149         return cpu_silicon_rev;
150 }
151 EXPORT_SYMBOL(mx53_revision);
152 #define MX50_HW_ADADIG_DIGPROG  0xB0
153
154 static int get_mx50_srev(void)
155 {
156         void __iomem *anatop = ioremap(MX50_ANATOP_BASE_ADDR, SZ_8K);
157         u32 rev;
158
159         if (!anatop) {
160                 cpu_silicon_rev = -EINVAL;
161                 return 0;
162         }
163
164         rev = readl(anatop + MX50_HW_ADADIG_DIGPROG);
165         rev &= 0xff;
166
167         iounmap(anatop);
168         if (rev == 0x0)
169                 return IMX_CHIP_REVISION_1_0;
170         else if (rev == 0x1)
171                 return IMX_CHIP_REVISION_1_1;
172         return 0;
173 }
174
175 int mx5_set_cpu_voltage(struct regulator *gp_reg, u32 cpu_volt)
176 {
177         u32 ret = 0;
178
179         if (!IS_ERR(gp_reg)) {
180                 ret = regulator_set_voltage(gp_reg, cpu_volt, cpu_volt);
181                 if (ret < 0)
182                         printk(KERN_DEBUG "COULD NOT SET GP VOLTAGE!!!!\n");
183         }
184         return ret;
185 }
186
187 /*
188  * Returns:
189  *      the silicon revision of the cpu
190  *      -EINVAL - not a mx50
191  */
192 int mx50_revision(void)
193 {
194         if (!cpu_is_mx50())
195                 return -EINVAL;
196
197         if (cpu_silicon_rev == -1)
198                 cpu_silicon_rev = get_mx50_srev();
199
200         return cpu_silicon_rev;
201 }
202 EXPORT_SYMBOL(mx50_revision);
203
204 void mx53_display_revision(void)
205 {
206         int rev;
207         char *srev;
208         rev = mx53_revision();
209
210         switch (rev) {
211         case IMX_CHIP_REVISION_1_0:
212                 srev = IMX_CHIP_REVISION_1_0_STRING;
213                 break;
214         case IMX_CHIP_REVISION_2_0:
215                 srev = IMX_CHIP_REVISION_2_0_STRING;
216                 break;
217         case IMX_CHIP_REVISION_2_1:
218                 srev = IMX_CHIP_REVISION_2_1_STRING;
219                 break;
220         default:
221                 srev = IMX_CHIP_REVISION_UNKNOWN_STRING;
222         }
223         printk(KERN_INFO "CPU identified as i.MX53, silicon rev %s\n", srev);
224 }
225 EXPORT_SYMBOL(mx53_display_revision);
226
227 static int __init post_cpu_init(void)
228 {
229         unsigned int reg;
230         void __iomem *base;
231         struct clk *gpcclk = clk_get(NULL, "gpc_dvfs_clk");
232
233         if (cpu_is_mx51()) {
234                 ccm_base = MX51_IO_ADDRESS(MX51_CCM_BASE_ADDR);
235                 gpc_base = MX51_IO_ADDRESS(MX51_GPC_BASE_ADDR);
236                 arm_plat_base = MX51_IO_ADDRESS(MX51_ARM_BASE_ADDR);
237                 iram_init(MX51_IRAM_BASE_ADDR, MX51_IRAM_SIZE);
238         } else if (cpu_is_mx53()) {
239                 ccm_base = MX53_IO_ADDRESS(MX53_CCM_BASE_ADDR);
240                 gpc_base = MX53_IO_ADDRESS(MX53_GPC_BASE_ADDR);
241                 arm_plat_base = MX53_IO_ADDRESS(MX53_ARM_BASE_ADDR);
242                 iram_init(MX53_IRAM_BASE_ADDR, MX53_IRAM_SIZE);
243         } else {
244                 ccm_base = MX50_IO_ADDRESS(MX50_CCM_BASE_ADDR);
245                 gpc_base = MX50_IO_ADDRESS(MX50_GPC_BASE_ADDR);
246                 arm_plat_base = MX50_IO_ADDRESS(MX50_ARM_BASE_ADDR);
247                 iram_init(MX50_IRAM_BASE_ADDR, MX50_IRAM_SIZE);
248         }
249
250         if (cpu_is_mx51() || cpu_is_mx53()) {
251                 if (cpu_is_mx51()) {
252                         base = MX51_IO_ADDRESS(MX51_AIPS1_BASE_ADDR);
253                 } else {
254                         base = MX53_IO_ADDRESS(MX53_AIPS1_BASE_ADDR);
255                 }
256
257                 __raw_writel(0x0, base + 0x40);
258                 __raw_writel(0x0, base + 0x44);
259                 __raw_writel(0x0, base + 0x48);
260                 __raw_writel(0x0, base + 0x4C);
261                 reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
262                 __raw_writel(reg, base + 0x50);
263
264                 if (cpu_is_mx51())
265                         base = MX51_IO_ADDRESS(MX51_AIPS2_BASE_ADDR);
266                 else
267                         base = MX53_IO_ADDRESS(MX53_AIPS2_BASE_ADDR);
268
269                 __raw_writel(0x0, base + 0x40);
270                 __raw_writel(0x0, base + 0x44);
271                 __raw_writel(0x0, base + 0x48);
272                 __raw_writel(0x0, base + 0x4C);
273                 reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
274                 __raw_writel(reg, base + 0x50);
275         }
276         clk_enable(gpcclk);
277
278         /* Setup the number of clock cycles to wait for SRPG
279         * power up and power down requests.
280         */
281         __raw_writel(0x010F0201, gpc_base + SRPG_ARM_PUPSCR);
282         __raw_writel(0x010F0201, gpc_base + SRPG_NEON_PUPSCR);
283         __raw_writel(0x00000008, gpc_base + SRPG_EMPGC0_PUPSCR);
284         __raw_writel(0x00000008, gpc_base + SRPG_EMPGC1_PUPSCR);
285
286         __raw_writel(0x01010101, gpc_base + SRPG_ARM_PDNSCR);
287         __raw_writel(0x01010101, gpc_base + SRPG_NEON_PDNSCR);
288         __raw_writel(0x00000018, gpc_base + SRPG_EMPGC0_PDNSCR);
289         __raw_writel(0x00000018, gpc_base + SRPG_EMPGC1_PDNSCR);
290
291         clk_disable(gpcclk);
292         clk_put(gpcclk);
293
294         /* Set ALP bits to 000. Set ALP_EN bit in Arm Memory Controller reg. */
295         reg = 0x8;
296         __raw_writel(reg, arm_plat_base + CORTEXA8_PLAT_AMC);
297
298         if (cpu_is_mx50())
299                 init_ddr_settings();
300
301         return 0;
302 }
303
304 postcore_initcall(post_cpu_init);