summaryrefslogtreecommitdiff
path: root/core/cortex-m/cpu.h
blob: e3137cd8643fc679f3e1e1074f47478d863314f6 (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
/* Copyright 2012 The Chromium OS Authors. All rights reserved.
 * 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 <stdint.h>
#include "compile_time_macros.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);
}

#endif /* __CROS_EC_CPU_H */