1 /* 2 * Copyright 2008-2010 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/module.h> 18 #include <mach/hardware.h> 19 #include <linux/io.h> 20 21 static int mx5_cpu_rev = -1; 22 23 #define IIM_SREV 0x24 24 #define MX50_HW_ADADIG_DIGPROG 0xB0 25 26 static int get_mx51_srev(void) 27 { 28 void __iomem *iim_base = MX51_IO_ADDRESS(MX51_IIM_BASE_ADDR); 29 u32 rev = readl(iim_base + IIM_SREV) & 0xff; 30 31 switch (rev) { 32 case 0x0: 33 return IMX_CHIP_REVISION_2_0; 34 case 0x10: 35 return IMX_CHIP_REVISION_3_0; 36 default: 37 return IMX_CHIP_REVISION_UNKNOWN; 38 } 39 } 40 41 /* 42 * Returns: 43 * the silicon revision of the cpu 44 * -EINVAL - not a mx51 45 */ 46 int mx51_revision(void) 47 { 48 if (!cpu_is_mx51()) 49 return -EINVAL; 50 51 if (mx5_cpu_rev == -1) 52 mx5_cpu_rev = get_mx51_srev(); 53 54 return mx5_cpu_rev; 55 } 56 EXPORT_SYMBOL(mx51_revision); 57 58 #ifdef CONFIG_NEON 59 60 /* 61 * All versions of the silicon before Rev. 3 have broken NEON implementations. 62 * Dependent on link order - so the assumption is that vfp_init is called 63 * before us. 64 */ 65 static int __init mx51_neon_fixup(void) 66 { 67 if (!cpu_is_mx51()) 68 return 0; 69 70 if (mx51_revision() < IMX_CHIP_REVISION_3_0 && 71 (elf_hwcap & HWCAP_NEON)) { 72 elf_hwcap &= ~HWCAP_NEON; 73 pr_info("Turning off NEON support, detected broken NEON implementation\n"); 74 } 75 return 0; 76 } 77 78 late_initcall(mx51_neon_fixup); 79 #endif 80 81 static int get_mx53_srev(void) 82 { 83 void __iomem *iim_base = MX51_IO_ADDRESS(MX53_IIM_BASE_ADDR); 84 u32 rev = readl(iim_base + IIM_SREV) & 0xff; 85 86 switch (rev) { 87 case 0x0: 88 return IMX_CHIP_REVISION_1_0; 89 case 0x2: 90 return IMX_CHIP_REVISION_2_0; 91 case 0x3: 92 return IMX_CHIP_REVISION_2_1; 93 default: 94 return IMX_CHIP_REVISION_UNKNOWN; 95 } 96 } 97 98 /* 99 * Returns: 100 * the silicon revision of the cpu 101 * -EINVAL - not a mx53 102 */ 103 int mx53_revision(void) 104 { 105 if (!cpu_is_mx53()) 106 return -EINVAL; 107 108 if (mx5_cpu_rev == -1) 109 mx5_cpu_rev = get_mx53_srev(); 110 111 return mx5_cpu_rev; 112 } 113 EXPORT_SYMBOL(mx53_revision); 114 115 static int get_mx50_srev(void) 116 { 117 void __iomem *anatop = ioremap(MX50_ANATOP_BASE_ADDR, SZ_8K); 118 u32 rev; 119 120 if (!anatop) { 121 mx5_cpu_rev = -EINVAL; 122 return 0; 123 } 124 125 rev = readl(anatop + MX50_HW_ADADIG_DIGPROG); 126 rev &= 0xff; 127 128 iounmap(anatop); 129 if (rev == 0x0) 130 return IMX_CHIP_REVISION_1_0; 131 else if (rev == 0x1) 132 return IMX_CHIP_REVISION_1_1; 133 return 0; 134 } 135 136 /* 137 * Returns: 138 * the silicon revision of the cpu 139 * -EINVAL - not a mx50 140 */ 141 int mx50_revision(void) 142 { 143 if (!cpu_is_mx50()) 144 return -EINVAL; 145 146 if (mx5_cpu_rev == -1) 147 mx5_cpu_rev = get_mx50_srev(); 148 149 return mx5_cpu_rev; 150 } 151 EXPORT_SYMBOL(mx50_revision); 152 153 static int __init post_cpu_init(void) 154 { 155 unsigned int reg; 156 void __iomem *base; 157 158 if (cpu_is_mx51() || cpu_is_mx53()) { 159 if (cpu_is_mx51()) 160 base = MX51_IO_ADDRESS(MX51_AIPS1_BASE_ADDR); 161 else 162 base = MX53_IO_ADDRESS(MX53_AIPS1_BASE_ADDR); 163 164 __raw_writel(0x0, base + 0x40); 165 __raw_writel(0x0, base + 0x44); 166 __raw_writel(0x0, base + 0x48); 167 __raw_writel(0x0, base + 0x4C); 168 reg = __raw_readl(base + 0x50) & 0x00FFFFFF; 169 __raw_writel(reg, base + 0x50); 170 171 if (cpu_is_mx51()) 172 base = MX51_IO_ADDRESS(MX51_AIPS2_BASE_ADDR); 173 else 174 base = MX53_IO_ADDRESS(MX53_AIPS2_BASE_ADDR); 175 176 __raw_writel(0x0, base + 0x40); 177 __raw_writel(0x0, base + 0x44); 178 __raw_writel(0x0, base + 0x48); 179 __raw_writel(0x0, base + 0x4C); 180 reg = __raw_readl(base + 0x50) & 0x00FFFFFF; 181 __raw_writel(reg, base + 0x50); 182 } 183 184 return 0; 185 } 186 187 postcore_initcall(post_cpu_init); 188