0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/init.h>
0009 #include <linux/io.h>
0010
0011 #include <asm/smp_plat.h>
0012 #include <asm/smp_scu.h>
0013 #include <asm/cacheflush.h>
0014 #include <asm/cputype.h>
0015
0016 #define SCU_CTRL 0x00
0017 #define SCU_ENABLE (1 << 0)
0018 #define SCU_STANDBY_ENABLE (1 << 5)
0019 #define SCU_CONFIG 0x04
0020 #define SCU_CPU_STATUS 0x08
0021 #define SCU_CPU_STATUS_MASK GENMASK(1, 0)
0022 #define SCU_INVALIDATE 0x0c
0023 #define SCU_FPGA_REVISION 0x10
0024
0025 #ifdef CONFIG_SMP
0026
0027
0028
0029 unsigned int __init scu_get_core_count(void __iomem *scu_base)
0030 {
0031 unsigned int ncores = readl_relaxed(scu_base + SCU_CONFIG);
0032 return (ncores & 0x03) + 1;
0033 }
0034
0035
0036
0037
0038 void scu_enable(void __iomem *scu_base)
0039 {
0040 u32 scu_ctrl;
0041
0042 #ifdef CONFIG_ARM_ERRATA_764369
0043
0044 if ((read_cpuid_id() & 0xff0ffff0) == 0x410fc090) {
0045 scu_ctrl = readl_relaxed(scu_base + 0x30);
0046 if (!(scu_ctrl & 1))
0047 writel_relaxed(scu_ctrl | 0x1, scu_base + 0x30);
0048 }
0049 #endif
0050
0051 scu_ctrl = readl_relaxed(scu_base + SCU_CTRL);
0052
0053 if (scu_ctrl & SCU_ENABLE)
0054 return;
0055
0056 scu_ctrl |= SCU_ENABLE;
0057
0058
0059 if ((read_cpuid_id() & 0xff0ffff0) == 0x410fc090 &&
0060 (read_cpuid_id() & 0x00f0000f) >= 0x00200000)
0061 scu_ctrl |= SCU_STANDBY_ENABLE;
0062
0063 writel_relaxed(scu_ctrl, scu_base + SCU_CTRL);
0064
0065
0066
0067
0068
0069 flush_cache_all();
0070 }
0071 #endif
0072
0073 static int scu_set_power_mode_internal(void __iomem *scu_base,
0074 unsigned int logical_cpu,
0075 unsigned int mode)
0076 {
0077 unsigned int val;
0078 int cpu = MPIDR_AFFINITY_LEVEL(cpu_logical_map(logical_cpu), 0);
0079
0080 if (mode > 3 || mode == 1 || cpu > 3)
0081 return -EINVAL;
0082
0083 val = readb_relaxed(scu_base + SCU_CPU_STATUS + cpu);
0084 val &= ~SCU_CPU_STATUS_MASK;
0085 val |= mode;
0086 writeb_relaxed(val, scu_base + SCU_CPU_STATUS + cpu);
0087
0088 return 0;
0089 }
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099 int scu_power_mode(void __iomem *scu_base, unsigned int mode)
0100 {
0101 return scu_set_power_mode_internal(scu_base, smp_processor_id(), mode);
0102 }
0103
0104
0105
0106
0107 int scu_cpu_power_enable(void __iomem *scu_base, unsigned int cpu)
0108 {
0109 return scu_set_power_mode_internal(scu_base, cpu, SCU_PM_NORMAL);
0110 }
0111
0112 int scu_get_cpu_power_mode(void __iomem *scu_base, unsigned int logical_cpu)
0113 {
0114 unsigned int val;
0115 int cpu = MPIDR_AFFINITY_LEVEL(cpu_logical_map(logical_cpu), 0);
0116
0117 if (cpu > 3)
0118 return -EINVAL;
0119
0120 val = readb_relaxed(scu_base + SCU_CPU_STATUS + cpu);
0121 val &= SCU_CPU_STATUS_MASK;
0122
0123 return val;
0124 }