cpu.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /*
  2. * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
  3. *
  4. * The code contained herein is licensed under the GNU General Public
  5. * License. You may obtain a copy of the GNU General Public License
  6. * Version 2 or later at the following locations:
  7. *
  8. * http://www.opensource.org/licenses/gpl-license.html
  9. * http://www.gnu.org/copyleft/gpl.html
  10. *
  11. * This file contains the CPU initialization code.
  12. */
  13. #include <linux/types.h>
  14. #include <linux/kernel.h>
  15. #include <linux/init.h>
  16. #include <linux/module.h>
  17. #include <mach/hardware.h>
  18. #include <asm/io.h>
  19. static int cpu_silicon_rev = -1;
  20. #define IIM_SREV 0x24
  21. #define MX50_HW_ADADIG_DIGPROG 0xB0
  22. static int get_mx51_srev(void)
  23. {
  24. void __iomem *iim_base = MX51_IO_ADDRESS(MX51_IIM_BASE_ADDR);
  25. u32 rev = readl(iim_base + IIM_SREV) & 0xff;
  26. if (rev == 0x0)
  27. return IMX_CHIP_REVISION_2_0;
  28. else if (rev == 0x10)
  29. return IMX_CHIP_REVISION_3_0;
  30. return 0;
  31. }
  32. /*
  33. * Returns:
  34. * the silicon revision of the cpu
  35. * -EINVAL - not a mx51
  36. */
  37. int mx51_revision(void)
  38. {
  39. if (!cpu_is_mx51())
  40. return -EINVAL;
  41. if (cpu_silicon_rev == -1)
  42. cpu_silicon_rev = get_mx51_srev();
  43. return cpu_silicon_rev;
  44. }
  45. EXPORT_SYMBOL(mx51_revision);
  46. void mx51_display_revision(void)
  47. {
  48. int rev;
  49. char *srev;
  50. rev = mx51_revision();
  51. switch (rev) {
  52. case IMX_CHIP_REVISION_2_0:
  53. srev = IMX_CHIP_REVISION_2_0_STRING;
  54. break;
  55. case IMX_CHIP_REVISION_3_0:
  56. srev = IMX_CHIP_REVISION_3_0_STRING;
  57. break;
  58. default:
  59. srev = IMX_CHIP_REVISION_UNKNOWN_STRING;
  60. }
  61. printk(KERN_INFO "CPU identified as i.MX51, silicon rev %s\n", srev);
  62. }
  63. EXPORT_SYMBOL(mx51_display_revision);
  64. #ifdef CONFIG_NEON
  65. /*
  66. * All versions of the silicon before Rev. 3 have broken NEON implementations.
  67. * Dependent on link order - so the assumption is that vfp_init is called
  68. * before us.
  69. */
  70. static int __init mx51_neon_fixup(void)
  71. {
  72. if (!cpu_is_mx51())
  73. return 0;
  74. if (mx51_revision() < IMX_CHIP_REVISION_3_0 && (elf_hwcap & HWCAP_NEON)) {
  75. elf_hwcap &= ~HWCAP_NEON;
  76. pr_info("Turning off NEON support, detected broken NEON implementation\n");
  77. }
  78. return 0;
  79. }
  80. late_initcall(mx51_neon_fixup);
  81. #endif
  82. static int get_mx53_srev(void)
  83. {
  84. void __iomem *iim_base = MX51_IO_ADDRESS(MX53_IIM_BASE_ADDR);
  85. u32 rev = readl(iim_base + IIM_SREV) & 0xff;
  86. switch (rev) {
  87. case 0x0:
  88. return IMX_CHIP_REVISION_1_0;
  89. case 0x2:
  90. return IMX_CHIP_REVISION_2_0;
  91. case 0x3:
  92. return IMX_CHIP_REVISION_2_1;
  93. default:
  94. return IMX_CHIP_REVISION_UNKNOWN;
  95. }
  96. }
  97. /*
  98. * Returns:
  99. * the silicon revision of the cpu
  100. * -EINVAL - not a mx53
  101. */
  102. int mx53_revision(void)
  103. {
  104. if (!cpu_is_mx53())
  105. return -EINVAL;
  106. if (cpu_silicon_rev == -1)
  107. cpu_silicon_rev = get_mx53_srev();
  108. return cpu_silicon_rev;
  109. }
  110. EXPORT_SYMBOL(mx53_revision);
  111. static int get_mx50_srev(void)
  112. {
  113. void __iomem *anatop = ioremap(MX50_ANATOP_BASE_ADDR, SZ_8K);
  114. u32 rev;
  115. if (!anatop) {
  116. cpu_silicon_rev = -EINVAL;
  117. return 0;
  118. }
  119. rev = readl(anatop + MX50_HW_ADADIG_DIGPROG);
  120. rev &= 0xff;
  121. iounmap(anatop);
  122. if (rev == 0x0)
  123. return IMX_CHIP_REVISION_1_0;
  124. else if (rev == 0x1)
  125. return IMX_CHIP_REVISION_1_1;
  126. return 0;
  127. }
  128. /*
  129. * Returns:
  130. * the silicon revision of the cpu
  131. * -EINVAL - not a mx50
  132. */
  133. int mx50_revision(void)
  134. {
  135. if (!cpu_is_mx50())
  136. return -EINVAL;
  137. if (cpu_silicon_rev == -1)
  138. cpu_silicon_rev = get_mx50_srev();
  139. return cpu_silicon_rev;
  140. }
  141. EXPORT_SYMBOL(mx50_revision);
  142. void mx53_display_revision(void)
  143. {
  144. int rev;
  145. char *srev;
  146. rev = mx53_revision();
  147. switch (rev) {
  148. case IMX_CHIP_REVISION_1_0:
  149. srev = IMX_CHIP_REVISION_1_0_STRING;
  150. break;
  151. case IMX_CHIP_REVISION_2_0:
  152. srev = IMX_CHIP_REVISION_2_0_STRING;
  153. break;
  154. case IMX_CHIP_REVISION_2_1:
  155. srev = IMX_CHIP_REVISION_2_1_STRING;
  156. break;
  157. default:
  158. srev = IMX_CHIP_REVISION_UNKNOWN_STRING;
  159. }
  160. printk(KERN_INFO "CPU identified as i.MX53, silicon rev %s\n", srev);
  161. }
  162. EXPORT_SYMBOL(mx53_display_revision);
  163. static int __init post_cpu_init(void)
  164. {
  165. unsigned int reg;
  166. void __iomem *base;
  167. if (cpu_is_mx51() || cpu_is_mx53()) {
  168. if (cpu_is_mx51())
  169. base = MX51_IO_ADDRESS(MX51_AIPS1_BASE_ADDR);
  170. else
  171. base = MX53_IO_ADDRESS(MX53_AIPS1_BASE_ADDR);
  172. __raw_writel(0x0, base + 0x40);
  173. __raw_writel(0x0, base + 0x44);
  174. __raw_writel(0x0, base + 0x48);
  175. __raw_writel(0x0, base + 0x4C);
  176. reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
  177. __raw_writel(reg, base + 0x50);
  178. if (cpu_is_mx51())
  179. base = MX51_IO_ADDRESS(MX51_AIPS2_BASE_ADDR);
  180. else
  181. base = MX53_IO_ADDRESS(MX53_AIPS2_BASE_ADDR);
  182. __raw_writel(0x0, base + 0x40);
  183. __raw_writel(0x0, base + 0x44);
  184. __raw_writel(0x0, base + 0x48);
  185. __raw_writel(0x0, base + 0x4C);
  186. reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
  187. __raw_writel(reg, base + 0x50);
  188. }
  189. return 0;
  190. }
  191. postcore_initcall(post_cpu_init);