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

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)