Merge tag 'phy-for-4.6-rc' of git://git.kernel.org/pub/scm/linux/kernel/git/kishon...
[deliverable/linux.git] / arch / arm / kernel / smp_scu.c
CommitLineData
a8cbcd92
RK
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
0bd82ade 14#include <asm/smp_plat.h>
a8cbcd92 15#include <asm/smp_scu.h>
af73110d 16#include <asm/cacheflush.h>
f630c1bd 17#include <asm/cputype.h>
a8cbcd92
RK
18
19#define SCU_CTRL 0x00
f8f3d4ed 20#define SCU_ENABLE (1 << 0)
c716483c 21#define SCU_STANDBY_ENABLE (1 << 5)
a8cbcd92
RK
22#define SCU_CONFIG 0x04
23#define SCU_CPU_STATUS 0x08
24#define SCU_INVALIDATE 0x0c
25#define SCU_FPGA_REVISION 0x10
26
10cdc7e5 27#ifdef CONFIG_SMP
a8cbcd92
RK
28/*
29 * Get the number of CPU cores from the SCU configuration
30 */
31unsigned int __init scu_get_core_count(void __iomem *scu_base)
32{
099a4809 33 unsigned int ncores = readl_relaxed(scu_base + SCU_CONFIG);
a8cbcd92
RK
34 return (ncores & 0x03) + 1;
35}
36
37/*
38 * Enable the SCU
39 */
26a527e6 40void scu_enable(void __iomem *scu_base)
a8cbcd92
RK
41{
42 u32 scu_ctrl;
43
f630c1bd
WD
44#ifdef CONFIG_ARM_ERRATA_764369
45 /* Cortex-A9 only */
ac52e83f 46 if ((read_cpuid_id() & 0xff0ffff0) == 0x410fc090) {
099a4809 47 scu_ctrl = readl_relaxed(scu_base + 0x30);
f630c1bd 48 if (!(scu_ctrl & 1))
099a4809 49 writel_relaxed(scu_ctrl | 0x1, scu_base + 0x30);
f630c1bd
WD
50 }
51#endif
52
099a4809 53 scu_ctrl = readl_relaxed(scu_base + SCU_CTRL);
9b229fa0 54 /* already enabled? */
f8f3d4ed 55 if (scu_ctrl & SCU_ENABLE)
9b229fa0
CM
56 return;
57
f8f3d4ed 58 scu_ctrl |= SCU_ENABLE;
c716483c
SG
59
60 /* Cortex-A9 earlier than r2p0 has no standby bit in SCU */
61 if ((read_cpuid_id() & 0xff0ffff0) == 0x410fc090 &&
62 (read_cpuid_id() & 0x00f0000f) >= 0x00200000)
63 scu_ctrl |= SCU_STANDBY_ENABLE;
64
099a4809 65 writel_relaxed(scu_ctrl, scu_base + SCU_CTRL);
af73110d
CM
66
67 /*
68 * Ensure that the data accessed by CPU0 before the SCU was
69 * initialised is visible to the other CPUs.
70 */
71 flush_cache_all();
a8cbcd92 72}
10cdc7e5 73#endif
292ec42a
RK
74
75/*
76 * Set the executing CPUs power mode as defined. This will be in
77 * preparation for it executing a WFI instruction.
78 *
79 * This function must be called with preemption disabled, and as it
80 * has the side effect of disabling coherency, caches must have been
81 * flushed. Interrupts must also have been disabled.
82 */
83int scu_power_mode(void __iomem *scu_base, unsigned int mode)
84{
85 unsigned int val;
c7d5b93e 86 int cpu = MPIDR_AFFINITY_LEVEL(cpu_logical_map(smp_processor_id()), 0);
292ec42a
RK
87
88 if (mode > 3 || mode == 1 || cpu > 3)
89 return -EINVAL;
90
099a4809 91 val = readb_relaxed(scu_base + SCU_CPU_STATUS + cpu) & ~0x03;
292ec42a 92 val |= mode;
099a4809 93 writeb_relaxed(val, scu_base + SCU_CPU_STATUS + cpu);
292ec42a
RK
94
95 return 0;
96}
This page took 0.584557 seconds and 5 git commands to generate.