1#ifndef __ASM_ARM_CPUTYPE_H
2#define __ASM_ARM_CPUTYPE_H
3
4#include <linux/stringify.h>
5#include <linux/kernel.h>
6
7#define CPUID_ID	0
8#define CPUID_CACHETYPE	1
9#define CPUID_TCM	2
10#define CPUID_TLBTYPE	3
11#define CPUID_MPUIR	4
12#define CPUID_MPIDR	5
13#define CPUID_REVIDR	6
14
15#ifdef CONFIG_CPU_V7M
16#define CPUID_EXT_PFR0	0x40
17#define CPUID_EXT_PFR1	0x44
18#define CPUID_EXT_DFR0	0x48
19#define CPUID_EXT_AFR0	0x4c
20#define CPUID_EXT_MMFR0	0x50
21#define CPUID_EXT_MMFR1	0x54
22#define CPUID_EXT_MMFR2	0x58
23#define CPUID_EXT_MMFR3	0x5c
24#define CPUID_EXT_ISAR0	0x60
25#define CPUID_EXT_ISAR1	0x64
26#define CPUID_EXT_ISAR2	0x68
27#define CPUID_EXT_ISAR3	0x6c
28#define CPUID_EXT_ISAR4	0x70
29#define CPUID_EXT_ISAR5	0x74
30#else
31#define CPUID_EXT_PFR0	"c1, 0"
32#define CPUID_EXT_PFR1	"c1, 1"
33#define CPUID_EXT_DFR0	"c1, 2"
34#define CPUID_EXT_AFR0	"c1, 3"
35#define CPUID_EXT_MMFR0	"c1, 4"
36#define CPUID_EXT_MMFR1	"c1, 5"
37#define CPUID_EXT_MMFR2	"c1, 6"
38#define CPUID_EXT_MMFR3	"c1, 7"
39#define CPUID_EXT_ISAR0	"c2, 0"
40#define CPUID_EXT_ISAR1	"c2, 1"
41#define CPUID_EXT_ISAR2	"c2, 2"
42#define CPUID_EXT_ISAR3	"c2, 3"
43#define CPUID_EXT_ISAR4	"c2, 4"
44#define CPUID_EXT_ISAR5	"c2, 5"
45#endif
46
47#define MPIDR_SMP_BITMASK (0x3 << 30)
48#define MPIDR_SMP_VALUE (0x2 << 30)
49
50#define MPIDR_MT_BITMASK (0x1 << 24)
51
52#define MPIDR_HWID_BITMASK 0xFFFFFF
53
54#define MPIDR_INVALID (~MPIDR_HWID_BITMASK)
55
56#define MPIDR_LEVEL_BITS 8
57#define MPIDR_LEVEL_MASK ((1 << MPIDR_LEVEL_BITS) - 1)
58
59#define MPIDR_AFFINITY_LEVEL(mpidr, level) \
60	((mpidr >> (MPIDR_LEVEL_BITS * level)) & MPIDR_LEVEL_MASK)
61
62#define ARM_CPU_IMP_ARM			0x41
63#define ARM_CPU_IMP_INTEL		0x69
64
65/* ARM implemented processors */
66#define ARM_CPU_PART_ARM1136		0x4100b360
67#define ARM_CPU_PART_ARM1156		0x4100b560
68#define ARM_CPU_PART_ARM1176		0x4100b760
69#define ARM_CPU_PART_ARM11MPCORE	0x4100b020
70#define ARM_CPU_PART_CORTEX_A8		0x4100c080
71#define ARM_CPU_PART_CORTEX_A9		0x4100c090
72#define ARM_CPU_PART_CORTEX_A5		0x4100c050
73#define ARM_CPU_PART_CORTEX_A7		0x4100c070
74#define ARM_CPU_PART_CORTEX_A12		0x4100c0d0
75#define ARM_CPU_PART_CORTEX_A17		0x4100c0e0
76#define ARM_CPU_PART_CORTEX_A15		0x4100c0f0
77#define ARM_CPU_PART_MASK		0xff00fff0
78
79#define ARM_CPU_XSCALE_ARCH_MASK	0xe000
80#define ARM_CPU_XSCALE_ARCH_V1		0x2000
81#define ARM_CPU_XSCALE_ARCH_V2		0x4000
82#define ARM_CPU_XSCALE_ARCH_V3		0x6000
83
84extern unsigned int processor_id;
85
86#ifdef CONFIG_CPU_CP15
87#define read_cpuid(reg)							\
88	({								\
89		unsigned int __val;					\
90		asm("mrc	p15, 0, %0, c0, c0, " __stringify(reg)	\
91		    : "=r" (__val)					\
92		    :							\
93		    : "cc");						\
94		__val;							\
95	})
96
97/*
98 * The memory clobber prevents gcc 4.5 from reordering the mrc before
99 * any is_smp() tests, which can cause undefined instruction aborts on
100 * ARM1136 r0 due to the missing extended CP15 registers.
101 */
102#define read_cpuid_ext(ext_reg)						\
103	({								\
104		unsigned int __val;					\
105		asm("mrc	p15, 0, %0, c0, " ext_reg		\
106		    : "=r" (__val)					\
107		    :							\
108		    : "memory");					\
109		__val;							\
110	})
111
112#elif defined(CONFIG_CPU_V7M)
113
114#include <asm/io.h>
115#include <asm/v7m.h>
116
117#define read_cpuid(reg)							\
118	({								\
119		WARN_ON_ONCE(1);					\
120		0;							\
121	})
122
123static inline unsigned int __attribute_const__ read_cpuid_ext(unsigned offset)
124{
125	return readl(BASEADDR_V7M_SCB + offset);
126}
127
128#else /* ifdef CONFIG_CPU_CP15 / elif defined (CONFIG_CPU_V7M) */
129
130/*
131 * read_cpuid and read_cpuid_ext should only ever be called on machines that
132 * have cp15 so warn on other usages.
133 */
134#define read_cpuid(reg)							\
135	({								\
136		WARN_ON_ONCE(1);					\
137		0;							\
138	})
139
140#define read_cpuid_ext(reg) read_cpuid(reg)
141
142#endif /* ifdef CONFIG_CPU_CP15 / else */
143
144#ifdef CONFIG_CPU_CP15
145/*
146 * The CPU ID never changes at run time, so we might as well tell the
147 * compiler that it's constant.  Use this function to read the CPU ID
148 * rather than directly reading processor_id or read_cpuid() directly.
149 */
150static inline unsigned int __attribute_const__ read_cpuid_id(void)
151{
152	return read_cpuid(CPUID_ID);
153}
154
155#elif defined(CONFIG_CPU_V7M)
156
157static inline unsigned int __attribute_const__ read_cpuid_id(void)
158{
159	return readl(BASEADDR_V7M_SCB + V7M_SCB_CPUID);
160}
161
162#else /* ifdef CONFIG_CPU_CP15 / elif defined(CONFIG_CPU_V7M) */
163
164static inline unsigned int __attribute_const__ read_cpuid_id(void)
165{
166	return processor_id;
167}
168
169#endif /* ifdef CONFIG_CPU_CP15 / else */
170
171static inline unsigned int __attribute_const__ read_cpuid_implementor(void)
172{
173	return (read_cpuid_id() & 0xFF000000) >> 24;
174}
175
176/*
177 * The CPU part number is meaningless without referring to the CPU
178 * implementer: implementers are free to define their own part numbers
179 * which are permitted to clash with other implementer part numbers.
180 */
181static inline unsigned int __attribute_const__ read_cpuid_part(void)
182{
183	return read_cpuid_id() & ARM_CPU_PART_MASK;
184}
185
186static inline unsigned int __attribute_const__ __deprecated read_cpuid_part_number(void)
187{
188	return read_cpuid_id() & 0xFFF0;
189}
190
191static inline unsigned int __attribute_const__ xscale_cpu_arch_version(void)
192{
193	return read_cpuid_id() & ARM_CPU_XSCALE_ARCH_MASK;
194}
195
196static inline unsigned int __attribute_const__ read_cpuid_cachetype(void)
197{
198	return read_cpuid(CPUID_CACHETYPE);
199}
200
201static inline unsigned int __attribute_const__ read_cpuid_tcmstatus(void)
202{
203	return read_cpuid(CPUID_TCM);
204}
205
206static inline unsigned int __attribute_const__ read_cpuid_mpidr(void)
207{
208	return read_cpuid(CPUID_MPIDR);
209}
210
211/*
212 * Intel's XScale3 core supports some v6 features (supersections, L2)
213 * but advertises itself as v5 as it does not support the v6 ISA.  For
214 * this reason, we need a way to explicitly test for this type of CPU.
215 */
216#ifndef CONFIG_CPU_XSC3
217#define cpu_is_xsc3()	0
218#else
219static inline int cpu_is_xsc3(void)
220{
221	unsigned int id;
222	id = read_cpuid_id() & 0xffffe000;
223	/* It covers both Intel ID and Marvell ID */
224	if ((id == 0x69056000) || (id == 0x56056000))
225		return 1;
226
227	return 0;
228}
229#endif
230
231#if !defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_CPU_XSC3)
232#define	cpu_is_xscale()	0
233#else
234#define	cpu_is_xscale()	1
235#endif
236
237/*
238 * Marvell's PJ4 and PJ4B cores are based on V7 version,
239 * but require a specical sequence for enabling coprocessors.
240 * For this reason, we need a way to distinguish them.
241 */
242#if defined(CONFIG_CPU_PJ4) || defined(CONFIG_CPU_PJ4B)
243static inline int cpu_is_pj4(void)
244{
245	unsigned int id;
246
247	id = read_cpuid_id();
248	if ((id & 0xff0fff00) == 0x560f5800)
249		return 1;
250
251	return 0;
252}
253#else
254#define cpu_is_pj4()	0
255#endif
256
257static inline int __attribute_const__ cpuid_feature_extract_field(u32 features,
258								  int field)
259{
260	int feature = (features >> field) & 15;
261
262	/* feature registers are signed values */
263	if (feature > 8)
264		feature -= 16;
265
266	return feature;
267}
268
269#define cpuid_feature_extract(reg, field) \
270	cpuid_feature_extract_field(read_cpuid_ext(reg), field)
271
272#endif
273