|  | /* | 
|  | * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved. | 
|  | * | 
|  | * The code contained herein is licensed under the GNU General Public | 
|  | * License. You may obtain a copy of the GNU General Public License | 
|  | * Version 2 or later at the following locations: | 
|  | * | 
|  | * http://www.opensource.org/licenses/gpl-license.html | 
|  | * http://www.gnu.org/copyleft/gpl.html | 
|  | * | 
|  | * This file contains the CPU initialization code. | 
|  | */ | 
|  |  | 
|  | #include <linux/types.h> | 
|  | #include <linux/kernel.h> | 
|  | #include <linux/init.h> | 
|  | #include <linux/module.h> | 
|  | #include <linux/io.h> | 
|  | #include <linux/of.h> | 
|  | #include <linux/of_address.h> | 
|  |  | 
|  | #include "hardware.h" | 
|  | #include "common.h" | 
|  |  | 
|  | static int mx5_cpu_rev = -1; | 
|  |  | 
|  | #define IIM_SREV 0x24 | 
|  |  | 
|  | static u32 imx5_read_srev_reg(const char *compat) | 
|  | { | 
|  | void __iomem *iim_base; | 
|  | struct device_node *np; | 
|  | u32 srev; | 
|  |  | 
|  | np = of_find_compatible_node(NULL, NULL, compat); | 
|  | iim_base = of_iomap(np, 0); | 
|  | WARN_ON(!iim_base); | 
|  |  | 
|  | srev = readl(iim_base + IIM_SREV) & 0xff; | 
|  |  | 
|  | iounmap(iim_base); | 
|  |  | 
|  | return srev; | 
|  | } | 
|  |  | 
|  | static int get_mx51_srev(void) | 
|  | { | 
|  | u32 rev = imx5_read_srev_reg("fsl,imx51-iim"); | 
|  |  | 
|  | switch (rev) { | 
|  | case 0x0: | 
|  | return IMX_CHIP_REVISION_2_0; | 
|  | case 0x10: | 
|  | return IMX_CHIP_REVISION_3_0; | 
|  | default: | 
|  | return IMX_CHIP_REVISION_UNKNOWN; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Returns: | 
|  | *	the silicon revision of the cpu | 
|  | */ | 
|  | int mx51_revision(void) | 
|  | { | 
|  | if (mx5_cpu_rev == -1) | 
|  | mx5_cpu_rev = get_mx51_srev(); | 
|  |  | 
|  | return mx5_cpu_rev; | 
|  | } | 
|  | EXPORT_SYMBOL(mx51_revision); | 
|  |  | 
|  | #ifdef CONFIG_NEON | 
|  |  | 
|  | /* | 
|  | * All versions of the silicon before Rev. 3 have broken NEON implementations. | 
|  | * Dependent on link order - so the assumption is that vfp_init is called | 
|  | * before us. | 
|  | */ | 
|  | int __init mx51_neon_fixup(void) | 
|  | { | 
|  | if (mx51_revision() < IMX_CHIP_REVISION_3_0 && | 
|  | (elf_hwcap & HWCAP_NEON)) { | 
|  | elf_hwcap &= ~HWCAP_NEON; | 
|  | pr_info("Turning off NEON support, detected broken NEON implementation\n"); | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | #endif | 
|  |  | 
|  | static int get_mx53_srev(void) | 
|  | { | 
|  | u32 rev = imx5_read_srev_reg("fsl,imx53-iim"); | 
|  |  | 
|  | switch (rev) { | 
|  | case 0x0: | 
|  | return IMX_CHIP_REVISION_1_0; | 
|  | case 0x2: | 
|  | return IMX_CHIP_REVISION_2_0; | 
|  | case 0x3: | 
|  | return IMX_CHIP_REVISION_2_1; | 
|  | default: | 
|  | return IMX_CHIP_REVISION_UNKNOWN; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Returns: | 
|  | *	the silicon revision of the cpu | 
|  | */ | 
|  | int mx53_revision(void) | 
|  | { | 
|  | if (mx5_cpu_rev == -1) | 
|  | mx5_cpu_rev = get_mx53_srev(); | 
|  |  | 
|  | return mx5_cpu_rev; | 
|  | } | 
|  | EXPORT_SYMBOL(mx53_revision); | 
|  |  | 
|  | #define ARM_GPC		0x4 | 
|  | #define DBGEN		BIT(16) | 
|  |  | 
|  | /* | 
|  | * This enables the DBGEN bit in ARM_GPC register, which is | 
|  | * required for accessing some performance counter features. | 
|  | * Technically it is only required while perf is used, but to | 
|  | * keep the source code simple we just enable it all the time | 
|  | * when the kernel configuration allows using the feature. | 
|  | */ | 
|  | void __init imx5_pmu_init(void) | 
|  | { | 
|  | void __iomem *tigerp_base; | 
|  | struct device_node *np; | 
|  | u32 gpc; | 
|  |  | 
|  | if (!IS_ENABLED(CONFIG_ARM_PMU)) | 
|  | return; | 
|  |  | 
|  | np = of_find_compatible_node(NULL, NULL, "arm,cortex-a8-pmu"); | 
|  | if (!np) | 
|  | return; | 
|  |  | 
|  | if (!of_property_read_bool(np, "secure-reg-access")) | 
|  | goto exit; | 
|  |  | 
|  | of_node_put(np); | 
|  |  | 
|  | np = of_find_compatible_node(NULL, NULL, "fsl,imx51-tigerp"); | 
|  | if (!np) | 
|  | return; | 
|  |  | 
|  | tigerp_base = of_iomap(np, 0); | 
|  | if (!tigerp_base) | 
|  | goto exit; | 
|  |  | 
|  | gpc = readl_relaxed(tigerp_base + ARM_GPC); | 
|  | gpc |= DBGEN; | 
|  | writel_relaxed(gpc, tigerp_base + ARM_GPC); | 
|  | iounmap(tigerp_base); | 
|  | exit: | 
|  | of_node_put(np); | 
|  |  | 
|  | } |