18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * This file contains the CPU initialization code. 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/types.h> 98c2ecf20Sopenharmony_ci#include <linux/kernel.h> 108c2ecf20Sopenharmony_ci#include <linux/init.h> 118c2ecf20Sopenharmony_ci#include <linux/module.h> 128c2ecf20Sopenharmony_ci#include <linux/io.h> 138c2ecf20Sopenharmony_ci#include <linux/of.h> 148c2ecf20Sopenharmony_ci#include <linux/of_address.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include "hardware.h" 178c2ecf20Sopenharmony_ci#include "common.h" 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_cistatic int mx5_cpu_rev = -1; 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#define IIM_SREV 0x24 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cistatic u32 imx5_read_srev_reg(const char *compat) 248c2ecf20Sopenharmony_ci{ 258c2ecf20Sopenharmony_ci void __iomem *iim_base; 268c2ecf20Sopenharmony_ci struct device_node *np; 278c2ecf20Sopenharmony_ci u32 srev; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci np = of_find_compatible_node(NULL, NULL, compat); 308c2ecf20Sopenharmony_ci iim_base = of_iomap(np, 0); 318c2ecf20Sopenharmony_ci of_node_put(np); 328c2ecf20Sopenharmony_ci WARN_ON(!iim_base); 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci srev = readl(iim_base + IIM_SREV) & 0xff; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci iounmap(iim_base); 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci return srev; 398c2ecf20Sopenharmony_ci} 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_cistatic int get_mx51_srev(void) 428c2ecf20Sopenharmony_ci{ 438c2ecf20Sopenharmony_ci u32 rev = imx5_read_srev_reg("fsl,imx51-iim"); 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci switch (rev) { 468c2ecf20Sopenharmony_ci case 0x0: 478c2ecf20Sopenharmony_ci return IMX_CHIP_REVISION_2_0; 488c2ecf20Sopenharmony_ci case 0x10: 498c2ecf20Sopenharmony_ci return IMX_CHIP_REVISION_3_0; 508c2ecf20Sopenharmony_ci default: 518c2ecf20Sopenharmony_ci return IMX_CHIP_REVISION_UNKNOWN; 528c2ecf20Sopenharmony_ci } 538c2ecf20Sopenharmony_ci} 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci/* 568c2ecf20Sopenharmony_ci * Returns: 578c2ecf20Sopenharmony_ci * the silicon revision of the cpu 588c2ecf20Sopenharmony_ci */ 598c2ecf20Sopenharmony_ciint mx51_revision(void) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci if (mx5_cpu_rev == -1) 628c2ecf20Sopenharmony_ci mx5_cpu_rev = get_mx51_srev(); 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci return mx5_cpu_rev; 658c2ecf20Sopenharmony_ci} 668c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mx51_revision); 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci#ifdef CONFIG_NEON 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci/* 718c2ecf20Sopenharmony_ci * All versions of the silicon before Rev. 3 have broken NEON implementations. 728c2ecf20Sopenharmony_ci * Dependent on link order - so the assumption is that vfp_init is called 738c2ecf20Sopenharmony_ci * before us. 748c2ecf20Sopenharmony_ci */ 758c2ecf20Sopenharmony_ciint __init mx51_neon_fixup(void) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci if (mx51_revision() < IMX_CHIP_REVISION_3_0 && 788c2ecf20Sopenharmony_ci (elf_hwcap & HWCAP_NEON)) { 798c2ecf20Sopenharmony_ci elf_hwcap &= ~HWCAP_NEON; 808c2ecf20Sopenharmony_ci pr_info("Turning off NEON support, detected broken NEON implementation\n"); 818c2ecf20Sopenharmony_ci } 828c2ecf20Sopenharmony_ci return 0; 838c2ecf20Sopenharmony_ci} 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci#endif 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_cistatic int get_mx53_srev(void) 888c2ecf20Sopenharmony_ci{ 898c2ecf20Sopenharmony_ci u32 rev = imx5_read_srev_reg("fsl,imx53-iim"); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci switch (rev) { 928c2ecf20Sopenharmony_ci case 0x0: 938c2ecf20Sopenharmony_ci return IMX_CHIP_REVISION_1_0; 948c2ecf20Sopenharmony_ci case 0x2: 958c2ecf20Sopenharmony_ci return IMX_CHIP_REVISION_2_0; 968c2ecf20Sopenharmony_ci case 0x3: 978c2ecf20Sopenharmony_ci return IMX_CHIP_REVISION_2_1; 988c2ecf20Sopenharmony_ci default: 998c2ecf20Sopenharmony_ci return IMX_CHIP_REVISION_UNKNOWN; 1008c2ecf20Sopenharmony_ci } 1018c2ecf20Sopenharmony_ci} 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci/* 1048c2ecf20Sopenharmony_ci * Returns: 1058c2ecf20Sopenharmony_ci * the silicon revision of the cpu 1068c2ecf20Sopenharmony_ci */ 1078c2ecf20Sopenharmony_ciint mx53_revision(void) 1088c2ecf20Sopenharmony_ci{ 1098c2ecf20Sopenharmony_ci if (mx5_cpu_rev == -1) 1108c2ecf20Sopenharmony_ci mx5_cpu_rev = get_mx53_srev(); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci return mx5_cpu_rev; 1138c2ecf20Sopenharmony_ci} 1148c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mx53_revision); 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci#define ARM_GPC 0x4 1178c2ecf20Sopenharmony_ci#define DBGEN BIT(16) 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci/* 1208c2ecf20Sopenharmony_ci * This enables the DBGEN bit in ARM_GPC register, which is 1218c2ecf20Sopenharmony_ci * required for accessing some performance counter features. 1228c2ecf20Sopenharmony_ci * Technically it is only required while perf is used, but to 1238c2ecf20Sopenharmony_ci * keep the source code simple we just enable it all the time 1248c2ecf20Sopenharmony_ci * when the kernel configuration allows using the feature. 1258c2ecf20Sopenharmony_ci */ 1268c2ecf20Sopenharmony_civoid __init imx5_pmu_init(void) 1278c2ecf20Sopenharmony_ci{ 1288c2ecf20Sopenharmony_ci void __iomem *tigerp_base; 1298c2ecf20Sopenharmony_ci struct device_node *np; 1308c2ecf20Sopenharmony_ci u32 gpc; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci if (!IS_ENABLED(CONFIG_ARM_PMU)) 1338c2ecf20Sopenharmony_ci return; 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci np = of_find_compatible_node(NULL, NULL, "arm,cortex-a8-pmu"); 1368c2ecf20Sopenharmony_ci if (!np) 1378c2ecf20Sopenharmony_ci return; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci if (!of_property_read_bool(np, "secure-reg-access")) 1408c2ecf20Sopenharmony_ci goto exit; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci of_node_put(np); 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci np = of_find_compatible_node(NULL, NULL, "fsl,imx51-tigerp"); 1458c2ecf20Sopenharmony_ci if (!np) 1468c2ecf20Sopenharmony_ci return; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci tigerp_base = of_iomap(np, 0); 1498c2ecf20Sopenharmony_ci if (!tigerp_base) 1508c2ecf20Sopenharmony_ci goto exit; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci gpc = readl_relaxed(tigerp_base + ARM_GPC); 1538c2ecf20Sopenharmony_ci gpc |= DBGEN; 1548c2ecf20Sopenharmony_ci writel_relaxed(gpc, tigerp_base + ARM_GPC); 1558c2ecf20Sopenharmony_ci iounmap(tigerp_base); 1568c2ecf20Sopenharmony_ciexit: 1578c2ecf20Sopenharmony_ci of_node_put(np); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci} 160