1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved. 4 * 5 * This file contains the CPU initialization code. 6 */ 7 8 #include <linux/types.h> 9 #include <linux/kernel.h> 10 #include <linux/init.h> 11 #include <linux/module.h> 12 #include <linux/io.h> 13 #include <linux/of.h> 14 #include <linux/of_address.h> 15 16 #include "hardware.h" 17 #include "common.h" 18 19 static int mx5_cpu_rev = -1; 20 21 #define IIM_SREV 0x24 22 23 static u32 imx5_read_srev_reg(const char *compat) 24 { 25 void __iomem *iim_base; 26 struct device_node *np; 27 u32 srev; 28 29 np = of_find_compatible_node(NULL, NULL, compat); 30 iim_base = of_iomap(np, 0); 31 of_node_put(np); 32 WARN_ON(!iim_base); 33 34 srev = readl(iim_base + IIM_SREV) & 0xff; 35 36 iounmap(iim_base); 37 38 return srev; 39 } 40 41 static int get_mx51_srev(void) 42 { 43 u32 rev = imx5_read_srev_reg("fsl,imx51-iim"); 44 45 switch (rev) { 46 case 0x0: 47 return IMX_CHIP_REVISION_2_0; 48 case 0x10: 49 return IMX_CHIP_REVISION_3_0; 50 default: 51 return IMX_CHIP_REVISION_UNKNOWN; 52 } 53 } 54 55 /* 56 * Returns: 57 * the silicon revision of the cpu 58 */ 59 int mx51_revision(void) 60 { 61 if (mx5_cpu_rev == -1) 62 mx5_cpu_rev = get_mx51_srev(); 63 64 return mx5_cpu_rev; 65 } 66 EXPORT_SYMBOL(mx51_revision); 67 68 #ifdef CONFIG_NEON 69 70 /* 71 * All versions of the silicon before Rev. 3 have broken NEON implementations. 72 * Dependent on link order - so the assumption is that vfp_init is called 73 * before us. 74 */ 75 int __init mx51_neon_fixup(void) 76 { 77 if (mx51_revision() < IMX_CHIP_REVISION_3_0 && 78 (elf_hwcap & HWCAP_NEON)) { 79 elf_hwcap &= ~HWCAP_NEON; 80 pr_info("Turning off NEON support, detected broken NEON implementation\n"); 81 } 82 return 0; 83 } 84 85 #endif 86 87 static int get_mx53_srev(void) 88 { 89 u32 rev = imx5_read_srev_reg("fsl,imx53-iim"); 90 91 switch (rev) { 92 case 0x0: 93 return IMX_CHIP_REVISION_1_0; 94 case 0x2: 95 return IMX_CHIP_REVISION_2_0; 96 case 0x3: 97 return IMX_CHIP_REVISION_2_1; 98 default: 99 return IMX_CHIP_REVISION_UNKNOWN; 100 } 101 } 102 103 /* 104 * Returns: 105 * the silicon revision of the cpu 106 */ 107 int mx53_revision(void) 108 { 109 if (mx5_cpu_rev == -1) 110 mx5_cpu_rev = get_mx53_srev(); 111 112 return mx5_cpu_rev; 113 } 114 EXPORT_SYMBOL(mx53_revision); 115 116 #define ARM_GPC 0x4 117 #define DBGEN BIT(16) 118 119 /* 120 * This enables the DBGEN bit in ARM_GPC register, which is 121 * required for accessing some performance counter features. 122 * Technically it is only required while perf is used, but to 123 * keep the source code simple we just enable it all the time 124 * when the kernel configuration allows using the feature. 125 */ 126 void __init imx5_pmu_init(void) 127 { 128 void __iomem *tigerp_base; 129 struct device_node *np; 130 u32 gpc; 131 132 if (!IS_ENABLED(CONFIG_ARM_PMU)) 133 return; 134 135 np = of_find_compatible_node(NULL, NULL, "arm,cortex-a8-pmu"); 136 if (!np) 137 return; 138 139 if (!of_property_read_bool(np, "secure-reg-access")) 140 goto exit; 141 142 of_node_put(np); 143 144 np = of_find_compatible_node(NULL, NULL, "fsl,imx51-tigerp"); 145 if (!np) 146 return; 147 148 tigerp_base = of_iomap(np, 0); 149 if (!tigerp_base) 150 goto exit; 151 152 gpc = readl_relaxed(tigerp_base + ARM_GPC); 153 gpc |= DBGEN; 154 writel_relaxed(gpc, tigerp_base + ARM_GPC); 155 iounmap(tigerp_base); 156 exit: 157 of_node_put(np); 158 159 } 160