| Amit Kucheria | a329b48 | 2010-02-04 12:21:53 -0800 | [diff] [blame] | 1 | /* | 
| Dinh Nguyen | b66ff7a | 2010-11-15 11:30:00 -0600 | [diff] [blame] | 2 | * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved. | 
| Amit Kucheria | a329b48 | 2010-02-04 12:21:53 -0800 | [diff] [blame] | 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> | 
| Sascha Hauer | 5443856 | 2010-03-19 10:50:55 +0100 | [diff] [blame] | 17 | #include <linux/module.h> | 
| Amit Kucheria | a329b48 | 2010-02-04 12:21:53 -0800 | [diff] [blame] | 18 | #include <mach/hardware.h> | 
|  | 19 | #include <asm/io.h> | 
|  | 20 |  | 
| Sascha Hauer | 5443856 | 2010-03-19 10:50:55 +0100 | [diff] [blame] | 21 | static int cpu_silicon_rev = -1; | 
|  | 22 |  | 
| Dinh Nguyen | 9ab4650 | 2010-11-15 11:30:01 -0600 | [diff] [blame] | 23 | #define IIM_SREV 0x24 | 
| Dinh Nguyen | 16f246e | 2011-03-21 16:30:35 -0500 | [diff] [blame] | 24 | #define MX50_HW_ADADIG_DIGPROG	0xB0 | 
| Sascha Hauer | 5443856 | 2010-03-19 10:50:55 +0100 | [diff] [blame] | 25 |  | 
| Dinh Nguyen | 9ab4650 | 2010-11-15 11:30:01 -0600 | [diff] [blame] | 26 | static int get_mx51_srev(void) | 
| Sascha Hauer | 5443856 | 2010-03-19 10:50:55 +0100 | [diff] [blame] | 27 | { | 
| Dinh Nguyen | 9ab4650 | 2010-11-15 11:30:01 -0600 | [diff] [blame] | 28 | void __iomem *iim_base = MX51_IO_ADDRESS(MX51_IIM_BASE_ADDR); | 
|  | 29 | u32 rev = readl(iim_base + IIM_SREV) & 0xff; | 
| Sascha Hauer | 5443856 | 2010-03-19 10:50:55 +0100 | [diff] [blame] | 30 |  | 
| Dinh Nguyen | 9ab4650 | 2010-11-15 11:30:01 -0600 | [diff] [blame] | 31 | if (rev == 0x0) | 
|  | 32 | return IMX_CHIP_REVISION_2_0; | 
|  | 33 | else if (rev == 0x10) | 
|  | 34 | return IMX_CHIP_REVISION_3_0; | 
|  | 35 | return 0; | 
| Sascha Hauer | 5443856 | 2010-03-19 10:50:55 +0100 | [diff] [blame] | 36 | } | 
|  | 37 |  | 
|  | 38 | /* | 
|  | 39 | * Returns: | 
|  | 40 | *	the silicon revision of the cpu | 
|  | 41 | *	-EINVAL - not a mx51 | 
|  | 42 | */ | 
|  | 43 | int mx51_revision(void) | 
|  | 44 | { | 
|  | 45 | if (!cpu_is_mx51()) | 
|  | 46 | return -EINVAL; | 
|  | 47 |  | 
|  | 48 | if (cpu_silicon_rev == -1) | 
| Dinh Nguyen | 9ab4650 | 2010-11-15 11:30:01 -0600 | [diff] [blame] | 49 | cpu_silicon_rev = get_mx51_srev(); | 
| Sascha Hauer | 5443856 | 2010-03-19 10:50:55 +0100 | [diff] [blame] | 50 |  | 
|  | 51 | return cpu_silicon_rev; | 
|  | 52 | } | 
|  | 53 | EXPORT_SYMBOL(mx51_revision); | 
|  | 54 |  | 
| Fabio Estevam | 76422db | 2011-03-17 23:32:11 -0300 | [diff] [blame] | 55 | void mx51_display_revision(void) | 
|  | 56 | { | 
|  | 57 | int rev; | 
|  | 58 | char *srev; | 
|  | 59 | rev = mx51_revision(); | 
|  | 60 |  | 
|  | 61 | switch (rev) { | 
|  | 62 | case IMX_CHIP_REVISION_2_0: | 
|  | 63 | srev = IMX_CHIP_REVISION_2_0_STRING; | 
|  | 64 | break; | 
|  | 65 | case IMX_CHIP_REVISION_3_0: | 
|  | 66 | srev = IMX_CHIP_REVISION_3_0_STRING; | 
|  | 67 | break; | 
|  | 68 | default: | 
|  | 69 | srev = IMX_CHIP_REVISION_UNKNOWN_STRING; | 
|  | 70 | } | 
|  | 71 | printk(KERN_INFO "CPU identified as i.MX51, silicon rev %s\n", srev); | 
|  | 72 | } | 
|  | 73 | EXPORT_SYMBOL(mx51_display_revision); | 
|  | 74 |  | 
| Amit Kucheria | 33d7c5c | 2010-09-01 22:49:13 +0300 | [diff] [blame] | 75 | #ifdef CONFIG_NEON | 
|  | 76 |  | 
|  | 77 | /* | 
|  | 78 | * All versions of the silicon before Rev. 3 have broken NEON implementations. | 
|  | 79 | * Dependent on link order - so the assumption is that vfp_init is called | 
|  | 80 | * before us. | 
|  | 81 | */ | 
|  | 82 | static int __init mx51_neon_fixup(void) | 
|  | 83 | { | 
| Sascha Hauer | 92fcdc9 | 2010-11-04 23:08:17 +0100 | [diff] [blame] | 84 | if (!cpu_is_mx51()) | 
|  | 85 | return 0; | 
|  | 86 |  | 
| Dinh Nguyen | 9ab4650 | 2010-11-15 11:30:01 -0600 | [diff] [blame] | 87 | if (mx51_revision() < IMX_CHIP_REVISION_3_0 && (elf_hwcap & HWCAP_NEON)) { | 
| Amit Kucheria | 33d7c5c | 2010-09-01 22:49:13 +0300 | [diff] [blame] | 88 | elf_hwcap &= ~HWCAP_NEON; | 
|  | 89 | pr_info("Turning off NEON support, detected broken NEON implementation\n"); | 
|  | 90 | } | 
|  | 91 | return 0; | 
|  | 92 | } | 
|  | 93 |  | 
|  | 94 | late_initcall(mx51_neon_fixup); | 
|  | 95 | #endif | 
|  | 96 |  | 
| Dinh Nguyen | 9ab4650 | 2010-11-15 11:30:01 -0600 | [diff] [blame] | 97 | static int get_mx53_srev(void) | 
|  | 98 | { | 
|  | 99 | void __iomem *iim_base = MX51_IO_ADDRESS(MX53_IIM_BASE_ADDR); | 
|  | 100 | u32 rev = readl(iim_base + IIM_SREV) & 0xff; | 
|  | 101 |  | 
| Richard Zhao | 503e163 | 2011-02-18 20:26:30 +0800 | [diff] [blame] | 102 | switch (rev) { | 
|  | 103 | case 0x0: | 
| Dinh Nguyen | 9ab4650 | 2010-11-15 11:30:01 -0600 | [diff] [blame] | 104 | return IMX_CHIP_REVISION_1_0; | 
| Richard Zhao | 503e163 | 2011-02-18 20:26:30 +0800 | [diff] [blame] | 105 | case 0x2: | 
| Dinh Nguyen | 9ab4650 | 2010-11-15 11:30:01 -0600 | [diff] [blame] | 106 | return IMX_CHIP_REVISION_2_0; | 
| Richard Zhao | 503e163 | 2011-02-18 20:26:30 +0800 | [diff] [blame] | 107 | case 0x3: | 
|  | 108 | return IMX_CHIP_REVISION_2_1; | 
|  | 109 | default: | 
|  | 110 | return IMX_CHIP_REVISION_UNKNOWN; | 
|  | 111 | } | 
| Dinh Nguyen | 9ab4650 | 2010-11-15 11:30:01 -0600 | [diff] [blame] | 112 | } | 
|  | 113 |  | 
| Dinh Nguyen | b66ff7a | 2010-11-15 11:30:00 -0600 | [diff] [blame] | 114 | /* | 
|  | 115 | * Returns: | 
|  | 116 | *	the silicon revision of the cpu | 
|  | 117 | *	-EINVAL - not a mx53 | 
|  | 118 | */ | 
|  | 119 | int mx53_revision(void) | 
|  | 120 | { | 
|  | 121 | if (!cpu_is_mx53()) | 
|  | 122 | return -EINVAL; | 
|  | 123 |  | 
|  | 124 | if (cpu_silicon_rev == -1) | 
| Dinh Nguyen | 9ab4650 | 2010-11-15 11:30:01 -0600 | [diff] [blame] | 125 | cpu_silicon_rev = get_mx53_srev(); | 
| Dinh Nguyen | b66ff7a | 2010-11-15 11:30:00 -0600 | [diff] [blame] | 126 |  | 
|  | 127 | return cpu_silicon_rev; | 
|  | 128 | } | 
|  | 129 | EXPORT_SYMBOL(mx53_revision); | 
|  | 130 |  | 
| Dinh Nguyen | 16f246e | 2011-03-21 16:30:35 -0500 | [diff] [blame] | 131 | static int get_mx50_srev(void) | 
|  | 132 | { | 
|  | 133 | void __iomem *anatop = ioremap(MX50_ANATOP_BASE_ADDR, SZ_8K); | 
|  | 134 | u32 rev; | 
|  | 135 |  | 
|  | 136 | if (!anatop) { | 
|  | 137 | cpu_silicon_rev = -EINVAL; | 
|  | 138 | return 0; | 
|  | 139 | } | 
|  | 140 |  | 
|  | 141 | rev = readl(anatop + MX50_HW_ADADIG_DIGPROG); | 
|  | 142 | rev &= 0xff; | 
|  | 143 |  | 
|  | 144 | iounmap(anatop); | 
|  | 145 | if (rev == 0x0) | 
|  | 146 | return IMX_CHIP_REVISION_1_0; | 
|  | 147 | else if (rev == 0x1) | 
|  | 148 | return IMX_CHIP_REVISION_1_1; | 
|  | 149 | return 0; | 
|  | 150 | } | 
|  | 151 |  | 
|  | 152 | /* | 
|  | 153 | * Returns: | 
|  | 154 | *	the silicon revision of the cpu | 
|  | 155 | *	-EINVAL - not a mx50 | 
|  | 156 | */ | 
|  | 157 | int mx50_revision(void) | 
|  | 158 | { | 
|  | 159 | if (!cpu_is_mx50()) | 
|  | 160 | return -EINVAL; | 
|  | 161 |  | 
|  | 162 | if (cpu_silicon_rev == -1) | 
|  | 163 | cpu_silicon_rev = get_mx50_srev(); | 
|  | 164 |  | 
|  | 165 | return cpu_silicon_rev; | 
|  | 166 | } | 
|  | 167 | EXPORT_SYMBOL(mx50_revision); | 
|  | 168 |  | 
| Fabio Estevam | 2d95378 | 2011-03-25 12:52:47 -0300 | [diff] [blame] | 169 | void mx53_display_revision(void) | 
|  | 170 | { | 
|  | 171 | int rev; | 
|  | 172 | char *srev; | 
|  | 173 | rev = mx53_revision(); | 
|  | 174 |  | 
|  | 175 | switch (rev) { | 
|  | 176 | case IMX_CHIP_REVISION_1_0: | 
|  | 177 | srev = IMX_CHIP_REVISION_1_0_STRING; | 
|  | 178 | break; | 
|  | 179 | case IMX_CHIP_REVISION_2_0: | 
|  | 180 | srev = IMX_CHIP_REVISION_2_0_STRING; | 
|  | 181 | break; | 
|  | 182 | case IMX_CHIP_REVISION_2_1: | 
|  | 183 | srev = IMX_CHIP_REVISION_2_1_STRING; | 
|  | 184 | break; | 
|  | 185 | default: | 
|  | 186 | srev = IMX_CHIP_REVISION_UNKNOWN_STRING; | 
|  | 187 | } | 
|  | 188 | printk(KERN_INFO "CPU identified as i.MX53, silicon rev %s\n", srev); | 
|  | 189 | } | 
|  | 190 | EXPORT_SYMBOL(mx53_display_revision); | 
|  | 191 |  | 
| Amit Kucheria | a329b48 | 2010-02-04 12:21:53 -0800 | [diff] [blame] | 192 | static int __init post_cpu_init(void) | 
|  | 193 | { | 
|  | 194 | unsigned int reg; | 
|  | 195 | void __iomem *base; | 
|  | 196 |  | 
| Dinh Nguyen | c0abefd | 2010-11-15 11:29:59 -0600 | [diff] [blame] | 197 | if (cpu_is_mx51() || cpu_is_mx53()) { | 
|  | 198 | if (cpu_is_mx51()) | 
|  | 199 | base = MX51_IO_ADDRESS(MX51_AIPS1_BASE_ADDR); | 
|  | 200 | else | 
|  | 201 | base = MX53_IO_ADDRESS(MX53_AIPS1_BASE_ADDR); | 
| Amit Kucheria | a329b48 | 2010-02-04 12:21:53 -0800 | [diff] [blame] | 202 |  | 
| Dinh Nguyen | c0abefd | 2010-11-15 11:29:59 -0600 | [diff] [blame] | 203 | __raw_writel(0x0, base + 0x40); | 
|  | 204 | __raw_writel(0x0, base + 0x44); | 
|  | 205 | __raw_writel(0x0, base + 0x48); | 
|  | 206 | __raw_writel(0x0, base + 0x4C); | 
|  | 207 | reg = __raw_readl(base + 0x50) & 0x00FFFFFF; | 
|  | 208 | __raw_writel(reg, base + 0x50); | 
| Amit Kucheria | a329b48 | 2010-02-04 12:21:53 -0800 | [diff] [blame] | 209 |  | 
| Dinh Nguyen | c0abefd | 2010-11-15 11:29:59 -0600 | [diff] [blame] | 210 | if (cpu_is_mx51()) | 
|  | 211 | base = MX51_IO_ADDRESS(MX51_AIPS2_BASE_ADDR); | 
|  | 212 | else | 
|  | 213 | base = MX53_IO_ADDRESS(MX53_AIPS2_BASE_ADDR); | 
|  | 214 |  | 
|  | 215 | __raw_writel(0x0, base + 0x40); | 
|  | 216 | __raw_writel(0x0, base + 0x44); | 
|  | 217 | __raw_writel(0x0, base + 0x48); | 
|  | 218 | __raw_writel(0x0, base + 0x4C); | 
|  | 219 | reg = __raw_readl(base + 0x50) & 0x00FFFFFF; | 
|  | 220 | __raw_writel(reg, base + 0x50); | 
|  | 221 | } | 
| Amit Kucheria | a329b48 | 2010-02-04 12:21:53 -0800 | [diff] [blame] | 222 |  | 
|  | 223 | return 0; | 
|  | 224 | } | 
|  | 225 |  | 
|  | 226 | postcore_initcall(post_cpu_init); |