1/*
2** Copyright 2003-2004, Axel D��rfler, axeld@pinc-software.de. All rights reserved.
3** Distributed under the terms of the MIT License.
4*/
5#ifndef _KERNEL_ARCH_ARM_CPU_H
6#define _KERNEL_ARCH_ARM_CPU_H
7
8
9#define CPU_MAX_CACHE_LEVEL 8
10#define CACHE_LINE_SIZE 64
11	// TODO: Could be 32-bits sometimes?
12
13
14#define isb() __asm__ __volatile__("isb" : : : "memory")
15#define dsb() __asm__ __volatile__("dsb" : : : "memory")
16#define dmb() __asm__ __volatile__("dmb" : : : "memory")
17
18#define set_ac()
19#define clear_ac()
20
21
22#ifndef _ASSEMBLER
23
24#include <arch/arm/arch_thread_types.h>
25#include <kernel.h>
26
27/**! Values for arch_cpu_info.arch */
28enum {
29	ARCH_ARM_PRE_ARM7,
30	ARCH_ARM_v3,
31	ARCH_ARM_v4,
32	ARCH_ARM_v4T,
33	ARCH_ARM_v5,
34	ARCH_ARM_v5T,
35	ARCH_ARM_v5TE,
36	ARCH_ARM_v5TEJ,
37	ARCH_ARM_v6,
38	ARCH_ARM_v7
39};
40
41typedef struct arch_cpu_info {
42	/* For a detailed interpretation of these values,
43	   see "The System Control coprocessor",
44	   "Main ID register" in your ARM ARM */
45	int implementor;
46	int part_number;
47	int revision;
48	int variant;
49	int arch;
50} arch_cpu_info;
51
52#ifdef __cplusplus
53extern "C" {
54#endif
55
56
57#define DEFINE_ARM_GET_REG(name, cp, opc1, crn, crm, opc2) \
58	static inline uint32 \
59	arm_get_##name(void) \
60	{ \
61		uint32 res; \
62		asm volatile ("mrc " #cp ", " #opc1 ", %0, " #crn ", " #crm ", " #opc2 : "=r" (res)); \
63		return res; \
64	}
65
66
67#define DEFINE_ARM_SET_REG(name, cp, opc1, crn, crm, opc2) \
68	static inline void \
69	arm_set_##name(uint32 val) \
70	{ \
71		asm volatile ("mcr " #cp ", " #opc1 ", %0, " #crn ", " #crm ", " #opc2 :: "r" (val)); \
72	}
73
74
75/* CP15 c1, System Control Register */
76DEFINE_ARM_GET_REG(sctlr, p15, 0, c1, c0, 0)
77DEFINE_ARM_SET_REG(sctlr, p15, 0, c1, c0, 0)
78
79/* CP15 c2, Translation table support registers */
80DEFINE_ARM_GET_REG(ttbr0, p15, 0, c2, c0, 0)
81DEFINE_ARM_SET_REG(ttbr0, p15, 0, c2, c0, 0)
82DEFINE_ARM_GET_REG(ttbr1, p15, 0, c2, c0, 1)
83DEFINE_ARM_SET_REG(ttbr1, p15, 0, c2, c0, 1)
84DEFINE_ARM_GET_REG(ttbcr, p15, 0, c2, c0, 2)
85DEFINE_ARM_SET_REG(ttbcr, p15, 0, c2, c0, 2)
86
87/* CP15 c5 and c6, Memory system fault registers */
88DEFINE_ARM_GET_REG(dfsr, p15, 0, c5, c0, 0)
89DEFINE_ARM_GET_REG(ifsr, p15, 0, c5, c0, 1)
90DEFINE_ARM_GET_REG(dfar, p15, 0, c6, c0, 0)
91DEFINE_ARM_GET_REG(ifar, p15, 0, c6, c0, 2)
92
93/* CP15 c13, Process, context and thread ID registers */
94DEFINE_ARM_GET_REG(tpidruro, p15, 0, c13, c0, 3)
95DEFINE_ARM_SET_REG(tpidruro, p15, 0, c13, c0, 3)
96DEFINE_ARM_GET_REG(tpidrprw, p15, 0, c13, c0, 4)
97DEFINE_ARM_SET_REG(tpidrprw, p15, 0, c13, c0, 4)
98
99
100#undef DEFINE_ARM_GET_REG
101#undef DEFINE_ARM_SET_REG
102
103
104static inline addr_t
105arm_get_fp(void)
106{
107	uint32 res;
108	asm volatile ("mov %0, fp": "=r" (res));
109	return res;
110}
111
112
113void arch_cpu_invalidate_TLB_page(addr_t page);
114
115static inline void
116arch_cpu_pause(void)
117{
118	// TODO: ARM Priority pause call
119}
120
121
122static inline void
123arch_cpu_idle(void)
124{
125	uint32 Rd = 0;
126	asm volatile("mcr p15, 0, %[c7format], c7, c0, 4"
127		: : [c7format] "r" (Rd) );
128}
129
130
131#ifdef __cplusplus
132};
133#endif
134
135#endif	// !_ASSEMBLER
136
137#endif	/* _KERNEL_ARCH_ARM_CPU_H */
138