xref: /openbmc/linux/arch/arm/mach-imx/cpu-imx5.c (revision 784a90c0)
1784a90c0SSascha Hauer /*
2784a90c0SSascha Hauer  * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
3784a90c0SSascha Hauer  *
4784a90c0SSascha Hauer  * The code contained herein is licensed under the GNU General Public
5784a90c0SSascha Hauer  * License. You may obtain a copy of the GNU General Public License
6784a90c0SSascha Hauer  * Version 2 or later at the following locations:
7784a90c0SSascha Hauer  *
8784a90c0SSascha Hauer  * http://www.opensource.org/licenses/gpl-license.html
9784a90c0SSascha Hauer  * http://www.gnu.org/copyleft/gpl.html
10784a90c0SSascha Hauer  *
11784a90c0SSascha Hauer  * This file contains the CPU initialization code.
12784a90c0SSascha Hauer  */
13784a90c0SSascha Hauer 
14784a90c0SSascha Hauer #include <linux/types.h>
15784a90c0SSascha Hauer #include <linux/kernel.h>
16784a90c0SSascha Hauer #include <linux/init.h>
17784a90c0SSascha Hauer #include <linux/module.h>
18784a90c0SSascha Hauer #include <mach/hardware.h>
19784a90c0SSascha Hauer #include <asm/io.h>
20784a90c0SSascha Hauer 
21784a90c0SSascha Hauer static int mx5_cpu_rev = -1;
22784a90c0SSascha Hauer 
23784a90c0SSascha Hauer #define IIM_SREV 0x24
24784a90c0SSascha Hauer #define MX50_HW_ADADIG_DIGPROG	0xB0
25784a90c0SSascha Hauer 
26784a90c0SSascha Hauer static int get_mx51_srev(void)
27784a90c0SSascha Hauer {
28784a90c0SSascha Hauer 	void __iomem *iim_base = MX51_IO_ADDRESS(MX51_IIM_BASE_ADDR);
29784a90c0SSascha Hauer 	u32 rev = readl(iim_base + IIM_SREV) & 0xff;
30784a90c0SSascha Hauer 
31784a90c0SSascha Hauer 	switch (rev) {
32784a90c0SSascha Hauer 	case 0x0:
33784a90c0SSascha Hauer 		return IMX_CHIP_REVISION_2_0;
34784a90c0SSascha Hauer 	case 0x10:
35784a90c0SSascha Hauer 		return IMX_CHIP_REVISION_3_0;
36784a90c0SSascha Hauer 	default:
37784a90c0SSascha Hauer 		return IMX_CHIP_REVISION_UNKNOWN;
38784a90c0SSascha Hauer 	}
39784a90c0SSascha Hauer }
40784a90c0SSascha Hauer 
41784a90c0SSascha Hauer /*
42784a90c0SSascha Hauer  * Returns:
43784a90c0SSascha Hauer  *	the silicon revision of the cpu
44784a90c0SSascha Hauer  *	-EINVAL - not a mx51
45784a90c0SSascha Hauer  */
46784a90c0SSascha Hauer int mx51_revision(void)
47784a90c0SSascha Hauer {
48784a90c0SSascha Hauer 	if (!cpu_is_mx51())
49784a90c0SSascha Hauer 		return -EINVAL;
50784a90c0SSascha Hauer 
51784a90c0SSascha Hauer 	if (mx5_cpu_rev == -1)
52784a90c0SSascha Hauer 		mx5_cpu_rev = get_mx51_srev();
53784a90c0SSascha Hauer 
54784a90c0SSascha Hauer 	return mx5_cpu_rev;
55784a90c0SSascha Hauer }
56784a90c0SSascha Hauer EXPORT_SYMBOL(mx51_revision);
57784a90c0SSascha Hauer 
58784a90c0SSascha Hauer #ifdef CONFIG_NEON
59784a90c0SSascha Hauer 
60784a90c0SSascha Hauer /*
61784a90c0SSascha Hauer  * All versions of the silicon before Rev. 3 have broken NEON implementations.
62784a90c0SSascha Hauer  * Dependent on link order - so the assumption is that vfp_init is called
63784a90c0SSascha Hauer  * before us.
64784a90c0SSascha Hauer  */
65784a90c0SSascha Hauer static int __init mx51_neon_fixup(void)
66784a90c0SSascha Hauer {
67784a90c0SSascha Hauer 	if (!cpu_is_mx51())
68784a90c0SSascha Hauer 		return 0;
69784a90c0SSascha Hauer 
70784a90c0SSascha Hauer 	if (mx51_revision() < IMX_CHIP_REVISION_3_0 && (elf_hwcap & HWCAP_NEON)) {
71784a90c0SSascha Hauer 		elf_hwcap &= ~HWCAP_NEON;
72784a90c0SSascha Hauer 		pr_info("Turning off NEON support, detected broken NEON implementation\n");
73784a90c0SSascha Hauer 	}
74784a90c0SSascha Hauer 	return 0;
75784a90c0SSascha Hauer }
76784a90c0SSascha Hauer 
77784a90c0SSascha Hauer late_initcall(mx51_neon_fixup);
78784a90c0SSascha Hauer #endif
79784a90c0SSascha Hauer 
80784a90c0SSascha Hauer static int get_mx53_srev(void)
81784a90c0SSascha Hauer {
82784a90c0SSascha Hauer 	void __iomem *iim_base = MX51_IO_ADDRESS(MX53_IIM_BASE_ADDR);
83784a90c0SSascha Hauer 	u32 rev = readl(iim_base + IIM_SREV) & 0xff;
84784a90c0SSascha Hauer 
85784a90c0SSascha Hauer 	switch (rev) {
86784a90c0SSascha Hauer 	case 0x0:
87784a90c0SSascha Hauer 		return IMX_CHIP_REVISION_1_0;
88784a90c0SSascha Hauer 	case 0x2:
89784a90c0SSascha Hauer 		return IMX_CHIP_REVISION_2_0;
90784a90c0SSascha Hauer 	case 0x3:
91784a90c0SSascha Hauer 		return IMX_CHIP_REVISION_2_1;
92784a90c0SSascha Hauer 	default:
93784a90c0SSascha Hauer 		return IMX_CHIP_REVISION_UNKNOWN;
94784a90c0SSascha Hauer 	}
95784a90c0SSascha Hauer }
96784a90c0SSascha Hauer 
97784a90c0SSascha Hauer /*
98784a90c0SSascha Hauer  * Returns:
99784a90c0SSascha Hauer  *	the silicon revision of the cpu
100784a90c0SSascha Hauer  *	-EINVAL - not a mx53
101784a90c0SSascha Hauer  */
102784a90c0SSascha Hauer int mx53_revision(void)
103784a90c0SSascha Hauer {
104784a90c0SSascha Hauer 	if (!cpu_is_mx53())
105784a90c0SSascha Hauer 		return -EINVAL;
106784a90c0SSascha Hauer 
107784a90c0SSascha Hauer 	if (mx5_cpu_rev == -1)
108784a90c0SSascha Hauer 		mx5_cpu_rev = get_mx53_srev();
109784a90c0SSascha Hauer 
110784a90c0SSascha Hauer 	return mx5_cpu_rev;
111784a90c0SSascha Hauer }
112784a90c0SSascha Hauer EXPORT_SYMBOL(mx53_revision);
113784a90c0SSascha Hauer 
114784a90c0SSascha Hauer static int get_mx50_srev(void)
115784a90c0SSascha Hauer {
116784a90c0SSascha Hauer 	void __iomem *anatop = ioremap(MX50_ANATOP_BASE_ADDR, SZ_8K);
117784a90c0SSascha Hauer 	u32 rev;
118784a90c0SSascha Hauer 
119784a90c0SSascha Hauer 	if (!anatop) {
120784a90c0SSascha Hauer 		mx5_cpu_rev = -EINVAL;
121784a90c0SSascha Hauer 		return 0;
122784a90c0SSascha Hauer 	}
123784a90c0SSascha Hauer 
124784a90c0SSascha Hauer 	rev = readl(anatop + MX50_HW_ADADIG_DIGPROG);
125784a90c0SSascha Hauer 	rev &= 0xff;
126784a90c0SSascha Hauer 
127784a90c0SSascha Hauer 	iounmap(anatop);
128784a90c0SSascha Hauer 	if (rev == 0x0)
129784a90c0SSascha Hauer 		return IMX_CHIP_REVISION_1_0;
130784a90c0SSascha Hauer 	else if (rev == 0x1)
131784a90c0SSascha Hauer 		return IMX_CHIP_REVISION_1_1;
132784a90c0SSascha Hauer 	return 0;
133784a90c0SSascha Hauer }
134784a90c0SSascha Hauer 
135784a90c0SSascha Hauer /*
136784a90c0SSascha Hauer  * Returns:
137784a90c0SSascha Hauer  *	the silicon revision of the cpu
138784a90c0SSascha Hauer  *	-EINVAL - not a mx50
139784a90c0SSascha Hauer  */
140784a90c0SSascha Hauer int mx50_revision(void)
141784a90c0SSascha Hauer {
142784a90c0SSascha Hauer 	if (!cpu_is_mx50())
143784a90c0SSascha Hauer 		return -EINVAL;
144784a90c0SSascha Hauer 
145784a90c0SSascha Hauer 	if (mx5_cpu_rev == -1)
146784a90c0SSascha Hauer 		mx5_cpu_rev = get_mx50_srev();
147784a90c0SSascha Hauer 
148784a90c0SSascha Hauer 	return mx5_cpu_rev;
149784a90c0SSascha Hauer }
150784a90c0SSascha Hauer EXPORT_SYMBOL(mx50_revision);
151784a90c0SSascha Hauer 
152784a90c0SSascha Hauer static int __init post_cpu_init(void)
153784a90c0SSascha Hauer {
154784a90c0SSascha Hauer 	unsigned int reg;
155784a90c0SSascha Hauer 	void __iomem *base;
156784a90c0SSascha Hauer 
157784a90c0SSascha Hauer 	if (cpu_is_mx51() || cpu_is_mx53()) {
158784a90c0SSascha Hauer 		if (cpu_is_mx51())
159784a90c0SSascha Hauer 			base = MX51_IO_ADDRESS(MX51_AIPS1_BASE_ADDR);
160784a90c0SSascha Hauer 		else
161784a90c0SSascha Hauer 			base = MX53_IO_ADDRESS(MX53_AIPS1_BASE_ADDR);
162784a90c0SSascha Hauer 
163784a90c0SSascha Hauer 		__raw_writel(0x0, base + 0x40);
164784a90c0SSascha Hauer 		__raw_writel(0x0, base + 0x44);
165784a90c0SSascha Hauer 		__raw_writel(0x0, base + 0x48);
166784a90c0SSascha Hauer 		__raw_writel(0x0, base + 0x4C);
167784a90c0SSascha Hauer 		reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
168784a90c0SSascha Hauer 		__raw_writel(reg, base + 0x50);
169784a90c0SSascha Hauer 
170784a90c0SSascha Hauer 		if (cpu_is_mx51())
171784a90c0SSascha Hauer 			base = MX51_IO_ADDRESS(MX51_AIPS2_BASE_ADDR);
172784a90c0SSascha Hauer 		else
173784a90c0SSascha Hauer 			base = MX53_IO_ADDRESS(MX53_AIPS2_BASE_ADDR);
174784a90c0SSascha Hauer 
175784a90c0SSascha Hauer 		__raw_writel(0x0, base + 0x40);
176784a90c0SSascha Hauer 		__raw_writel(0x0, base + 0x44);
177784a90c0SSascha Hauer 		__raw_writel(0x0, base + 0x48);
178784a90c0SSascha Hauer 		__raw_writel(0x0, base + 0x4C);
179784a90c0SSascha Hauer 		reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
180784a90c0SSascha Hauer 		__raw_writel(reg, base + 0x50);
181784a90c0SSascha Hauer 	}
182784a90c0SSascha Hauer 
183784a90c0SSascha Hauer 	return 0;
184784a90c0SSascha Hauer }
185784a90c0SSascha Hauer 
186784a90c0SSascha Hauer postcore_initcall(post_cpu_init);
187