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