smp_scu.c 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /*
  2. * linux/arch/arm/kernel/smp_scu.c
  3. *
  4. * Copyright (C) 2002 ARM Ltd.
  5. * All Rights Reserved
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 as
  9. * published by the Free Software Foundation.
  10. */
  11. #include <linux/init.h>
  12. #include <linux/io.h>
  13. #include <asm/smp_plat.h>
  14. #include <asm/smp_scu.h>
  15. #include <asm/cacheflush.h>
  16. #include <asm/cputype.h>
  17. #define SCU_CTRL 0x00
  18. #define SCU_ENABLE (1 << 0)
  19. #define SCU_STANDBY_ENABLE (1 << 5)
  20. #define SCU_CONFIG 0x04
  21. #define SCU_CPU_STATUS 0x08
  22. #define SCU_INVALIDATE 0x0c
  23. #define SCU_FPGA_REVISION 0x10
  24. #ifdef CONFIG_SMP
  25. /*
  26. * Get the number of CPU cores from the SCU configuration
  27. */
  28. unsigned int __init scu_get_core_count(void __iomem *scu_base)
  29. {
  30. unsigned int ncores = readl_relaxed(scu_base + SCU_CONFIG);
  31. return (ncores & 0x03) + 1;
  32. }
  33. /*
  34. * Enable the SCU
  35. */
  36. void scu_enable(void __iomem *scu_base)
  37. {
  38. u32 scu_ctrl;
  39. #ifdef CONFIG_ARM_ERRATA_764369
  40. /* Cortex-A9 only */
  41. if ((read_cpuid_id() & 0xff0ffff0) == 0x410fc090) {
  42. scu_ctrl = readl_relaxed(scu_base + 0x30);
  43. if (!(scu_ctrl & 1))
  44. writel_relaxed(scu_ctrl | 0x1, scu_base + 0x30);
  45. }
  46. #endif
  47. scu_ctrl = readl_relaxed(scu_base + SCU_CTRL);
  48. /* already enabled? */
  49. if (scu_ctrl & SCU_ENABLE)
  50. return;
  51. scu_ctrl |= SCU_ENABLE;
  52. /* Cortex-A9 earlier than r2p0 has no standby bit in SCU */
  53. if ((read_cpuid_id() & 0xff0ffff0) == 0x410fc090 &&
  54. (read_cpuid_id() & 0x00f0000f) >= 0x00200000)
  55. scu_ctrl |= SCU_STANDBY_ENABLE;
  56. writel_relaxed(scu_ctrl, scu_base + SCU_CTRL);
  57. /*
  58. * Ensure that the data accessed by CPU0 before the SCU was
  59. * initialised is visible to the other CPUs.
  60. */
  61. flush_cache_all();
  62. }
  63. #endif
  64. /*
  65. * Set the executing CPUs power mode as defined. This will be in
  66. * preparation for it executing a WFI instruction.
  67. *
  68. * This function must be called with preemption disabled, and as it
  69. * has the side effect of disabling coherency, caches must have been
  70. * flushed. Interrupts must also have been disabled.
  71. */
  72. int scu_power_mode(void __iomem *scu_base, unsigned int mode)
  73. {
  74. unsigned int val;
  75. int cpu = MPIDR_AFFINITY_LEVEL(cpu_logical_map(smp_processor_id()), 0);
  76. if (mode > 3 || mode == 1 || cpu > 3)
  77. return -EINVAL;
  78. val = readb_relaxed(scu_base + SCU_CPU_STATUS + cpu) & ~0x03;
  79. val |= mode;
  80. writeb_relaxed(val, scu_base + SCU_CPU_STATUS + cpu);
  81. return 0;
  82. }