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

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)