summaryrefslogtreecommitdiff
path: root/core/cortex-m/cpu.h
blob: 4a36d63ddaf4a21b44fc6796fd01cab4d4cdd68c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/* Copyright 2012 The ChromiumOS Authors
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 * Registers map and definitions for Cortex-MLM4x processor
 */

#ifndef __CROS_EC_CPU_H
#define __CROS_EC_CPU_H

#include "compile_time_macros.h"
#include "debug.h"

#include <stdint.h>

/* Macro to access 32-bit registers */
#define CPUREG(addr) (*(volatile uint32_t *)(addr))

#define CPU_NVIC_ST_CTRL CPUREG(0xE000E010)
#define ST_ENABLE BIT(0)
#define ST_TICKINT BIT(1)
#define ST_CLKSOURCE BIT(2)
#define ST_COUNTFLAG BIT(16)

/* Nested Vectored Interrupt Controller */
#define CPU_NVIC_EN(x) CPUREG(0xe000e100 + 4 * (x))
#define CPU_NVIC_DIS(x) CPUREG(0xe000e180 + 4 * (x))
#define CPU_NVIC_UNPEND(x) CPUREG(0xe000e280 + 4 * (x))
#define CPU_NVIC_PRI(x) CPUREG(0xe000e400 + 4 * (x))
/* SCB AIRCR : Application interrupt and reset control register */
#define CPU_NVIC_APINT CPUREG(0xe000ed0c)
#define CPU_NVIC_APINT_SYSRST BIT(2) /* System reset request */
#define CPU_NVIC_APINT_PRIOGRP (BIT(8) | BIT(9) | BIT(10))
#define CPU_NVIC_APINT_ENDIAN BIT(15) /* Endianness */
#define CPU_NVIC_APINT_KEY_RD (0xFA05U << 16)
#define CPU_NVIC_APINT_KEY_WR (0x05FAU << 16)
/* NVIC STIR : Software Trigger Interrupt Register */
#define CPU_NVIC_SWTRIG CPUREG(0xe000ef00)
/* SCB SCR : System Control Register */
#define CPU_SCB_SYSCTRL CPUREG(0xe000ed10)

#define CPU_NVIC_CCR CPUREG(0xe000ed14)
#define CPU_NVIC_SHCSR CPUREG(0xe000ed24)
#define CPU_NVIC_CFSR CPUREG(0xe000ed28)
#define CPU_NVIC_HFSR CPUREG(0xe000ed2c)
#define CPU_NVIC_DFSR CPUREG(0xe000ed30)
#define CPU_NVIC_MFAR CPUREG(0xe000ed34)
#define CPU_NVIC_BFAR CPUREG(0xe000ed38)

enum {
	CPU_NVIC_CFSR_BFARVALID = BIT(15),
	CPU_NVIC_CFSR_MFARVALID = BIT(7),

	CPU_NVIC_CCR_ICACHE = BIT(17),
	CPU_NVIC_CCR_DCACHE = BIT(16),
	CPU_NVIC_CCR_DIV_0_TRAP = BIT(4),
	CPU_NVIC_CCR_UNALIGN_TRAP = BIT(3),

	CPU_NVIC_HFSR_DEBUGEVT = 1UL << 31,
	CPU_NVIC_HFSR_FORCED = BIT(30),
	CPU_NVIC_HFSR_VECTTBL = BIT(1),

	CPU_NVIC_SHCSR_MEMFAULTENA = BIT(16),
	CPU_NVIC_SHCSR_BUSFAULTENA = BIT(17),
	CPU_NVIC_SHCSR_USGFAULTENA = BIT(18),
};

/* System Control Block: cache registers */
#define CPU_SCB_CCSIDR CPUREG(0xe000ed80)
#define CPU_SCB_CCSELR CPUREG(0xe000ed84)
#define CPU_SCB_ICIALLU CPUREG(0xe000ef50)
#define CPU_SCB_DCISW CPUREG(0xe000ef60)
#define CPU_SCB_DCCISW CPUREG(0xe000ef74)

/* Floating Point Context Address Register */
#define CPU_FPU_FPCAR CPUREG(0xe000ef38)

/*
 * As defined by Armv7-M Reference Manual B1.5.7 "Context state stacking on
 * exception entry with the FP extension" the structure of the FPU state is:
 * s0, s1, ..., s14, s15, fpscr.
 */
#define FPU_IDX_REG_FPSCR 16
#define FPU_FPSCR_IOC BIT(0) /* Invalid operation */
#define FPU_FPSCR_DZC BIT(1) /* Division by zero */
#define FPU_FPSCR_OFC BIT(2) /* Overflow */
#define FPU_FPSCR_UFC BIT(3) /* Underflow */
#define FPU_FPSCR_IXC BIT(4) /* Inexact */
#define FPU_FPSCR_IDC BIT(7) /* Input denormal */
#define FPU_FPSCR_EXC_FLAGS                                              \
	(FPU_FPSCR_IOC | FPU_FPSCR_DZC | FPU_FPSCR_OFC | FPU_FPSCR_UFC | \
	 FPU_FPSCR_IXC | FPU_FPSCR_IDC)

/* Bitfield values for EXC_RETURN. */
#define EXC_RETURN_ES_MASK BIT(0)
#define EXC_RETURN_ES_NON_SECURE 0
#define EXC_RETURN_ES_SECURE BIT(0)
#define EXC_RETURN_SPSEL_MASK BIT(2)
#define EXC_RETURN_SPSEL_MSP 0
#define EXC_RETURN_SPSEL_PSP BIT(2)
#define EXC_RETURN_MODE_MASK BIT(3)
#define EXC_RETURN_MODE_HANDLER 0
#define EXC_RETURN_MODE_THREAD BIT(3)
#define EXC_RETURN_FTYPE_MASK BIT(4)
#define EXC_RETURN_FTYPE_ON 0
#define EXC_RETURN_FTYPE_OFF BIT(4)
#define EXC_RETURN_DCRS_MASK BIT(5)
#define EXC_RETURN_DCRS_OFF 0
#define EXC_RETURN_DCRS_ON BIT(5)
#define EXC_RETURN_S_MASK BIT(6)
#define EXC_RETURN_S_NON_SECURE 0
#define EXC_RETURN_S_SECURE BIT(6)

/* Set up the cpu to detect faults */
void cpu_init(void);
/* Enable the CPU I-cache and D-cache if they are not already enabled */
void cpu_enable_caches(void);
/* Disable the CPU I-cache and D-cache */
void cpu_disable_caches(void);
/* Invalidate the D-cache */
void cpu_invalidate_dcache(void);
/* Clean and Invalidate the D-cache to the Point of Coherency */
void cpu_clean_invalidate_dcache(void);

/* Invalidate a single range of the D-cache */
void cpu_invalidate_dcache_range(uintptr_t base, unsigned int length);
/* Clean and Invalidate a single range of the D-cache */
void cpu_clean_invalidate_dcache_range(uintptr_t base, unsigned int length);

/* Set the priority of the given IRQ in the NVIC (0 is highest). */
static inline void cpu_set_interrupt_priority(uint8_t irq, uint8_t priority)
{
	const uint32_t prio_shift = irq % 4 * 8 + 5;

	if (priority > 7)
		priority = 7;

	CPU_NVIC_PRI(irq / 4) = (CPU_NVIC_PRI(irq / 4) & ~(7 << prio_shift)) |
				(priority << prio_shift);
}

static inline void cpu_enter_suspend_mode(void)
{
	/* Preserve debug sessions by not suspending when connected */
	if (!debugger_is_connected()) {
		asm("wfi");
	}
}

#endif /* __CROS_EC_CPU_H */