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