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

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)