2 * Copyright 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved.
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:
8 * http://www.opensource.org/licenses/gpl-license.html
9 * http://www.gnu.org/copyleft/gpl.html
11 * This file contains the CPU initialization code.
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>
23 #include <mach/hardware.h>
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
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);
41 extern void init_ddr_settings(void);
43 static int cpu_silicon_rev = -1;
46 #define MX50_HW_ADADIG_DIGPROG 0xB0
48 static int get_mx51_srev(void)
50 void __iomem *iim_base = MX51_IO_ADDRESS(MX51_IIM_BASE_ADDR);
51 u32 rev = readl(iim_base + IIM_SREV) & 0xff;
54 return IMX_CHIP_REVISION_2_0;
56 return IMX_CHIP_REVISION_3_0;
62 * the silicon revision of the cpu
63 * -EINVAL - not a mx51
65 int mx51_revision(void)
70 if (cpu_silicon_rev == -1)
71 cpu_silicon_rev = get_mx51_srev();
73 return cpu_silicon_rev;
75 EXPORT_SYMBOL(mx51_revision);
77 void mx51_display_revision(void)
81 rev = mx51_revision();
84 case IMX_CHIP_REVISION_2_0:
85 srev = IMX_CHIP_REVISION_2_0_STRING;
87 case IMX_CHIP_REVISION_3_0:
88 srev = IMX_CHIP_REVISION_3_0_STRING;
91 srev = IMX_CHIP_REVISION_UNKNOWN_STRING;
93 printk(KERN_INFO "CPU identified as i.MX51, silicon rev %s\n", srev);
95 EXPORT_SYMBOL(mx51_display_revision);
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
104 static int __init mx51_neon_fixup(void)
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");
116 late_initcall(mx51_neon_fixup);
119 static int get_mx53_srev(void)
121 void __iomem *iim_base = MX51_IO_ADDRESS(MX53_IIM_BASE_ADDR);
122 u32 rev = readl(iim_base + IIM_SREV) & 0xff;
126 return IMX_CHIP_REVISION_1_0;
128 return IMX_CHIP_REVISION_2_0;
130 return IMX_CHIP_REVISION_2_1;
132 return IMX_CHIP_REVISION_UNKNOWN;
138 * the silicon revision of the cpu
139 * -EINVAL - not a mx53
141 int mx53_revision(void)
146 if (cpu_silicon_rev == -1)
147 cpu_silicon_rev = get_mx53_srev();
149 return cpu_silicon_rev;
151 EXPORT_SYMBOL(mx53_revision);
152 #define MX50_HW_ADADIG_DIGPROG 0xB0
154 static int get_mx50_srev(void)
156 void __iomem *anatop = ioremap(MX50_ANATOP_BASE_ADDR, SZ_8K);
160 cpu_silicon_rev = -EINVAL;
164 rev = readl(anatop + MX50_HW_ADADIG_DIGPROG);
169 return IMX_CHIP_REVISION_1_0;
171 return IMX_CHIP_REVISION_1_1;
175 int mx5_set_cpu_voltage(struct regulator *gp_reg, u32 cpu_volt)
179 if (!IS_ERR(gp_reg)) {
180 ret = regulator_set_voltage(gp_reg, cpu_volt, cpu_volt);
182 printk(KERN_DEBUG "COULD NOT SET GP VOLTAGE!!!!\n");
189 * the silicon revision of the cpu
190 * -EINVAL - not a mx50
192 int mx50_revision(void)
197 if (cpu_silicon_rev == -1)
198 cpu_silicon_rev = get_mx50_srev();
200 return cpu_silicon_rev;
202 EXPORT_SYMBOL(mx50_revision);
204 void mx53_display_revision(void)
208 rev = mx53_revision();
211 case IMX_CHIP_REVISION_1_0:
212 srev = IMX_CHIP_REVISION_1_0_STRING;
214 case IMX_CHIP_REVISION_2_0:
215 srev = IMX_CHIP_REVISION_2_0_STRING;
217 case IMX_CHIP_REVISION_2_1:
218 srev = IMX_CHIP_REVISION_2_1_STRING;
221 srev = IMX_CHIP_REVISION_UNKNOWN_STRING;
223 printk(KERN_INFO "CPU identified as i.MX53, silicon rev %s\n", srev);
225 EXPORT_SYMBOL(mx53_display_revision);
227 static int __init post_cpu_init(void)
231 struct clk *gpcclk = clk_get(NULL, "gpc_dvfs_clk");
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);
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);
250 if (cpu_is_mx51() || cpu_is_mx53()) {
252 base = MX51_IO_ADDRESS(MX51_AIPS1_BASE_ADDR);
254 base = MX53_IO_ADDRESS(MX53_AIPS1_BASE_ADDR);
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);
265 base = MX51_IO_ADDRESS(MX51_AIPS2_BASE_ADDR);
267 base = MX53_IO_ADDRESS(MX53_AIPS2_BASE_ADDR);
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);
278 /* Setup the number of clock cycles to wait for SRPG
279 * power up and power down requests.
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);
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);
294 /* Set ALP bits to 000. Set ALP_EN bit in Arm Memory Controller reg. */
296 __raw_writel(reg, arm_plat_base + CORTEXA8_PLAT_AMC);
304 postcore_initcall(post_cpu_init);