Remove FSF address from GPL notices
[openocd.git] / src / flash / nor / stellaris.c
1 /***************************************************************************
2 * Copyright (C) 2006 by Magnus Lundin *
3 * lundin@mlu.mine.nu *
4 * *
5 * Copyright (C) 2008 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
20 ***************************************************************************/
21
22 /***************************************************************************
23 * STELLARIS flash is tested on LM3S811, LM3S6965, LM3s3748, more.
24 ***************************************************************************/
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include "jtag/interface.h"
31 #include "imp.h"
32 #include <target/algorithm.h>
33 #include <target/armv7m.h>
34
35 #define DID0_VER(did0) ((did0 >> 28)&0x07)
36
37 /* STELLARIS control registers */
38 #define SCB_BASE 0x400FE000
39 #define DID0 0x000
40 #define DID1 0x004
41 #define DC0 0x008
42 #define DC1 0x010
43 #define DC2 0x014
44 #define DC3 0x018
45 #define DC4 0x01C
46
47 #define RIS 0x050
48 #define RCC 0x060
49 #define PLLCFG 0x064
50 #define RCC2 0x070
51 #define NVMSTAT 0x1a0
52
53 /* "legacy" flash memory protection registers (64KB max) */
54 #define FMPRE 0x130
55 #define FMPPE 0x134
56
57 /* new flash memory protection registers (for more than 64KB) */
58 #define FMPRE0 0x200 /* PRE1 = PRE0 + 4, etc */
59 #define FMPPE0 0x400 /* PPE1 = PPE0 + 4, etc */
60
61 #define USECRL 0x140
62
63 #define FLASH_CONTROL_BASE 0x400FD000
64 #define FLASH_FMA (FLASH_CONTROL_BASE | 0x000)
65 #define FLASH_FMD (FLASH_CONTROL_BASE | 0x004)
66 #define FLASH_FMC (FLASH_CONTROL_BASE | 0x008)
67 #define FLASH_CRIS (FLASH_CONTROL_BASE | 0x00C)
68 #define FLASH_CIM (FLASH_CONTROL_BASE | 0x010)
69 #define FLASH_MISC (FLASH_CONTROL_BASE | 0x014)
70 #define FLASH_FSIZE (FLASH_CONTROL_BASE | 0xFC0)
71 #define FLASH_SSIZE (FLASH_CONTROL_BASE | 0xFC4)
72
73 #define AMISC 1
74 #define PMISC 2
75
76 #define AMASK 1
77 #define PMASK 2
78
79 /* Flash Controller Command bits */
80 #define FMC_WRKEY (0xA442 << 16)
81 #define FMC_COMT (1 << 3)
82 #define FMC_MERASE (1 << 2)
83 #define FMC_ERASE (1 << 1)
84 #define FMC_WRITE (1 << 0)
85
86 /* STELLARIS constants */
87
88 /* values to write in FMA to commit write-"once" values */
89 #define FLASH_FMA_PRE(x) (2 * (x)) /* for FMPPREx */
90 #define FLASH_FMA_PPE(x) (2 * (x) + 1) /* for FMPPPEx */
91
92 static void stellaris_read_clock_info(struct flash_bank *bank);
93 static int stellaris_mass_erase(struct flash_bank *bank);
94
95 struct stellaris_flash_bank {
96 /* chip id register */
97 uint32_t did0;
98 uint32_t did1;
99 uint32_t dc0;
100 uint32_t dc1;
101 uint32_t fsize;
102 uint32_t ssize;
103
104 const char *target_name;
105 uint8_t target_class;
106
107 uint32_t sramsiz;
108 /* flash geometry */
109 uint32_t num_pages;
110 uint32_t pagesize;
111
112 /* main clock status */
113 uint32_t rcc;
114 uint32_t rcc2;
115 uint8_t mck_valid;
116 uint8_t xtal_mask;
117 uint32_t iosc_freq;
118 uint32_t mck_freq;
119 const char *iosc_desc;
120 const char *mck_desc;
121 };
122
123 /* Autogenerated by contrib/gen-stellaris-part-header.pl */
124 /* From Stellaris Firmware Development Package revision 9453 */
125 static const struct {
126 uint8_t class;
127 uint8_t partno;
128 const char *partname;
129 } StellarisParts[] = {
130 {0x00, 0x01, "LM3S101"},
131 {0x00, 0x02, "LM3S102"},
132 {0x01, 0xBF, "LM3S1110"},
133 {0x01, 0xC3, "LM3S1133"},
134 {0x01, 0xC5, "LM3S1138"},
135 {0x01, 0xC1, "LM3S1150"},
136 {0x01, 0xC4, "LM3S1162"},
137 {0x01, 0xC2, "LM3S1165"},
138 {0x01, 0xEC, "LM3S1166"},
139 {0x01, 0xC6, "LM3S1332"},
140 {0x01, 0xBC, "LM3S1435"},
141 {0x01, 0xBA, "LM3S1439"},
142 {0x01, 0xBB, "LM3S1512"},
143 {0x01, 0xC7, "LM3S1538"},
144 {0x01, 0xDB, "LM3S1601"},
145 {0x03, 0x06, "LM3S1607"},
146 {0x01, 0xDA, "LM3S1608"},
147 {0x01, 0xC0, "LM3S1620"},
148 {0x04, 0xCD, "LM3S1621"},
149 {0x03, 0x03, "LM3S1625"},
150 {0x03, 0x04, "LM3S1626"},
151 {0x03, 0x05, "LM3S1627"},
152 {0x01, 0xB3, "LM3S1635"},
153 {0x01, 0xEB, "LM3S1636"},
154 {0x01, 0xBD, "LM3S1637"},
155 {0x04, 0xB1, "LM3S1651"},
156 {0x01, 0xB9, "LM3S1751"},
157 {0x03, 0x10, "LM3S1776"},
158 {0x04, 0x16, "LM3S1811"},
159 {0x04, 0x3D, "LM3S1816"},
160 {0x01, 0xB4, "LM3S1850"},
161 {0x01, 0xDD, "LM3S1911"},
162 {0x01, 0xDC, "LM3S1918"},
163 {0x01, 0xB7, "LM3S1937"},
164 {0x01, 0xBE, "LM3S1958"},
165 {0x01, 0xB5, "LM3S1960"},
166 {0x01, 0xB8, "LM3S1968"},
167 {0x01, 0xEA, "LM3S1969"},
168 {0x04, 0xCE, "LM3S1B21"},
169 {0x06, 0xCA, "LM3S1C21"},
170 {0x06, 0xCB, "LM3S1C26"},
171 {0x06, 0x98, "LM3S1C58"},
172 {0x06, 0xB0, "LM3S1D21"},
173 {0x06, 0xCC, "LM3S1D26"},
174 {0x06, 0x1D, "LM3S1F11"},
175 {0x06, 0x1B, "LM3S1F16"},
176 {0x06, 0xAF, "LM3S1G21"},
177 {0x06, 0x95, "LM3S1G58"},
178 {0x06, 0x1E, "LM3S1H11"},
179 {0x06, 0x1C, "LM3S1H16"},
180 {0x04, 0x0F, "LM3S1J11"},
181 {0x04, 0x3C, "LM3S1J16"},
182 {0x04, 0x0E, "LM3S1N11"},
183 {0x04, 0x3B, "LM3S1N16"},
184 {0x04, 0xB2, "LM3S1P51"},
185 {0x04, 0x9E, "LM3S1R21"},
186 {0x04, 0xC9, "LM3S1R26"},
187 {0x04, 0x30, "LM3S1W16"},
188 {0x04, 0x2F, "LM3S1Z16"},
189 {0x01, 0x51, "LM3S2110"},
190 {0x01, 0x84, "LM3S2139"},
191 {0x03, 0x39, "LM3S2276"},
192 {0x01, 0xA2, "LM3S2410"},
193 {0x01, 0x59, "LM3S2412"},
194 {0x01, 0x56, "LM3S2432"},
195 {0x01, 0x5A, "LM3S2533"},
196 {0x01, 0xE1, "LM3S2601"},
197 {0x01, 0xE0, "LM3S2608"},
198 {0x03, 0x33, "LM3S2616"},
199 {0x01, 0x57, "LM3S2620"},
200 {0x01, 0x85, "LM3S2637"},
201 {0x01, 0x53, "LM3S2651"},
202 {0x03, 0x80, "LM3S2671"},
203 {0x03, 0x50, "LM3S2678"},
204 {0x01, 0xA4, "LM3S2730"},
205 {0x01, 0x52, "LM3S2739"},
206 {0x03, 0x3A, "LM3S2776"},
207 {0x04, 0x6D, "LM3S2793"},
208 {0x01, 0xE3, "LM3S2911"},
209 {0x01, 0xE2, "LM3S2918"},
210 {0x01, 0xED, "LM3S2919"},
211 {0x01, 0x54, "LM3S2939"},
212 {0x01, 0x8F, "LM3S2948"},
213 {0x01, 0x58, "LM3S2950"},
214 {0x01, 0x55, "LM3S2965"},
215 {0x04, 0x6C, "LM3S2B93"},
216 {0x06, 0x94, "LM3S2D93"},
217 {0x06, 0x93, "LM3S2U93"},
218 {0x00, 0x19, "LM3S300"},
219 {0x00, 0x11, "LM3S301"},
220 {0x00, 0x1A, "LM3S308"},
221 {0x00, 0x12, "LM3S310"},
222 {0x00, 0x13, "LM3S315"},
223 {0x00, 0x14, "LM3S316"},
224 {0x00, 0x17, "LM3S317"},
225 {0x00, 0x15, "LM3S328"},
226 {0x03, 0x08, "LM3S3634"},
227 {0x03, 0x43, "LM3S3651"},
228 {0x04, 0xC8, "LM3S3654"},
229 {0x03, 0x44, "LM3S3739"},
230 {0x03, 0x49, "LM3S3748"},
231 {0x03, 0x45, "LM3S3749"},
232 {0x04, 0x42, "LM3S3826"},
233 {0x04, 0x41, "LM3S3J26"},
234 {0x04, 0x40, "LM3S3N26"},
235 {0x04, 0x3F, "LM3S3W26"},
236 {0x04, 0x3E, "LM3S3Z26"},
237 {0x03, 0x81, "LM3S5632"},
238 {0x04, 0x0C, "LM3S5651"},
239 {0x03, 0x8A, "LM3S5652"},
240 {0x04, 0x4D, "LM3S5656"},
241 {0x03, 0x91, "LM3S5662"},
242 {0x03, 0x96, "LM3S5732"},
243 {0x03, 0x97, "LM3S5737"},
244 {0x03, 0xA0, "LM3S5739"},
245 {0x03, 0x99, "LM3S5747"},
246 {0x03, 0xA7, "LM3S5749"},
247 {0x03, 0x9A, "LM3S5752"},
248 {0x03, 0x9C, "LM3S5762"},
249 {0x04, 0x69, "LM3S5791"},
250 {0x04, 0x0B, "LM3S5951"},
251 {0x04, 0x4E, "LM3S5956"},
252 {0x04, 0x68, "LM3S5B91"},
253 {0x06, 0x2E, "LM3S5C31"},
254 {0x06, 0x2C, "LM3S5C36"},
255 {0x06, 0x5E, "LM3S5C51"},
256 {0x06, 0x5B, "LM3S5C56"},
257 {0x06, 0x5F, "LM3S5D51"},
258 {0x06, 0x5C, "LM3S5D56"},
259 {0x06, 0x87, "LM3S5D91"},
260 {0x06, 0x2D, "LM3S5G31"},
261 {0x06, 0x1F, "LM3S5G36"},
262 {0x06, 0x5D, "LM3S5G51"},
263 {0x06, 0x4F, "LM3S5G56"},
264 {0x04, 0x09, "LM3S5K31"},
265 {0x04, 0x4A, "LM3S5K36"},
266 {0x04, 0x0A, "LM3S5P31"},
267 {0x04, 0x48, "LM3S5P36"},
268 {0x04, 0xB6, "LM3S5P3B"},
269 {0x04, 0x0D, "LM3S5P51"},
270 {0x04, 0x4C, "LM3S5P56"},
271 {0x04, 0x07, "LM3S5R31"},
272 {0x04, 0x4B, "LM3S5R36"},
273 {0x04, 0x47, "LM3S5T36"},
274 {0x06, 0x7F, "LM3S5U91"},
275 {0x04, 0x46, "LM3S5Y36"},
276 {0x00, 0x2A, "LM3S600"},
277 {0x00, 0x21, "LM3S601"},
278 {0x00, 0x2B, "LM3S608"},
279 {0x00, 0x22, "LM3S610"},
280 {0x01, 0xA1, "LM3S6100"},
281 {0x00, 0x23, "LM3S611"},
282 {0x01, 0x74, "LM3S6110"},
283 {0x00, 0x24, "LM3S612"},
284 {0x00, 0x25, "LM3S613"},
285 {0x00, 0x26, "LM3S615"},
286 {0x00, 0x28, "LM3S617"},
287 {0x00, 0x29, "LM3S618"},
288 {0x00, 0x27, "LM3S628"},
289 {0x01, 0xA5, "LM3S6420"},
290 {0x01, 0x82, "LM3S6422"},
291 {0x01, 0x75, "LM3S6432"},
292 {0x01, 0x76, "LM3S6537"},
293 {0x01, 0x71, "LM3S6610"},
294 {0x01, 0xE7, "LM3S6611"},
295 {0x01, 0xE6, "LM3S6618"},
296 {0x01, 0x83, "LM3S6633"},
297 {0x01, 0x8B, "LM3S6637"},
298 {0x01, 0xA3, "LM3S6730"},
299 {0x01, 0x77, "LM3S6753"},
300 {0x01, 0xE9, "LM3S6911"},
301 {0x01, 0xE8, "LM3S6918"},
302 {0x01, 0x89, "LM3S6938"},
303 {0x01, 0x72, "LM3S6950"},
304 {0x01, 0x78, "LM3S6952"},
305 {0x01, 0x73, "LM3S6965"},
306 {0x06, 0xAA, "LM3S6C11"},
307 {0x06, 0xAC, "LM3S6C65"},
308 {0x06, 0x9F, "LM3S6G11"},
309 {0x06, 0xAB, "LM3S6G65"},
310 {0x00, 0x38, "LM3S800"},
311 {0x00, 0x31, "LM3S801"},
312 {0x00, 0x39, "LM3S808"},
313 {0x00, 0x32, "LM3S811"},
314 {0x00, 0x33, "LM3S812"},
315 {0x00, 0x34, "LM3S815"},
316 {0x00, 0x36, "LM3S817"},
317 {0x00, 0x37, "LM3S818"},
318 {0x00, 0x35, "LM3S828"},
319 {0x01, 0x64, "LM3S8530"},
320 {0x01, 0x8E, "LM3S8538"},
321 {0x01, 0x61, "LM3S8630"},
322 {0x01, 0x63, "LM3S8730"},
323 {0x01, 0x8D, "LM3S8733"},
324 {0x01, 0x86, "LM3S8738"},
325 {0x01, 0x65, "LM3S8930"},
326 {0x01, 0x8C, "LM3S8933"},
327 {0x01, 0x88, "LM3S8938"},
328 {0x01, 0xA6, "LM3S8962"},
329 {0x01, 0x62, "LM3S8970"},
330 {0x01, 0xD7, "LM3S8971"},
331 {0x06, 0xAE, "LM3S8C62"},
332 {0x06, 0xAD, "LM3S8G62"},
333 {0x04, 0xCF, "LM3S9781"},
334 {0x04, 0x67, "LM3S9790"},
335 {0x04, 0x6B, "LM3S9792"},
336 {0x04, 0x2D, "LM3S9971"},
337 {0x04, 0x20, "LM3S9997"},
338 {0x04, 0xD0, "LM3S9B81"},
339 {0x04, 0x66, "LM3S9B90"},
340 {0x04, 0x6A, "LM3S9B92"},
341 {0x04, 0x6E, "LM3S9B95"},
342 {0x04, 0x6F, "LM3S9B96"},
343 {0x04, 0x1D, "LM3S9BN2"},
344 {0x04, 0x1E, "LM3S9BN5"},
345 {0x04, 0x1F, "LM3S9BN6"},
346 {0x06, 0x70, "LM3S9C97"},
347 {0x06, 0xA9, "LM3S9D81"},
348 {0x06, 0x7E, "LM3S9D90"},
349 {0x06, 0x92, "LM3S9D92"},
350 {0x06, 0x9D, "LM3S9D96"},
351 {0x06, 0x7B, "LM3S9DN5"},
352 {0x06, 0x7C, "LM3S9DN6"},
353 {0x06, 0x60, "LM3S9G97"},
354 {0x06, 0x79, "LM3S9GN5"},
355 {0x04, 0x1B, "LM3S9L71"},
356 {0x04, 0x18, "LM3S9L97"},
357 {0x06, 0xA8, "LM3S9U81"},
358 {0x06, 0x7D, "LM3S9U90"},
359 {0x06, 0x90, "LM3S9U92"},
360 {0x06, 0x9B, "LM3S9U96"},
361 {0x05, 0x01, "LM4F120B2QR/TM4C1233C3PM"},
362 {0x05, 0x02, "LM4F120C4QR/TM4C1233D5PM"},
363 {0x05, 0x03, "LM4F120E5QR/TM4C1233E6PM"},
364 {0x05, 0x04, "LM4F120H5QR/TM4C1233H6PM"},
365 {0x05, 0x08, "LM4F121B2QR/TM4C1232C3PM"},
366 {0x05, 0x09, "LM4F121C4QR/TM4C1232D5PM"},
367 {0x05, 0x0A, "LM4F121E5QR/TM4C1232E6PM"},
368 {0x05, 0x0B, "LM4F121H5QR/TM4C1232H6PM"},
369 {0x05, 0x10, "LM4F110E5QR/TM4C1231E6PM"},
370 {0x05, 0x11, "LM4F110H5QR/TM4C1231H6PM"},
371 {0x05, 0x18, "LM4F110B2QR/TM4C1231C3PM"},
372 {0x05, 0x19, "LM4F110C4QR/TM4C1231D5PM"},
373 {0x05, 0x20, "LM4F111E5QR/TM4C1230E6PM"},
374 {0x05, 0x21, "LM4F111H5QR/TM4C1230H6PM"},
375 {0x05, 0x22, "LM4F111B2QR/TM4C1230C3PM"},
376 {0x05, 0x23, "LM4F111C4QR/TM4C1230D5PM"},
377 {0x05, 0x30, "LM4F112E5QC/TM4C1231E6PZ"},
378 {0x05, 0x31, "LM4F112H5QC/TM4C1231H6PZ"},
379 {0x05, 0x35, "LM4F112H5QD/TM4C1231H6PGE"},
380 {0x05, 0x36, "LM4F112C4QC/TM4C1231D5PZ"},
381 {0x05, 0x40, "LM4F130E5QR/TM4C1237E6PM"},
382 {0x05, 0x41, "LM4F130H5QR/TM4C1237H6PM"},
383 {0x05, 0x48, "LM4F130C4QR/TM4C1237D5PM"},
384 {0x05, 0x50, "LM4F131E5QR/TM4C1236E6PM"},
385 {0x05, 0x51, "LM4F131H5QR/TM4C1236H6PM"},
386 {0x05, 0x52, "LM4F131C4QR/TM4C1236D5PM"},
387 {0x05, 0x60, "LM4F132E5QC/TM4C1237E6PZ"},
388 {0x05, 0x61, "LM4F132H5QC/TM4C1237H6PZ"},
389 {0x05, 0x65, "LM4F132H5QD/TM4C1237H6PGE"},
390 {0x05, 0x66, "LM4F132C4QC/TM4C1237D5PZ"},
391 {0x05, 0x70, "LM4F210E5QR/TM4C123BE6PM"},
392 {0x05, 0x73, "LM4F210H5QR/TM4C123BH6PM"},
393 {0x05, 0x80, "LM4F211E5QR/TM4C123AE6PM"},
394 {0x05, 0x83, "LM4F211H5QR/TM4C123AH6PM"},
395 {0x05, 0xA0, "LM4F230E5QR/TM4C123GE6PM"},
396 {0x05, 0xA1, "LM4F230H5QR/TM4C123GH6PM"},
397 {0x05, 0xB0, "LM4F231E5QR/TM4C123FE6PM"},
398 {0x05, 0xB1, "LM4F231H5QR/TM4C123FH6PM"},
399 {0x05, 0xC0, "LM4F232E5QC/TM4C123GE6PZ"},
400 {0x05, 0xC1, "LM4F232H5QC/TM4C123GH6PZ"},
401 {0x05, 0xC3, "LM4F212E5QC/TM4C123BE6PZ"},
402 {0x05, 0xC4, "LM4F212H5QC/TM4C123BH6PZ"},
403 {0x05, 0xC5, "LM4F232H5QD/TM4C123GH6PGE"},
404 {0x05, 0xC6, "LM4F212H5QD/TM4C123BH6PGE"},
405 {0x05, 0xD0, "LM4F122C4QC/TM4C1233D5PZ"},
406 {0x05, 0xD1, "LM4F122E5QC/TM4C1233E6PZ"},
407 {0x05, 0xD2, "LM4F122H5QC/TM4C1233H6PZ"},
408 {0x05, 0xD6, "LM4F122H5QD/TM4C1233H6PGE"},
409 {0x05, 0xE1, "LM4FSXLH5BB"},
410 {0x05, 0xE3, "LM4F232H5BB/TM4C123GH6ZRB"},
411 {0x05, 0xE4, "LM4FS99H5BB"},
412 {0x05, 0xE5, "LM4FS1AH5BB"},
413 {0x05, 0xE9, "LM4F212H5BB/TM4C123BH6ZRB"},
414 {0x05, 0xEA, "LM4FS1GH5BB"},
415 {0x05, 0xF0, "TM4C123GH6ZXR"},
416 {0x0A, 0x19, "TM4C1290NCPDT"},
417 {0x0A, 0x1B, "TM4C1290NCZAD"},
418 {0x0A, 0x1C, "TM4C1292NCPDT"},
419 {0x0A, 0x1E, "TM4C1292NCZAD"},
420 {0x0A, 0x1F, "TM4C1294NCPDT"},
421 {0x0A, 0x21, "TM4C1294NCZAD"},
422 {0x0A, 0x22, "TM4C1297NCZAD"},
423 {0x0A, 0x23, "TM4C1299NCZAD"},
424 {0x0A, 0x24, "TM4C129CNCPDT"},
425 {0x0A, 0x26, "TM4C129CNCZAD"},
426 {0x0A, 0x27, "TM4C129DNCPDT"},
427 {0x0A, 0x29, "TM4C129DNCZAD"},
428 {0x0A, 0x2D, "TM4C129ENCPDT"},
429 {0x0A, 0x2F, "TM4C129ENCZAD"},
430 {0x0A, 0x30, "TM4C129LNCZAD"},
431 {0x0A, 0x32, "TM4C129XNCZAD"},
432 {0x0A, 0x34, "TM4C1294KCPDT"},
433 {0x0A, 0x35, "TM4C129EKCPDT"},
434 {0x0A, 0x36, "TM4C1299KCZAD"},
435 {0x0A, 0x37, "TM4C129XKCZAD"},
436 {0xFF, 0x00, "Unknown Part"}
437 };
438
439 static const char * const StellarisClassname[] = {
440 "Sandstorm",
441 "Fury",
442 "Unknown",
443 "DustDevil",
444 "Tempest",
445 "Blizzard/TM4C123x",
446 "Firestorm",
447 "",
448 "",
449 "",
450 "Snowflake",
451 };
452
453 /***************************************************************************
454 * openocd command interface *
455 ***************************************************************************/
456
457 /* flash_bank stellaris <base> <size> 0 0 <target#>
458 */
459 FLASH_BANK_COMMAND_HANDLER(stellaris_flash_bank_command)
460 {
461 struct stellaris_flash_bank *stellaris_info;
462
463 if (CMD_ARGC < 6)
464 return ERROR_COMMAND_SYNTAX_ERROR;
465
466 stellaris_info = calloc(sizeof(struct stellaris_flash_bank), 1);
467 bank->base = 0x0;
468 bank->driver_priv = stellaris_info;
469
470 stellaris_info->target_name = "Unknown target";
471
472 /* part wasn't probed for info yet */
473 stellaris_info->did1 = 0;
474
475 /* TODO Specify the main crystal speed in kHz using an optional
476 * argument; ditto, the speed of an external oscillator used
477 * instead of a crystal. Avoid programming flash using IOSC.
478 */
479 return ERROR_OK;
480 }
481
482 static int get_stellaris_info(struct flash_bank *bank, char *buf, int buf_size)
483 {
484 int printed;
485 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
486
487 if (stellaris_info->did1 == 0)
488 return ERROR_FLASH_BANK_NOT_PROBED;
489
490 /* Read main and master clock freqency register */
491 stellaris_read_clock_info(bank);
492
493 printed = snprintf(buf,
494 buf_size,
495 "\nTI/LMI Stellaris information: Chip is "
496 "class %i (%s) %s rev %c%i\n",
497 stellaris_info->target_class,
498 StellarisClassname[stellaris_info->target_class],
499 stellaris_info->target_name,
500 (int)('A' + ((stellaris_info->did0 >> 8) & 0xFF)),
501 (int)((stellaris_info->did0) & 0xFF));
502 buf += printed;
503 buf_size -= printed;
504
505 printed = snprintf(buf,
506 buf_size,
507 "did1: 0x%8.8" PRIx32 ", arch: 0x%4.4" PRIx32
508 ", eproc: %s, ramsize: %" PRIu32 "k, flashsize: %" PRIu32 "k\n",
509 stellaris_info->did1,
510 stellaris_info->did1,
511 "ARMv7M",
512 stellaris_info->sramsiz,
513 (uint32_t)(stellaris_info->num_pages * stellaris_info->pagesize / 1024));
514 buf += printed;
515 buf_size -= printed;
516
517 snprintf(buf,
518 buf_size,
519 "master clock: %ikHz%s, "
520 "rcc is 0x%" PRIx32 ", rcc2 is 0x%" PRIx32 ", "
521 "pagesize: %" PRIu32 ", pages: %" PRIu32,
522 (int)(stellaris_info->mck_freq / 1000),
523 stellaris_info->mck_desc,
524 stellaris_info->rcc,
525 stellaris_info->rcc2,
526 stellaris_info->pagesize,
527 stellaris_info->num_pages);
528
529 return ERROR_OK;
530 }
531
532 /***************************************************************************
533 * chip identification and status *
534 ***************************************************************************/
535
536 /* Set the flash timimg register to match current clocking */
537 static void stellaris_set_flash_timing(struct flash_bank *bank)
538 {
539 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
540 struct target *target = bank->target;
541 uint32_t usecrl = (stellaris_info->mck_freq/1000000ul-1);
542
543 /* only valid for Sandstorm and Fury class devices */
544 if (stellaris_info->target_class > 1)
545 return;
546
547 LOG_DEBUG("usecrl = %i", (int)(usecrl));
548 target_write_u32(target, SCB_BASE | USECRL, usecrl);
549 }
550
551 static const unsigned rcc_xtal[32] = {
552 [0x00] = 1000000, /* no pll */
553 [0x01] = 1843200, /* no pll */
554 [0x02] = 2000000, /* no pll */
555 [0x03] = 2457600, /* no pll */
556
557 [0x04] = 3579545,
558 [0x05] = 3686400,
559 [0x06] = 4000000, /* usb */
560 [0x07] = 4096000,
561
562 [0x08] = 4915200,
563 [0x09] = 5000000, /* usb */
564 [0x0a] = 5120000,
565 [0x0b] = 6000000, /* (reset) usb */
566
567 [0x0c] = 6144000,
568 [0x0d] = 7372800,
569 [0x0e] = 8000000, /* usb */
570 [0x0f] = 8192000,
571
572 /* parts before DustDevil use just 4 bits for xtal spec */
573
574 [0x10] = 10000000, /* usb */
575 [0x11] = 12000000, /* usb */
576 [0x12] = 12288000,
577 [0x13] = 13560000,
578
579 [0x14] = 14318180,
580 [0x15] = 16000000, /* usb */
581 [0x16] = 16384000,
582 };
583
584 /** Read clock configuration and set stellaris_info->usec_clocks. */
585 static void stellaris_read_clock_info(struct flash_bank *bank)
586 {
587 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
588 struct target *target = bank->target;
589 uint32_t rcc, rcc2, pllcfg, sysdiv, usesysdiv, bypass, oscsrc;
590 unsigned xtal;
591 unsigned long mainfreq;
592
593 target_read_u32(target, SCB_BASE | RCC, &rcc);
594 LOG_DEBUG("Stellaris RCC %" PRIx32 "", rcc);
595
596 target_read_u32(target, SCB_BASE | RCC2, &rcc2);
597 LOG_DEBUG("Stellaris RCC2 %" PRIx32 "", rcc);
598
599 target_read_u32(target, SCB_BASE | PLLCFG, &pllcfg);
600 LOG_DEBUG("Stellaris PLLCFG %" PRIx32 "", pllcfg);
601
602 stellaris_info->rcc = rcc;
603 stellaris_info->rcc2 = rcc2;
604
605 sysdiv = (rcc >> 23) & 0xF;
606 usesysdiv = (rcc >> 22) & 0x1;
607 bypass = (rcc >> 11) & 0x1;
608 oscsrc = (rcc >> 4) & 0x3;
609 xtal = (rcc >> 6) & stellaris_info->xtal_mask;
610
611 /* NOTE: post-Sandstorm parts have RCC2 which may override
612 * parts of RCC ... with more sysdiv options, option for
613 * 32768 Hz mainfreq, PLL controls. On Sandstorm it reads
614 * as zero, so the "use RCC2" flag is always clear.
615 */
616 if (rcc2 & (1 << 31)) {
617 sysdiv = (rcc2 >> 23) & 0x3F;
618 bypass = (rcc2 >> 11) & 0x1;
619 oscsrc = (rcc2 >> 4) & 0x7;
620
621 /* FIXME Tempest parts have an additional lsb for
622 * fractional sysdiv (200 MHz / 2.5 == 80 MHz)
623 */
624 }
625
626 stellaris_info->mck_desc = "";
627
628 switch (oscsrc) {
629 case 0: /* MOSC */
630 mainfreq = rcc_xtal[xtal];
631 break;
632 case 1: /* IOSC */
633 mainfreq = stellaris_info->iosc_freq;
634 stellaris_info->mck_desc = stellaris_info->iosc_desc;
635 break;
636 case 2: /* IOSC/4 */
637 mainfreq = stellaris_info->iosc_freq / 4;
638 stellaris_info->mck_desc = stellaris_info->iosc_desc;
639 break;
640 case 3: /* lowspeed */
641 /* Sandstorm doesn't have this 30K +/- 30% osc */
642 mainfreq = 30000;
643 stellaris_info->mck_desc = " (±30%)";
644 break;
645 case 8: /* hibernation osc */
646 /* not all parts support hibernation */
647 mainfreq = 32768;
648 break;
649
650 default: /* NOTREACHED */
651 mainfreq = 0;
652 break;
653 }
654
655 /* PLL is used if it's not bypassed; its output is 200 MHz
656 * even when it runs at 400 MHz (adds divide-by-two stage).
657 */
658 if (!bypass)
659 mainfreq = 200000000;
660
661 if (usesysdiv)
662 stellaris_info->mck_freq = mainfreq/(1 + sysdiv);
663 else
664 stellaris_info->mck_freq = mainfreq;
665 }
666
667 /* Read device id register, main clock frequency register and fill in driver info structure */
668 static int stellaris_read_part_info(struct flash_bank *bank)
669 {
670 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
671 struct target *target = bank->target;
672 uint32_t did0, did1, ver, fam;
673 int i;
674
675 /* Read and parse chip identification register */
676 target_read_u32(target, SCB_BASE | DID0, &did0);
677 target_read_u32(target, SCB_BASE | DID1, &did1);
678 target_read_u32(target, SCB_BASE | DC0, &stellaris_info->dc0);
679 target_read_u32(target, SCB_BASE | DC1, &stellaris_info->dc1);
680 LOG_DEBUG("did0 0x%" PRIx32 ", did1 0x%" PRIx32 ", dc0 0x%" PRIx32 ", dc1 0x%" PRIx32 "",
681 did0, did1, stellaris_info->dc0, stellaris_info->dc1);
682
683 ver = DID0_VER(did0);
684 if ((ver != 0) && (ver != 1)) {
685 LOG_WARNING("Unknown did0 version, cannot identify target");
686 return ERROR_FLASH_OPERATION_FAILED;
687 }
688
689 if (did1 == 0) {
690 LOG_WARNING("Cannot identify target as a Stellaris");
691 return ERROR_FLASH_OPERATION_FAILED;
692 }
693
694 ver = did1 >> 28;
695 fam = (did1 >> 24) & 0xF;
696 if (((ver != 0) && (ver != 1)) || (fam != 0)) {
697 LOG_WARNING("Unknown did1 version/family.");
698 return ERROR_FLASH_OPERATION_FAILED;
699 }
700
701 /* For Sandstorm, Fury, DustDevil: current data sheets say IOSC
702 * is 12 MHz, but some older parts have 15 MHz. A few data sheets
703 * even give _both_ numbers! We'll use current numbers; IOSC is
704 * always approximate.
705 *
706 * For Tempest: IOSC is calibrated, 16 MHz
707 * For Blizzard: IOSC is calibrated, 16 MHz
708 * For Firestorm: IOSC is calibrated, 16 MHz
709 */
710 stellaris_info->iosc_freq = 12000000;
711 stellaris_info->iosc_desc = " (±30%)";
712 stellaris_info->xtal_mask = 0x0f;
713
714 /* get device class */
715 if (DID0_VER(did0) > 0) {
716 stellaris_info->target_class = (did0 >> 16) & 0xFF;
717 } else {
718 /* Sandstorm class */
719 stellaris_info->target_class = 0;
720 }
721
722 switch (stellaris_info->target_class) {
723 case 0: /* Sandstorm */
724 /*
725 * Current (2009-August) parts seem to be rev C2 and use 12 MHz.
726 * Parts before rev C0 used 15 MHz; some C0 parts use 15 MHz
727 * (LM3S618), but some other C0 parts are 12 MHz (LM3S811).
728 */
729 if (((did0 >> 8) & 0xff) < 2) {
730 stellaris_info->iosc_freq = 15000000;
731 stellaris_info->iosc_desc = " (±50%)";
732 }
733 break;
734
735 case 1: /* Fury */
736 break;
737
738 case 4: /* Tempest */
739 case 5: /* Blizzard */
740 case 6: /* Firestorm */
741 case 0xa: /* Snowflake */
742 stellaris_info->iosc_freq = 16000000; /* +/- 1% */
743 stellaris_info->iosc_desc = " (±1%)";
744 /* FALL THROUGH */
745
746 case 3: /* DustDevil */
747 stellaris_info->xtal_mask = 0x1f;
748 break;
749
750 default:
751 LOG_WARNING("Unknown did0 class");
752 }
753
754 for (i = 0; StellarisParts[i].partno; i++) {
755 if ((StellarisParts[i].partno == ((did1 >> 16) & 0xFF)) &&
756 (StellarisParts[i].class == stellaris_info->target_class))
757 break;
758 }
759
760 stellaris_info->target_name = StellarisParts[i].partname;
761
762 stellaris_info->did0 = did0;
763 stellaris_info->did1 = did1;
764
765 if (stellaris_info->target_class == 5) { /* Blizzard */
766 target_read_u32(target, FLASH_FSIZE, &stellaris_info->fsize);
767 target_read_u32(target, FLASH_SSIZE, &stellaris_info->ssize);
768
769 stellaris_info->num_pages = 2 * (1 + (stellaris_info->fsize & 0xFFFF));
770 stellaris_info->sramsiz = (1 + (stellaris_info->ssize & 0xFFFF)) / 4;
771 stellaris_info->pagesize = 1024;
772 } else if (stellaris_info->target_class == 0xa) { /* Snowflake */
773 target_read_u32(target, FLASH_FSIZE, &stellaris_info->fsize);
774 target_read_u32(target, FLASH_SSIZE, &stellaris_info->ssize);
775
776 stellaris_info->pagesize = (1 << ((stellaris_info->fsize >> 16) & 7)) * 1024;
777 stellaris_info->num_pages = 2048 * (1 + (stellaris_info->fsize & 0xFFFF)) /
778 stellaris_info->pagesize;
779 stellaris_info->sramsiz = (1 + (stellaris_info->ssize & 0xFFFF)) / 4;
780 } else {
781 stellaris_info->num_pages = 2 * (1 + (stellaris_info->dc0 & 0xFFFF));
782 stellaris_info->sramsiz = (1 + ((stellaris_info->dc0 >> 16) & 0xFFFF)) / 4;
783 stellaris_info->pagesize = 1024;
784 }
785
786 /* REVISIT for at least Tempest parts, read NVMSTAT.FWB too.
787 * That exposes a 32-word Flash Write Buffer ... enabling
788 * writes of more than one word at a time.
789 */
790
791 return ERROR_OK;
792 }
793
794 /***************************************************************************
795 * flash operations *
796 ***************************************************************************/
797
798 static int stellaris_protect_check(struct flash_bank *bank)
799 {
800 struct stellaris_flash_bank *stellaris = bank->driver_priv;
801 struct target *target = bank->target;
802 uint32_t flash_sizek = stellaris->pagesize / 1024 *
803 stellaris->num_pages;
804 uint32_t fmppe_addr;
805 int status = ERROR_OK;
806 unsigned i;
807
808 if (stellaris->did1 == 0)
809 return ERROR_FLASH_BANK_NOT_PROBED;
810
811 for (i = 0; i < (unsigned) bank->num_sectors; i++)
812 bank->sectors[i].is_protected = -1;
813
814 /* Read each Flash Memory Protection Program Enable (FMPPE) register
815 * to report any pages that we can't write. Ignore the Read Enable
816 * register (FMPRE).
817 */
818
819 if (stellaris->target_class >= 0x0a || flash_sizek > 64)
820 fmppe_addr = SCB_BASE | FMPPE0;
821 else
822 fmppe_addr = SCB_BASE | FMPPE;
823
824 unsigned int page = 0, lockbitnum, lockbitcnt = flash_sizek / 2;
825 unsigned int bits_per_page = stellaris->pagesize / 2048;
826 /* Every lock bit always corresponds to a 2k region */
827 for (lockbitnum = 0; lockbitnum < lockbitcnt; lockbitnum += 32) {
828 uint32_t fmppe;
829
830 target_read_u32(target, fmppe_addr, &fmppe);
831 for (i = 0; i < 32 && lockbitnum + i < lockbitcnt; i++) {
832 bool protect = !(fmppe & (1 << i));
833 if (bits_per_page) {
834 bank->sectors[page++].is_protected = protect;
835 i += bits_per_page - 1;
836 } else { /* 1024k pages, every lockbit covers 2 pages */
837 bank->sectors[page++].is_protected = protect;
838 bank->sectors[page++].is_protected = protect;
839 }
840 }
841 fmppe_addr += 4;
842 }
843
844 return status;
845 }
846
847 static int stellaris_erase(struct flash_bank *bank, int first, int last)
848 {
849 int banknr;
850 uint32_t flash_fmc, flash_cris;
851 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
852 struct target *target = bank->target;
853
854 if (bank->target->state != TARGET_HALTED) {
855 LOG_ERROR("Target not halted");
856 return ERROR_TARGET_NOT_HALTED;
857 }
858
859 if (stellaris_info->did1 == 0)
860 return ERROR_FLASH_BANK_NOT_PROBED;
861
862 if ((first < 0) || (last < first) || (last >= (int)stellaris_info->num_pages))
863 return ERROR_FLASH_SECTOR_INVALID;
864
865 if ((first == 0) && (last == ((int)stellaris_info->num_pages-1)))
866 return stellaris_mass_erase(bank);
867
868 /* Refresh flash controller timing */
869 stellaris_read_clock_info(bank);
870 stellaris_set_flash_timing(bank);
871
872 /* Clear and disable flash programming interrupts */
873 target_write_u32(target, FLASH_CIM, 0);
874 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
875
876 /* REVISIT this clobbers state set by any halted firmware ...
877 * it might want to process those IRQs.
878 */
879
880 for (banknr = first; banknr <= last; banknr++) {
881 /* Address is first word in page */
882 target_write_u32(target, FLASH_FMA, banknr * stellaris_info->pagesize);
883 /* Write erase command */
884 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_ERASE);
885 /* Wait until erase complete */
886 do {
887 target_read_u32(target, FLASH_FMC, &flash_fmc);
888 } while (flash_fmc & FMC_ERASE);
889
890 /* Check acess violations */
891 target_read_u32(target, FLASH_CRIS, &flash_cris);
892 if (flash_cris & (AMASK)) {
893 LOG_WARNING("Error erasing flash page %i, flash_cris 0x%" PRIx32 "",
894 banknr, flash_cris);
895 target_write_u32(target, FLASH_CRIS, 0);
896 return ERROR_FLASH_OPERATION_FAILED;
897 }
898
899 bank->sectors[banknr].is_erased = 1;
900 }
901
902 return ERROR_OK;
903 }
904
905 static int stellaris_protect(struct flash_bank *bank, int set, int first, int last)
906 {
907 struct stellaris_flash_bank *stellaris = bank->driver_priv;
908 struct target *target = bank->target;
909 uint32_t flash_fmc, flash_cris;
910 unsigned int bits_per_page = stellaris->pagesize / 2048;
911
912 if (target->state != TARGET_HALTED) {
913 LOG_ERROR("Target not halted");
914 return ERROR_TARGET_NOT_HALTED;
915 }
916
917 if (!set) {
918 LOG_ERROR("Hardware doesn't support page-level unprotect. "
919 "Try the 'recover' command.");
920 return ERROR_COMMAND_SYNTAX_ERROR;
921 }
922
923 if (stellaris->did1 == 0)
924 return ERROR_FLASH_BANK_NOT_PROBED;
925
926 if (stellaris->target_class == 0x03 &&
927 !((stellaris->did0 >> 8) & 0xFF) &&
928 !((stellaris->did0) & 0xFF)) {
929 LOG_ERROR("DustDevil A0 parts can't be unprotected, see errata; refusing to proceed");
930 return ERROR_FLASH_OPERATION_FAILED;
931 }
932
933 if (!bits_per_page && (first % 2 || !(last % 2))) {
934 LOG_ERROR("Can't protect unaligned pages");
935 return ERROR_FLASH_SECTOR_INVALID;
936 }
937
938 /* Refresh flash controller timing */
939 stellaris_read_clock_info(bank);
940 stellaris_set_flash_timing(bank);
941
942 /* Clear and disable flash programming interrupts */
943 target_write_u32(target, FLASH_CIM, 0);
944 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
945
946 uint32_t flash_sizek = stellaris->pagesize / 1024 *
947 stellaris->num_pages;
948 uint32_t fmppe_addr;
949
950 if (stellaris->target_class >= 0x0a || flash_sizek > 64)
951 fmppe_addr = SCB_BASE | FMPPE0;
952 else
953 fmppe_addr = SCB_BASE | FMPPE;
954
955 int page = 0;
956 unsigned int lockbitnum, lockbitcnt = flash_sizek / 2;
957 /* Every lock bit always corresponds to a 2k region */
958 for (lockbitnum = 0; lockbitnum < lockbitcnt; lockbitnum += 32) {
959 uint32_t fmppe;
960
961 target_read_u32(target, fmppe_addr, &fmppe);
962 for (unsigned int i = 0;
963 i < 32 && lockbitnum + i < lockbitcnt;
964 i++) {
965 if (page >= first && page <= last)
966 fmppe &= ~(1 << i);
967
968 if (bits_per_page) {
969 if (!((i + 1) % bits_per_page))
970 page++;
971 } else { /* 1024k pages, every lockbit covers 2 pages */
972 page += 2;
973 }
974 }
975 target_write_u32(target, fmppe_addr, fmppe);
976
977 /* Commit FMPPE* */
978 target_write_u32(target, FLASH_FMA, 1 + lockbitnum / 16);
979 /* Write commit command */
980 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_COMT);
981
982 /* Wait until commit complete */
983 do {
984 target_read_u32(target, FLASH_FMC, &flash_fmc);
985 } while (flash_fmc & FMC_COMT);
986
987 /* Check access violations */
988 target_read_u32(target, FLASH_CRIS, &flash_cris);
989 if (flash_cris & (AMASK)) {
990 LOG_WARNING("Error setting flash page protection, flash_cris 0x%" PRIx32 "", flash_cris);
991 target_write_u32(target, FLASH_CRIS, 0);
992 return ERROR_FLASH_OPERATION_FAILED;
993 }
994
995 fmppe_addr += 4;
996 }
997
998 return ERROR_OK;
999 }
1000
1001 /* see contib/loaders/flash/stellaris.s for src */
1002
1003 static const uint8_t stellaris_write_code[] = {
1004 /* write: */
1005 0xDF, 0xF8, 0x40, 0x40, /* ldr r4, pFLASH_CTRL_BASE */
1006 0xDF, 0xF8, 0x40, 0x50, /* ldr r5, FLASHWRITECMD */
1007 /* wait_fifo: */
1008 0xD0, 0xF8, 0x00, 0x80, /* ldr r8, [r0, #0] */
1009 0xB8, 0xF1, 0x00, 0x0F, /* cmp r8, #0 */
1010 0x17, 0xD0, /* beq exit */
1011 0x47, 0x68, /* ldr r7, [r0, #4] */
1012 0x47, 0x45, /* cmp r7, r8 */
1013 0xF7, 0xD0, /* beq wait_fifo */
1014 /* mainloop: */
1015 0x22, 0x60, /* str r2, [r4, #0] */
1016 0x02, 0xF1, 0x04, 0x02, /* add r2, r2, #4 */
1017 0x57, 0xF8, 0x04, 0x8B, /* ldr r8, [r7], #4 */
1018 0xC4, 0xF8, 0x04, 0x80, /* str r8, [r4, #4] */
1019 0xA5, 0x60, /* str r5, [r4, #8] */
1020 /* busy: */
1021 0xD4, 0xF8, 0x08, 0x80, /* ldr r8, [r4, #8] */
1022 0x18, 0xF0, 0x01, 0x0F, /* tst r8, #1 */
1023 0xFA, 0xD1, /* bne busy */
1024 0x8F, 0x42, /* cmp r7, r1 */
1025 0x28, 0xBF, /* it cs */
1026 0x00, 0xF1, 0x08, 0x07, /* addcs r7, r0, #8 */
1027 0x47, 0x60, /* str r7, [r0, #4] */
1028 0x01, 0x3B, /* subs r3, r3, #1 */
1029 0x03, 0xB1, /* cbz r3, exit */
1030 0xE2, 0xE7, /* b wait_fifo */
1031 /* exit: */
1032 0x00, 0xBE, /* bkpt #0 */
1033
1034 /* pFLASH_CTRL_BASE: */
1035 0x00, 0xD0, 0x0F, 0x40, /* .word 0x400FD000 */
1036 /* FLASHWRITECMD: */
1037 0x01, 0x00, 0x42, 0xA4 /* .word 0xA4420001 */
1038 };
1039 static int stellaris_write_block(struct flash_bank *bank,
1040 const uint8_t *buffer, uint32_t offset, uint32_t wcount)
1041 {
1042 struct target *target = bank->target;
1043 uint32_t buffer_size = 16384;
1044 struct working_area *source;
1045 struct working_area *write_algorithm;
1046 uint32_t address = bank->base + offset;
1047 struct reg_param reg_params[4];
1048 struct armv7m_algorithm armv7m_info;
1049 int retval = ERROR_OK;
1050
1051 /* power of two, and multiple of word size */
1052 static const unsigned buf_min = 128;
1053
1054 /* for small buffers it's faster not to download an algorithm */
1055 if (wcount * 4 < buf_min)
1056 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1057
1058 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32 " wcount=%08" PRIx32 "",
1059 bank, buffer, offset, wcount);
1060
1061 /* flash write code */
1062 if (target_alloc_working_area(target, sizeof(stellaris_write_code),
1063 &write_algorithm) != ERROR_OK) {
1064 LOG_DEBUG("no working area for block memory writes");
1065 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1066 }
1067
1068 /* plus a buffer big enough for this data */
1069 if (wcount * 4 < buffer_size)
1070 buffer_size = wcount * 4;
1071
1072 /* memory buffer */
1073 while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
1074 buffer_size /= 2;
1075 if (buffer_size <= buf_min) {
1076 target_free_working_area(target, write_algorithm);
1077 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1078 }
1079 LOG_DEBUG("retry target_alloc_working_area(%s, size=%u)",
1080 target_name(target), (unsigned) buffer_size);
1081 }
1082
1083 target_write_buffer(target, write_algorithm->address,
1084 sizeof(stellaris_write_code),
1085 stellaris_write_code);
1086
1087 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
1088 armv7m_info.core_mode = ARM_MODE_THREAD;
1089
1090 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
1091 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
1092 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
1093 init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
1094
1095 buf_set_u32(reg_params[0].value, 0, 32, source->address);
1096 buf_set_u32(reg_params[1].value, 0, 32, source->address + source->size);
1097 buf_set_u32(reg_params[2].value, 0, 32, address);
1098 buf_set_u32(reg_params[3].value, 0, 32, wcount);
1099
1100 retval = target_run_flash_async_algorithm(target, buffer, wcount, 4,
1101 0, NULL,
1102 4, reg_params,
1103 source->address, source->size,
1104 write_algorithm->address, 0,
1105 &armv7m_info);
1106
1107 if (retval == ERROR_FLASH_OPERATION_FAILED)
1108 LOG_ERROR("error %d executing stellaris flash write algorithm", retval);
1109
1110 target_free_working_area(target, write_algorithm);
1111 target_free_working_area(target, source);
1112
1113 destroy_reg_param(&reg_params[0]);
1114 destroy_reg_param(&reg_params[1]);
1115 destroy_reg_param(&reg_params[2]);
1116 destroy_reg_param(&reg_params[3]);
1117
1118 return retval;
1119 }
1120
1121 static int stellaris_write(struct flash_bank *bank, const uint8_t *buffer,
1122 uint32_t offset, uint32_t count)
1123 {
1124 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
1125 struct target *target = bank->target;
1126 uint32_t address = offset;
1127 uint32_t flash_cris, flash_fmc;
1128 uint32_t words_remaining = (count / 4);
1129 uint32_t bytes_remaining = (count & 0x00000003);
1130 uint32_t bytes_written = 0;
1131 int retval;
1132
1133 if (bank->target->state != TARGET_HALTED) {
1134 LOG_ERROR("Target not halted");
1135 return ERROR_TARGET_NOT_HALTED;
1136 }
1137
1138 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32 " count=%08" PRIx32 "",
1139 bank, buffer, offset, count);
1140
1141 if (stellaris_info->did1 == 0)
1142 return ERROR_FLASH_BANK_NOT_PROBED;
1143
1144 if (offset & 0x3) {
1145 LOG_WARNING("offset size must be word aligned");
1146 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
1147 }
1148
1149 if (offset + count > bank->size)
1150 return ERROR_FLASH_DST_OUT_OF_BANK;
1151
1152 /* Refresh flash controller timing */
1153 stellaris_read_clock_info(bank);
1154 stellaris_set_flash_timing(bank);
1155
1156 /* Clear and disable flash programming interrupts */
1157 target_write_u32(target, FLASH_CIM, 0);
1158 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
1159
1160 /* REVISIT this clobbers state set by any halted firmware ...
1161 * it might want to process those IRQs.
1162 */
1163
1164 /* multiple words to be programmed? */
1165 if (words_remaining > 0) {
1166 /* try using a block write */
1167 retval = stellaris_write_block(bank, buffer, offset,
1168 words_remaining);
1169 if (retval != ERROR_OK) {
1170 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
1171 LOG_DEBUG("writing flash word-at-a-time");
1172 } else if (retval == ERROR_FLASH_OPERATION_FAILED) {
1173 /* if an error occured, we examine the reason, and quit */
1174 target_read_u32(target, FLASH_CRIS, &flash_cris);
1175
1176 LOG_ERROR("flash writing failed with CRIS: 0x%" PRIx32 "", flash_cris);
1177 return ERROR_FLASH_OPERATION_FAILED;
1178 }
1179 } else {
1180 buffer += words_remaining * 4;
1181 address += words_remaining * 4;
1182 words_remaining = 0;
1183 }
1184 }
1185
1186 while (words_remaining > 0) {
1187 if (!(address & 0xff))
1188 LOG_DEBUG("0x%" PRIx32 "", address);
1189
1190 /* Program one word */
1191 target_write_u32(target, FLASH_FMA, address);
1192 target_write_buffer(target, FLASH_FMD, 4, buffer);
1193 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
1194 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1195 /* Wait until write complete */
1196 do {
1197 target_read_u32(target, FLASH_FMC, &flash_fmc);
1198 } while (flash_fmc & FMC_WRITE);
1199
1200 buffer += 4;
1201 address += 4;
1202 words_remaining--;
1203 }
1204
1205 if (bytes_remaining) {
1206 uint8_t last_word[4] = {0xff, 0xff, 0xff, 0xff};
1207
1208 /* copy the last remaining bytes into the write buffer */
1209 memcpy(last_word, buffer+bytes_written, bytes_remaining);
1210
1211 if (!(address & 0xff))
1212 LOG_DEBUG("0x%" PRIx32 "", address);
1213
1214 /* Program one word */
1215 target_write_u32(target, FLASH_FMA, address);
1216 target_write_buffer(target, FLASH_FMD, 4, last_word);
1217 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
1218 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1219 /* Wait until write complete */
1220 do {
1221 target_read_u32(target, FLASH_FMC, &flash_fmc);
1222 } while (flash_fmc & FMC_WRITE);
1223 }
1224
1225 /* Check access violations */
1226 target_read_u32(target, FLASH_CRIS, &flash_cris);
1227 if (flash_cris & (AMASK)) {
1228 LOG_DEBUG("flash_cris 0x%" PRIx32 "", flash_cris);
1229 return ERROR_FLASH_OPERATION_FAILED;
1230 }
1231 return ERROR_OK;
1232 }
1233
1234 static int stellaris_probe(struct flash_bank *bank)
1235 {
1236 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
1237 int retval;
1238
1239 /* If this is a stellaris chip, it has flash; probe() is just
1240 * to figure out how much is present. Only do it once.
1241 */
1242 if (stellaris_info->did1 != 0)
1243 return ERROR_OK;
1244
1245 /* stellaris_read_part_info() already handled error checking and
1246 * reporting. Note that it doesn't write, so we don't care about
1247 * whether the target is halted or not.
1248 */
1249 retval = stellaris_read_part_info(bank);
1250 if (retval != ERROR_OK)
1251 return retval;
1252
1253 if (bank->sectors) {
1254 free(bank->sectors);
1255 bank->sectors = NULL;
1256 }
1257
1258 /* provide this for the benefit of the NOR flash framework */
1259 bank->size = stellaris_info->num_pages * stellaris_info->pagesize;
1260 bank->num_sectors = stellaris_info->num_pages;
1261 bank->sectors = calloc(bank->num_sectors, sizeof(struct flash_sector));
1262 for (int i = 0; i < bank->num_sectors; i++) {
1263 bank->sectors[i].offset = i * stellaris_info->pagesize;
1264 bank->sectors[i].size = stellaris_info->pagesize;
1265 bank->sectors[i].is_erased = -1;
1266 bank->sectors[i].is_protected = -1;
1267 }
1268
1269 return retval;
1270 }
1271
1272 static int stellaris_mass_erase(struct flash_bank *bank)
1273 {
1274 struct target *target = NULL;
1275 struct stellaris_flash_bank *stellaris_info = NULL;
1276 uint32_t flash_fmc;
1277
1278 stellaris_info = bank->driver_priv;
1279 target = bank->target;
1280
1281 if (target->state != TARGET_HALTED) {
1282 LOG_ERROR("Target not halted");
1283 return ERROR_TARGET_NOT_HALTED;
1284 }
1285
1286 if (stellaris_info->did1 == 0)
1287 return ERROR_FLASH_BANK_NOT_PROBED;
1288
1289 /* Refresh flash controller timing */
1290 stellaris_read_clock_info(bank);
1291 stellaris_set_flash_timing(bank);
1292
1293 /* Clear and disable flash programming interrupts */
1294 target_write_u32(target, FLASH_CIM, 0);
1295 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
1296
1297 /* REVISIT this clobbers state set by any halted firmware ...
1298 * it might want to process those IRQs.
1299 */
1300
1301 target_write_u32(target, FLASH_FMA, 0);
1302 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
1303 /* Wait until erase complete */
1304 do {
1305 target_read_u32(target, FLASH_FMC, &flash_fmc);
1306 } while (flash_fmc & FMC_MERASE);
1307
1308 /* if device has > 128k, then second erase cycle is needed
1309 * this is only valid for older devices, but will not hurt */
1310 if (stellaris_info->num_pages * stellaris_info->pagesize > 0x20000) {
1311 target_write_u32(target, FLASH_FMA, 0x20000);
1312 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
1313 /* Wait until erase complete */
1314 do {
1315 target_read_u32(target, FLASH_FMC, &flash_fmc);
1316 } while (flash_fmc & FMC_MERASE);
1317 }
1318
1319 return ERROR_OK;
1320 }
1321
1322 COMMAND_HANDLER(stellaris_handle_mass_erase_command)
1323 {
1324 int i;
1325
1326 if (CMD_ARGC < 1)
1327 return ERROR_COMMAND_SYNTAX_ERROR;
1328
1329 struct flash_bank *bank;
1330 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1331 if (ERROR_OK != retval)
1332 return retval;
1333
1334 if (stellaris_mass_erase(bank) == ERROR_OK) {
1335 /* set all sectors as erased */
1336 for (i = 0; i < bank->num_sectors; i++)
1337 bank->sectors[i].is_erased = 1;
1338
1339 command_print(CMD_CTX, "stellaris mass erase complete");
1340 } else
1341 command_print(CMD_CTX, "stellaris mass erase failed");
1342
1343 return ERROR_OK;
1344 }
1345
1346 /**
1347 * Perform the Stellaris "Recovering a 'Locked' Device procedure.
1348 * This performs a mass erase and then restores all nonvolatile registers
1349 * (including USER_* registers and flash lock bits) to their defaults.
1350 * Accordingly, flash can be reprogrammed, and JTAG can be used.
1351 *
1352 * NOTE that DustDevil parts (at least rev A0 silicon) have errata which
1353 * can affect this operation if flash protection has been enabled.
1354 */
1355 COMMAND_HANDLER(stellaris_handle_recover_command)
1356 {
1357 struct flash_bank *bank;
1358 int retval;
1359
1360 if (CMD_ARGC != 0)
1361 return ERROR_COMMAND_SYNTAX_ERROR;
1362
1363 bank = get_flash_bank_by_num_noprobe(0);
1364 if (!bank)
1365 return ERROR_FAIL;
1366
1367 /* REVISIT ... it may be worth sanity checking that the AP is
1368 * inactive before we start. ARM documents that switching a DP's
1369 * mode while it's active can cause fault modes that need a power
1370 * cycle to recover.
1371 */
1372
1373 Jim_Eval_Named(CMD_CTX->interp, "catch { hla_command \"debug unlock\" }", 0, 0);
1374 if (!strcmp(Jim_GetString(Jim_GetResult(CMD_CTX->interp), NULL), "0")) {
1375 retval = ERROR_OK;
1376 goto user_action;
1377 }
1378
1379 /* assert SRST */
1380 if (!(jtag_get_reset_config() & RESET_HAS_SRST)) {
1381 LOG_ERROR("Can't recover Stellaris flash without SRST");
1382 return ERROR_FAIL;
1383 }
1384 adapter_assert_reset();
1385
1386 for (int i = 0; i < 5; i++) {
1387 retval = dap_to_swd(bank->target);
1388 if (retval != ERROR_OK)
1389 goto done;
1390
1391 retval = dap_to_jtag(bank->target);
1392 if (retval != ERROR_OK)
1393 goto done;
1394 }
1395
1396 /* de-assert SRST */
1397 adapter_deassert_reset();
1398 retval = jtag_execute_queue();
1399
1400 /* wait 400+ msec ... OK, "1+ second" is simpler */
1401 usleep(1000);
1402
1403 user_action:
1404 /* USER INTERVENTION required for the power cycle
1405 * Restarting OpenOCD is likely needed because of mode switching.
1406 */
1407 LOG_INFO("USER ACTION: "
1408 "power cycle Stellaris chip, then restart OpenOCD.");
1409
1410 done:
1411 return retval;
1412 }
1413
1414 static const struct command_registration stellaris_exec_command_handlers[] = {
1415 {
1416 .name = "mass_erase",
1417 .usage = "<bank>",
1418 .handler = stellaris_handle_mass_erase_command,
1419 .mode = COMMAND_EXEC,
1420 .help = "erase entire device",
1421 },
1422 {
1423 .name = "recover",
1424 .handler = stellaris_handle_recover_command,
1425 .mode = COMMAND_EXEC,
1426 .usage = "",
1427 .help = "recover (and erase) locked device",
1428 },
1429 COMMAND_REGISTRATION_DONE
1430 };
1431 static const struct command_registration stellaris_command_handlers[] = {
1432 {
1433 .name = "stellaris",
1434 .mode = COMMAND_EXEC,
1435 .help = "Stellaris flash command group",
1436 .usage = "",
1437 .chain = stellaris_exec_command_handlers,
1438 },
1439 COMMAND_REGISTRATION_DONE
1440 };
1441
1442 struct flash_driver stellaris_flash = {
1443 .name = "stellaris",
1444 .commands = stellaris_command_handlers,
1445 .flash_bank_command = stellaris_flash_bank_command,
1446 .erase = stellaris_erase,
1447 .protect = stellaris_protect,
1448 .write = stellaris_write,
1449 .read = default_flash_read,
1450 .probe = stellaris_probe,
1451 .auto_probe = stellaris_probe,
1452 .erase_check = default_flash_blank_check,
1453 .protect_check = stellaris_protect_check,
1454 .info = get_stellaris_info,
1455 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)