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