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

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)