1fcaf2036SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2784a90c0SSascha Hauer /*
3784a90c0SSascha Hauer * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
4784a90c0SSascha Hauer *
5784a90c0SSascha Hauer * This file contains the CPU initialization code.
6784a90c0SSascha Hauer */
7784a90c0SSascha Hauer
8784a90c0SSascha Hauer #include <linux/types.h>
9784a90c0SSascha Hauer #include <linux/kernel.h>
10784a90c0SSascha Hauer #include <linux/init.h>
11784a90c0SSascha Hauer #include <linux/module.h>
12eaed435aSLinus Torvalds #include <linux/io.h>
13ee18a715SShawn Guo #include <linux/of.h>
14ee18a715SShawn Guo #include <linux/of_address.h>
15784a90c0SSascha Hauer
1650f2de61SShawn Guo #include "hardware.h"
1722567796SFabio Estevam #include "common.h"
1850f2de61SShawn Guo
19784a90c0SSascha Hauer static int mx5_cpu_rev = -1;
20784a90c0SSascha Hauer
21784a90c0SSascha Hauer #define IIM_SREV 0x24
22784a90c0SSascha Hauer
imx5_read_srev_reg(const char * compat)23ee18a715SShawn Guo static u32 imx5_read_srev_reg(const char *compat)
24ee18a715SShawn Guo {
25ee18a715SShawn Guo void __iomem *iim_base;
26ee18a715SShawn Guo struct device_node *np;
27ee18a715SShawn Guo u32 srev;
28ee18a715SShawn Guo
29ee18a715SShawn Guo np = of_find_compatible_node(NULL, NULL, compat);
30ee18a715SShawn Guo iim_base = of_iomap(np, 0);
31*87b30c4bSDario Binacchi of_node_put(np);
32ee18a715SShawn Guo WARN_ON(!iim_base);
33ee18a715SShawn Guo
34ee18a715SShawn Guo srev = readl(iim_base + IIM_SREV) & 0xff;
35ee18a715SShawn Guo
36ee18a715SShawn Guo iounmap(iim_base);
37ee18a715SShawn Guo
38ee18a715SShawn Guo return srev;
39ee18a715SShawn Guo }
40ee18a715SShawn Guo
get_mx51_srev(void)41784a90c0SSascha Hauer static int get_mx51_srev(void)
42784a90c0SSascha Hauer {
43ee18a715SShawn Guo u32 rev = imx5_read_srev_reg("fsl,imx51-iim");
44784a90c0SSascha Hauer
45784a90c0SSascha Hauer switch (rev) {
46784a90c0SSascha Hauer case 0x0:
47784a90c0SSascha Hauer return IMX_CHIP_REVISION_2_0;
48784a90c0SSascha Hauer case 0x10:
49784a90c0SSascha Hauer return IMX_CHIP_REVISION_3_0;
50784a90c0SSascha Hauer default:
51784a90c0SSascha Hauer return IMX_CHIP_REVISION_UNKNOWN;
52784a90c0SSascha Hauer }
53784a90c0SSascha Hauer }
54784a90c0SSascha Hauer
55784a90c0SSascha Hauer /*
56784a90c0SSascha Hauer * Returns:
57784a90c0SSascha Hauer * the silicon revision of the cpu
58784a90c0SSascha Hauer */
mx51_revision(void)59784a90c0SSascha Hauer int mx51_revision(void)
60784a90c0SSascha Hauer {
61784a90c0SSascha Hauer if (mx5_cpu_rev == -1)
62784a90c0SSascha Hauer mx5_cpu_rev = get_mx51_srev();
63784a90c0SSascha Hauer
64784a90c0SSascha Hauer return mx5_cpu_rev;
65784a90c0SSascha Hauer }
66784a90c0SSascha Hauer EXPORT_SYMBOL(mx51_revision);
67784a90c0SSascha Hauer
68784a90c0SSascha Hauer #ifdef CONFIG_NEON
69784a90c0SSascha Hauer
70784a90c0SSascha Hauer /*
71784a90c0SSascha Hauer * All versions of the silicon before Rev. 3 have broken NEON implementations.
72784a90c0SSascha Hauer * Dependent on link order - so the assumption is that vfp_init is called
73784a90c0SSascha Hauer * before us.
74784a90c0SSascha Hauer */
mx51_neon_fixup(void)758321b758SShawn Guo int __init mx51_neon_fixup(void)
76784a90c0SSascha Hauer {
77eaed435aSLinus Torvalds if (mx51_revision() < IMX_CHIP_REVISION_3_0 &&
78eaed435aSLinus Torvalds (elf_hwcap & HWCAP_NEON)) {
79784a90c0SSascha Hauer elf_hwcap &= ~HWCAP_NEON;
80784a90c0SSascha Hauer pr_info("Turning off NEON support, detected broken NEON implementation\n");
81784a90c0SSascha Hauer }
82784a90c0SSascha Hauer return 0;
83784a90c0SSascha Hauer }
84784a90c0SSascha Hauer
85784a90c0SSascha Hauer #endif
86784a90c0SSascha Hauer
get_mx53_srev(void)87784a90c0SSascha Hauer static int get_mx53_srev(void)
88784a90c0SSascha Hauer {
89ee18a715SShawn Guo u32 rev = imx5_read_srev_reg("fsl,imx53-iim");
90784a90c0SSascha Hauer
91784a90c0SSascha Hauer switch (rev) {
92784a90c0SSascha Hauer case 0x0:
93784a90c0SSascha Hauer return IMX_CHIP_REVISION_1_0;
94784a90c0SSascha Hauer case 0x2:
95784a90c0SSascha Hauer return IMX_CHIP_REVISION_2_0;
96784a90c0SSascha Hauer case 0x3:
97784a90c0SSascha Hauer return IMX_CHIP_REVISION_2_1;
98784a90c0SSascha Hauer default:
99784a90c0SSascha Hauer return IMX_CHIP_REVISION_UNKNOWN;
100784a90c0SSascha Hauer }
101784a90c0SSascha Hauer }
102784a90c0SSascha Hauer
103784a90c0SSascha Hauer /*
104784a90c0SSascha Hauer * Returns:
105784a90c0SSascha Hauer * the silicon revision of the cpu
106784a90c0SSascha Hauer */
mx53_revision(void)107784a90c0SSascha Hauer int mx53_revision(void)
108784a90c0SSascha Hauer {
109784a90c0SSascha Hauer if (mx5_cpu_rev == -1)
110784a90c0SSascha Hauer mx5_cpu_rev = get_mx53_srev();
111784a90c0SSascha Hauer
112784a90c0SSascha Hauer return mx5_cpu_rev;
113784a90c0SSascha Hauer }
114784a90c0SSascha Hauer EXPORT_SYMBOL(mx53_revision);
11526b754f9SFabio Estevam
11626b754f9SFabio Estevam #define ARM_GPC 0x4
11726b754f9SFabio Estevam #define DBGEN BIT(16)
11826b754f9SFabio Estevam
11926b754f9SFabio Estevam /*
12026b754f9SFabio Estevam * This enables the DBGEN bit in ARM_GPC register, which is
12126b754f9SFabio Estevam * required for accessing some performance counter features.
12226b754f9SFabio Estevam * Technically it is only required while perf is used, but to
12326b754f9SFabio Estevam * keep the source code simple we just enable it all the time
12426b754f9SFabio Estevam * when the kernel configuration allows using the feature.
12526b754f9SFabio Estevam */
imx5_pmu_init(void)12626b754f9SFabio Estevam void __init imx5_pmu_init(void)
12726b754f9SFabio Estevam {
12826b754f9SFabio Estevam void __iomem *tigerp_base;
12926b754f9SFabio Estevam struct device_node *np;
13026b754f9SFabio Estevam u32 gpc;
13126b754f9SFabio Estevam
13226b754f9SFabio Estevam if (!IS_ENABLED(CONFIG_ARM_PMU))
13326b754f9SFabio Estevam return;
13426b754f9SFabio Estevam
13526b754f9SFabio Estevam np = of_find_compatible_node(NULL, NULL, "arm,cortex-a8-pmu");
13626b754f9SFabio Estevam if (!np)
13726b754f9SFabio Estevam return;
13826b754f9SFabio Estevam
13926b754f9SFabio Estevam if (!of_property_read_bool(np, "secure-reg-access"))
14026b754f9SFabio Estevam goto exit;
14126b754f9SFabio Estevam
14226b754f9SFabio Estevam of_node_put(np);
14326b754f9SFabio Estevam
14426b754f9SFabio Estevam np = of_find_compatible_node(NULL, NULL, "fsl,imx51-tigerp");
14526b754f9SFabio Estevam if (!np)
14626b754f9SFabio Estevam return;
14726b754f9SFabio Estevam
14826b754f9SFabio Estevam tigerp_base = of_iomap(np, 0);
14926b754f9SFabio Estevam if (!tigerp_base)
15026b754f9SFabio Estevam goto exit;
15126b754f9SFabio Estevam
15226b754f9SFabio Estevam gpc = readl_relaxed(tigerp_base + ARM_GPC);
15326b754f9SFabio Estevam gpc |= DBGEN;
15426b754f9SFabio Estevam writel_relaxed(gpc, tigerp_base + ARM_GPC);
15526b754f9SFabio Estevam iounmap(tigerp_base);
15626b754f9SFabio Estevam exit:
15726b754f9SFabio Estevam of_node_put(np);
15826b754f9SFabio Estevam
15926b754f9SFabio Estevam }
160