altos/stm: New compiler doesn't correctly build flash bits yet
[fw/altos] / src / stm / ao_mpu_stm.c
1 /*
2  * Copyright © 2012 Keith Packard <keithp@keithp.com>
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 as published by
6  * the Free Software Foundation; version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16  */
17
18 #include <ao.h>
19 #include <ao_mpu.h>
20
21 static uint32_t stm_mpu_dregion;
22
23 void
24 ao_mpu_init(void)
25 {
26         uint32_t        region;
27
28         /* Check to see how many regions we have */
29         stm_mpu_dregion = (stm_mpu.typer >> STM_MPU_TYPER_DREGION) & STM_MPU_TYPER_DREGION_MASK;
30
31         /* No MPU at all */
32         if (stm_mpu_dregion == 0)
33                 return;
34
35         /* Disable MPU */
36         stm_mpu.cr = ((0 << STM_MPU_CR_PRIVDEFENA) |
37                       (0 << STM_MPU_CR_HFNMIENA) |
38                       (0 << STM_MPU_CR_ENABLE));
39
40         /* Disable all regions */
41         for (region = 0; region < stm_mpu_dregion; region++) {
42                 /* Set the base address and RNR value */
43                 stm_mpu.rbar = ((0 & (STM_MPU_RBAR_ADDR_MASK << STM_MPU_RBAR_ADDR)) |
44                                 (1 << STM_MPU_RBAR_VALID) |
45                                 (region << STM_MPU_RBAR_REGION));
46
47                 /* Disable this region */
48                 stm_mpu.rasr = 0;
49         }
50
51         region = 0;
52
53         /* Flash */
54         /* 0x00000000 - 0x1fffffff */
55         stm_mpu.rbar = (0x0000000 |
56                         (1 << STM_MPU_RBAR_VALID) |
57                         (region << STM_MPU_RBAR_REGION));
58
59         stm_mpu.rasr = ((0 << STM_MPU_RASR_XN) |
60                         (STM_MPU_RASR_AP_RO_RO << STM_MPU_RASR_AP) |
61                         (5 << STM_MPU_RASR_TEX) |
62                         (0 << STM_MPU_RASR_C) |
63                         (1 << STM_MPU_RASR_B) |
64                         (0 << STM_MPU_RASR_S) |
65                         (0 << STM_MPU_RASR_SRD) |
66                         (28 << STM_MPU_RASR_SIZE) |
67                         (1 << STM_MPU_RASR_ENABLE));
68         region++;
69
70         /* Ram */
71         /* 0x20000000 - 0x3fffffff */
72         stm_mpu.rbar = (0x20000000 |
73                         (1 << STM_MPU_RBAR_VALID) |
74                         (region << STM_MPU_RBAR_REGION));
75
76         stm_mpu.rasr = ((0 << STM_MPU_RASR_XN) |
77                         (STM_MPU_RASR_AP_RW_RW << STM_MPU_RASR_AP) |
78                         (5 << STM_MPU_RASR_TEX) |
79                         (0 << STM_MPU_RASR_C) |
80                         (1 << STM_MPU_RASR_B) |
81                         (0 << STM_MPU_RASR_S) |
82                         (0 << STM_MPU_RASR_SRD) |
83                         (28 << STM_MPU_RASR_SIZE) |
84                         (1 << STM_MPU_RASR_ENABLE));
85         region++;
86
87         /* Peripherals */
88
89         /* 0x4000000 - 0x7ffffff */
90         stm_mpu.rbar = (0x40000000 |
91                         (1 << STM_MPU_RBAR_VALID) |
92                         (region << STM_MPU_RBAR_REGION));
93
94         stm_mpu.rasr = ((1 << STM_MPU_RASR_XN) |
95                         (STM_MPU_RASR_AP_RW_RW << STM_MPU_RASR_AP) |
96                         (2 << STM_MPU_RASR_TEX) |
97                         (0 << STM_MPU_RASR_C) |
98                         (0 << STM_MPU_RASR_B) |
99                         (0 << STM_MPU_RASR_S) |
100                         (0 << STM_MPU_RASR_SRD) |
101                         (29 << STM_MPU_RASR_SIZE) |
102                         (1 << STM_MPU_RASR_ENABLE));
103         region++;
104
105         /* 0x8000000 - 0xffffffff */
106         stm_mpu.rbar = (0x80000000 |
107                         (1 << STM_MPU_RBAR_VALID) |
108                         (region << STM_MPU_RBAR_REGION));
109
110         stm_mpu.rasr = ((1 << STM_MPU_RASR_XN) |
111                         (STM_MPU_RASR_AP_RW_RW << STM_MPU_RASR_AP) |
112                         (2 << STM_MPU_RASR_TEX) |
113                         (0 << STM_MPU_RASR_C) |
114                         (0 << STM_MPU_RASR_B) |
115                         (0 << STM_MPU_RASR_S) |
116                         (0 << STM_MPU_RASR_SRD) |
117                         (30 << STM_MPU_RASR_SIZE) |
118                         (1 << STM_MPU_RASR_ENABLE));
119         region++;
120
121         /* Enable MPU */
122         stm_mpu.cr = ((0 << STM_MPU_CR_PRIVDEFENA) |
123                       (0 << STM_MPU_CR_HFNMIENA) |
124                       (1 << STM_MPU_CR_ENABLE));
125 }
126
127 /*
128  * Protect the base of the stack from CPU access
129  */
130
131 void
132 ao_mpu_stack_guard(void *base)
133 {
134         uintptr_t       addr = (uintptr_t) base;
135
136         /* Round up to cover the lowest possible 32-byte region */
137         addr = (addr + ~(STM_MPU_RBAR_ADDR_MASK << STM_MPU_RBAR_ADDR)) & (STM_MPU_RBAR_ADDR_MASK << STM_MPU_RBAR_ADDR);
138
139         stm_mpu.rbar = addr | (1 << STM_MPU_RBAR_VALID) | (7 << STM_MPU_RBAR_REGION);
140         stm_mpu.rasr = ((1 << STM_MPU_RASR_XN) |
141                         (STM_MPU_RASR_AP_NONE_NONE << STM_MPU_RASR_AP) |
142                         (5 << STM_MPU_RASR_TEX) |
143                         (0 << STM_MPU_RASR_C) |
144                         (1 << STM_MPU_RASR_B) |
145                         (0 << STM_MPU_RASR_S) |
146                         (0 << STM_MPU_RASR_SRD) |
147                         (4 << STM_MPU_RASR_SIZE) |
148                         (1 << STM_MPU_RASR_ENABLE));
149 }