cpu-imx5.c 3.0 KB

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