1/*
2 * Copyright (C) 2012 ARM Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15 */
16#ifndef __ASM_CACHETYPE_H
17#define __ASM_CACHETYPE_H
18
19#include <asm/cputype.h>
20
21#define CTR_L1IP_SHIFT		14
22#define CTR_L1IP_MASK		3
23#define CTR_CWG_SHIFT		24
24#define CTR_CWG_MASK		15
25
26#define ICACHE_POLICY_RESERVED	0
27#define ICACHE_POLICY_AIVIVT	1
28#define ICACHE_POLICY_VIPT	2
29#define ICACHE_POLICY_PIPT	3
30
31#ifndef __ASSEMBLY__
32
33#include <linux/bitops.h>
34
35#define CTR_L1IP(ctr)	(((ctr) >> CTR_L1IP_SHIFT) & CTR_L1IP_MASK)
36
37#define ICACHEF_ALIASING	BIT(0)
38#define ICACHEF_AIVIVT		BIT(1)
39
40extern unsigned long __icache_flags;
41
42/*
43 * NumSets, bits[27:13] - (Number of sets in cache) - 1
44 * Associativity, bits[12:3] - (Associativity of cache) - 1
45 * LineSize, bits[2:0] - (Log2(Number of words in cache line)) - 2
46 */
47#define CCSIDR_EL1_WRITE_THROUGH	BIT(31)
48#define CCSIDR_EL1_WRITE_BACK		BIT(30)
49#define CCSIDR_EL1_READ_ALLOCATE	BIT(29)
50#define CCSIDR_EL1_WRITE_ALLOCATE	BIT(28)
51#define CCSIDR_EL1_LINESIZE_MASK	0x7
52#define CCSIDR_EL1_LINESIZE(x)		((x) & CCSIDR_EL1_LINESIZE_MASK)
53#define CCSIDR_EL1_ASSOCIATIVITY_SHIFT	3
54#define CCSIDR_EL1_ASSOCIATIVITY_MASK	0x3ff
55#define CCSIDR_EL1_ASSOCIATIVITY(x)	\
56	(((x) >> CCSIDR_EL1_ASSOCIATIVITY_SHIFT) & CCSIDR_EL1_ASSOCIATIVITY_MASK)
57#define CCSIDR_EL1_NUMSETS_SHIFT	13
58#define CCSIDR_EL1_NUMSETS_MASK		0x7fff
59#define CCSIDR_EL1_NUMSETS(x) \
60	(((x) >> CCSIDR_EL1_NUMSETS_SHIFT) & CCSIDR_EL1_NUMSETS_MASK)
61
62#define CACHE_LINESIZE(x)	(16 << CCSIDR_EL1_LINESIZE(x))
63#define CACHE_NUMSETS(x)	(CCSIDR_EL1_NUMSETS(x) + 1)
64#define CACHE_ASSOCIATIVITY(x)	(CCSIDR_EL1_ASSOCIATIVITY(x) + 1)
65
66extern u64 __attribute_const__ cache_get_ccsidr(u64 csselr);
67
68/* Helpers for Level 1 Instruction cache csselr = 1L */
69static inline int icache_get_linesize(void)
70{
71	return CACHE_LINESIZE(cache_get_ccsidr(1L));
72}
73
74static inline int icache_get_numsets(void)
75{
76	return CACHE_NUMSETS(cache_get_ccsidr(1L));
77}
78
79/*
80 * Whilst the D-side always behaves as PIPT on AArch64, aliasing is
81 * permitted in the I-cache.
82 */
83static inline int icache_is_aliasing(void)
84{
85	return test_bit(ICACHEF_ALIASING, &__icache_flags);
86}
87
88static inline int icache_is_aivivt(void)
89{
90	return test_bit(ICACHEF_AIVIVT, &__icache_flags);
91}
92
93static inline u32 cache_type_cwg(void)
94{
95	return (read_cpuid_cachetype() >> CTR_CWG_SHIFT) & CTR_CWG_MASK;
96}
97
98#endif	/* __ASSEMBLY__ */
99
100#endif	/* __ASM_CACHETYPE_H */
101