flash: update luminary device table
[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 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include "imp.h"
32 #include <target/algorithm.h>
33 #include <target/armv7m.h>
34
35
36 #define DID0_VER(did0) ((did0 >> 28)&0x07)
37
38 /* STELLARIS control registers */
39 #define SCB_BASE 0x400FE000
40 #define DID0 0x000
41 #define DID1 0x004
42 #define DC0 0x008
43 #define DC1 0x010
44 #define DC2 0x014
45 #define DC3 0x018
46 #define DC4 0x01C
47
48 #define RIS 0x050
49 #define RCC 0x060
50 #define PLLCFG 0x064
51 #define RCC2 0x070
52 #define NVMSTAT 0x1a0
53
54 /* "legacy" flash memory protection registers (64KB max) */
55 #define FMPRE 0x130
56 #define FMPPE 0x134
57
58 /* new flash memory protection registers (for more than 64KB) */
59 #define FMPRE0 0x200 /* PRE1 = PRE0 + 4, etc */
60 #define FMPPE0 0x400 /* PPE1 = PPE0 + 4, etc */
61
62 #define USECRL 0x140
63
64 #define FLASH_CONTROL_BASE 0x400FD000
65 #define FLASH_FMA (FLASH_CONTROL_BASE | 0x000)
66 #define FLASH_FMD (FLASH_CONTROL_BASE | 0x004)
67 #define FLASH_FMC (FLASH_CONTROL_BASE | 0x008)
68 #define FLASH_CRIS (FLASH_CONTROL_BASE | 0x00C)
69 #define FLASH_CIM (FLASH_CONTROL_BASE | 0x010)
70 #define FLASH_MISC (FLASH_CONTROL_BASE | 0x014)
71
72 #define AMISC 1
73 #define PMISC 2
74
75 #define AMASK 1
76 #define PMASK 2
77
78 /* Flash Controller Command bits */
79 #define FMC_WRKEY (0xA442 << 16)
80 #define FMC_COMT (1 << 3)
81 #define FMC_MERASE (1 << 2)
82 #define FMC_ERASE (1 << 1)
83 #define FMC_WRITE (1 << 0)
84
85 /* STELLARIS constants */
86
87 /* values to write in FMA to commit write-"once" values */
88 #define FLASH_FMA_PRE(x) (2 * (x)) /* for FMPPREx */
89 #define FLASH_FMA_PPE(x) (2 * (x) + 1) /* for FMPPPEx */
90
91
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 {
97 /* chip id register */
98 uint32_t did0;
99 uint32_t did1;
100 uint32_t dc0;
101 uint32_t dc1;
102
103 const char * target_name;
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 {
420 "Sandstorm",
421 "Fury",
422 "Unknown",
423 "DustDevil",
424 "Tempest",
425 "Blizzard",
426 "Firestorm"
427 };
428
429 /***************************************************************************
430 * openocd command interface *
431 ***************************************************************************/
432
433 /* flash_bank stellaris <base> <size> 0 0 <target#>
434 */
435 FLASH_BANK_COMMAND_HANDLER(stellaris_flash_bank_command)
436 {
437 struct stellaris_flash_bank *stellaris_info;
438
439 if (CMD_ARGC < 6)
440 {
441 LOG_WARNING("incomplete flash_bank stellaris configuration");
442 return ERROR_FLASH_BANK_INVALID;
443 }
444
445 stellaris_info = calloc(sizeof(struct stellaris_flash_bank), 1);
446 bank->base = 0x0;
447 bank->driver_priv = stellaris_info;
448
449 stellaris_info->target_name = "Unknown target";
450
451 /* part wasn't probed for info yet */
452 stellaris_info->did1 = 0;
453
454 /* TODO Specify the main crystal speed in kHz using an optional
455 * argument; ditto, the speed of an external oscillator used
456 * instead of a crystal. Avoid programming flash using IOSC.
457 */
458 return ERROR_OK;
459 }
460
461 static int get_stellaris_info(struct flash_bank *bank, char *buf, int buf_size)
462 {
463 int printed, device_class;
464 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
465
466 if (stellaris_info->did1 == 0)
467 return ERROR_FLASH_BANK_NOT_PROBED;
468
469 /* Read main and master clock freqency register */
470 stellaris_read_clock_info(bank);
471
472 if (DID0_VER(stellaris_info->did0) > 0)
473 {
474 device_class = (stellaris_info->did0 >> 16) & 0xFF;
475 }
476 else
477 {
478 device_class = 0;
479 }
480 printed = snprintf(buf,
481 buf_size,
482 "\nTI/LMI Stellaris information: Chip is "
483 "class %i (%s) %s rev %c%i\n",
484 device_class,
485 StellarisClassname[device_class],
486 stellaris_info->target_name,
487 (int)('A' + ((stellaris_info->did0 >> 8) & 0xFF)),
488 (int)((stellaris_info->did0) & 0xFF));
489 buf += printed;
490 buf_size -= printed;
491
492 printed = snprintf(buf,
493 buf_size,
494 "did1: 0x%8.8" PRIx32 ", arch: 0x%4.4" PRIx32
495 ", eproc: %s, ramsize: %ik, flashsize: %ik\n",
496 stellaris_info->did1,
497 stellaris_info->did1,
498 "ARMv7M",
499 (int)((1 + ((stellaris_info->dc0 >> 16) & 0xFFFF))/4),
500 (int)((1 + (stellaris_info->dc0 & 0xFFFF))*2));
501 buf += printed;
502 buf_size -= printed;
503
504 printed = snprintf(buf,
505 buf_size,
506 "master clock: %ikHz%s, "
507 "rcc is 0x%" PRIx32 ", rcc2 is 0x%" PRIx32 "\n",
508 (int)(stellaris_info->mck_freq / 1000),
509 stellaris_info->mck_desc,
510 stellaris_info->rcc,
511 stellaris_info->rcc2);
512 buf += printed;
513 buf_size -= printed;
514
515 if (stellaris_info->num_lockbits > 0)
516 {
517 printed = snprintf(buf,
518 buf_size,
519 "pagesize: %" PRIi32 ", pages: %d, "
520 "lockbits: %i, pages per lockbit: %i\n",
521 stellaris_info->pagesize,
522 (unsigned) stellaris_info->num_pages,
523 stellaris_info->num_lockbits,
524 (unsigned) stellaris_info->pages_in_lockregion);
525 buf += printed;
526 buf_size -= printed;
527 }
528 return ERROR_OK;
529 }
530
531 /***************************************************************************
532 * chip identification and status *
533 ***************************************************************************/
534
535 /* Set the flash timimg register to match current clocking */
536 static void stellaris_set_flash_timing(struct flash_bank *bank)
537 {
538 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
539 struct target *target = bank->target;
540 uint32_t usecrl = (stellaris_info->mck_freq/1000000ul-1);
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 {
625 case 0: /* MOSC */
626 mainfreq = rcc_xtal[xtal];
627 break;
628 case 1: /* IOSC */
629 mainfreq = stellaris_info->iosc_freq;
630 stellaris_info->mck_desc = stellaris_info->iosc_desc;
631 break;
632 case 2: /* IOSC/4 */
633 mainfreq = stellaris_info->iosc_freq / 4;
634 stellaris_info->mck_desc = stellaris_info->iosc_desc;
635 break;
636 case 3: /* lowspeed */
637 /* Sandstorm doesn't have this 30K +/- 30% osc */
638 mainfreq = 30000;
639 stellaris_info->mck_desc = " (±30%)";
640 break;
641 case 8: /* hibernation osc */
642 /* not all parts support hibernation */
643 mainfreq = 32768;
644 break;
645
646 default: /* NOTREACHED */
647 mainfreq = 0;
648 break;
649 }
650
651 /* PLL is used if it's not bypassed; its output is 200 MHz
652 * even when it runs at 400 MHz (adds divide-by-two stage).
653 */
654 if (!bypass)
655 mainfreq = 200000000;
656
657 if (usesysdiv)
658 stellaris_info->mck_freq = mainfreq/(1 + sysdiv);
659 else
660 stellaris_info->mck_freq = mainfreq;
661 }
662
663 /* Read device id register, main clock frequency register and fill in driver info structure */
664 static int stellaris_read_part_info(struct flash_bank *bank)
665 {
666 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
667 struct target *target = bank->target;
668 uint32_t did0, did1, ver, fam;
669 int i;
670
671 /* Read and parse chip identification register */
672 target_read_u32(target, SCB_BASE | DID0, &did0);
673 target_read_u32(target, SCB_BASE | DID1, &did1);
674 target_read_u32(target, SCB_BASE | DC0, &stellaris_info->dc0);
675 target_read_u32(target, SCB_BASE | DC1, &stellaris_info->dc1);
676 LOG_DEBUG("did0 0x%" PRIx32 ", did1 0x%" PRIx32 ", dc0 0x%" PRIx32 ", dc1 0x%" PRIx32 "",
677 did0, did1, stellaris_info->dc0, stellaris_info->dc1);
678
679 ver = did0 >> 28;
680 if ((ver != 0) && (ver != 1))
681 {
682 LOG_WARNING("Unknown did0 version, cannot identify target");
683 return ERROR_FLASH_OPERATION_FAILED;
684 }
685
686 if (did1 == 0)
687 {
688 LOG_WARNING("Cannot identify target as a Stellaris");
689 return ERROR_FLASH_OPERATION_FAILED;
690 }
691
692 ver = did1 >> 28;
693 fam = (did1 >> 24) & 0xF;
694 if (((ver != 0) && (ver != 1)) || (fam != 0))
695 {
696 LOG_WARNING("Unknown did1 version/family.");
697 return ERROR_FLASH_OPERATION_FAILED;
698 }
699
700 /* For Sandstorm, Fury, DustDevil: current data sheets say IOSC
701 * is 12 MHz, but some older parts have 15 MHz. A few data sheets
702 * even give _both_ numbers! We'll use current numbers; IOSC is
703 * always approximate.
704 *
705 * For Tempest: IOSC is calibrated, 16 MHz
706 */
707 stellaris_info->iosc_freq = 12000000;
708 stellaris_info->iosc_desc = " (±30%)";
709 stellaris_info->xtal_mask = 0x0f;
710
711 switch ((did0 >> 28) & 0x7) {
712 case 0: /* Sandstorm */
713 /*
714 * Current (2009-August) parts seem to be rev C2 and use 12 MHz.
715 * Parts before rev C0 used 15 MHz; some C0 parts use 15 MHz
716 * (LM3S618), but some other C0 parts are 12 MHz (LM3S811).
717 */
718 if (((did0 >> 8) & 0xff) < 2) {
719 stellaris_info->iosc_freq = 15000000;
720 stellaris_info->iosc_desc = " (±50%)";
721 }
722 break;
723 case 1:
724 switch ((did0 >> 16) & 0xff) {
725 case 1: /* Fury */
726 break;
727 case 4: /* Tempest */
728 stellaris_info->iosc_freq = 16000000; /* +/- 1% */
729 stellaris_info->iosc_desc = " (±1%)";
730 /* FALL THROUGH */
731 case 3: /* DustDevil */
732 stellaris_info->xtal_mask = 0x1f;
733 break;
734 default:
735 LOG_WARNING("Unknown did0 class");
736 }
737 break;
738 default:
739 LOG_WARNING("Unknown did0 version");
740 break;
741 }
742
743 for (i = 0; StellarisParts[i].partno; i++)
744 {
745 if ((StellarisParts[i].partno == ((did1 >> 16) & 0xFF)) &&
746 (StellarisParts[i].class == ((did0 >> 16) & 0xFF)))
747 break;
748 }
749
750 stellaris_info->target_name = StellarisParts[i].partname;
751
752 stellaris_info->did0 = did0;
753 stellaris_info->did1 = did1;
754
755 stellaris_info->num_lockbits = 1 + (stellaris_info->dc0 & 0xFFFF);
756 stellaris_info->num_pages = 2 *(1 + (stellaris_info->dc0 & 0xFFFF));
757 stellaris_info->pagesize = 1024;
758 stellaris_info->pages_in_lockregion = 2;
759
760 /* REVISIT for at least Tempest parts, read NVMSTAT.FWB too.
761 * That exposes a 32-word Flash Write Buffer ... enabling
762 * writes of more than one word at a time.
763 */
764
765 return ERROR_OK;
766 }
767
768 /***************************************************************************
769 * flash operations *
770 ***************************************************************************/
771
772 static int stellaris_protect_check(struct flash_bank *bank)
773 {
774 struct stellaris_flash_bank *stellaris = bank->driver_priv;
775 int status = ERROR_OK;
776 unsigned i;
777 unsigned page;
778
779 if (stellaris->did1 == 0)
780 return ERROR_FLASH_BANK_NOT_PROBED;
781
782 for (i = 0; i < (unsigned) bank->num_sectors; i++)
783 bank->sectors[i].is_protected = -1;
784
785 /* Read each Flash Memory Protection Program Enable (FMPPE) register
786 * to report any pages that we can't write. Ignore the Read Enable
787 * register (FMPRE).
788 */
789 for (i = 0, page = 0;
790 i < DIV_ROUND_UP(stellaris->num_lockbits, 32u);
791 i++) {
792 uint32_t lockbits;
793
794 status = target_read_u32(bank->target,
795 SCB_BASE + (i ? (FMPPE0 + 4 * i) : FMPPE),
796 &lockbits);
797 LOG_DEBUG("FMPPE%d = %#8.8x (status %d)", i,
798 (unsigned) lockbits, status);
799 if (status != ERROR_OK)
800 goto done;
801
802 for (unsigned j = 0; j < 32; j++) {
803 unsigned k;
804
805 for (k = 0; k < stellaris->pages_in_lockregion; k++) {
806 if (page >= (unsigned) bank->num_sectors)
807 goto done;
808 bank->sectors[page++].is_protected =
809 !(lockbits & (1 << j));
810 }
811 }
812 }
813
814 done:
815 return status;
816 }
817
818 static int stellaris_erase(struct flash_bank *bank, int first, int last)
819 {
820 int banknr;
821 uint32_t flash_fmc, flash_cris;
822 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
823 struct target *target = bank->target;
824
825 if (bank->target->state != TARGET_HALTED)
826 {
827 LOG_ERROR("Target not halted");
828 return ERROR_TARGET_NOT_HALTED;
829 }
830
831 if (stellaris_info->did1 == 0)
832 return ERROR_FLASH_BANK_NOT_PROBED;
833
834 if ((first < 0) || (last < first) || (last >= (int)stellaris_info->num_pages))
835 {
836 return ERROR_FLASH_SECTOR_INVALID;
837 }
838
839 if ((first == 0) && (last == ((int)stellaris_info->num_pages-1)))
840 {
841 return stellaris_mass_erase(bank);
842 }
843
844 /* Refresh flash controller timing */
845 stellaris_read_clock_info(bank);
846 stellaris_set_flash_timing(bank);
847
848 /* Clear and disable flash programming interrupts */
849 target_write_u32(target, FLASH_CIM, 0);
850 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
851
852 /* REVISIT this clobbers state set by any halted firmware ...
853 * it might want to process those IRQs.
854 */
855
856 for (banknr = first; banknr <= last; banknr++)
857 {
858 /* Address is first word in page */
859 target_write_u32(target, FLASH_FMA, banknr * stellaris_info->pagesize);
860 /* Write erase command */
861 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_ERASE);
862 /* Wait until erase complete */
863 do
864 {
865 target_read_u32(target, FLASH_FMC, &flash_fmc);
866 }
867 while (flash_fmc & FMC_ERASE);
868
869 /* Check acess violations */
870 target_read_u32(target, FLASH_CRIS, &flash_cris);
871 if (flash_cris & (AMASK))
872 {
873 LOG_WARNING("Error erasing flash page %i, flash_cris 0x%" PRIx32 "", banknr, flash_cris);
874 target_write_u32(target, FLASH_CRIS, 0);
875 return ERROR_FLASH_OPERATION_FAILED;
876 }
877
878 bank->sectors[banknr].is_erased = 1;
879 }
880
881 return ERROR_OK;
882 }
883
884 static int stellaris_protect(struct flash_bank *bank, int set, int first, int last)
885 {
886 uint32_t fmppe, flash_fmc, flash_cris;
887 int lockregion;
888
889 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
890 struct target *target = bank->target;
891
892 if (bank->target->state != TARGET_HALTED)
893 {
894 LOG_ERROR("Target not halted");
895 return ERROR_TARGET_NOT_HALTED;
896 }
897
898 if (!set)
899 {
900 LOG_ERROR("Hardware doesn't support page-level unprotect. "
901 "Try the 'recover' command.");
902 return ERROR_INVALID_ARGUMENTS;
903 }
904
905 if (stellaris_info->did1 == 0)
906 return ERROR_FLASH_BANK_NOT_PROBED;
907
908 /* lockregions are 2 pages ... must protect [even..odd] */
909 if ((first < 0) || (first & 1)
910 || (last < first) || !(last & 1)
911 || (last >= 2 * stellaris_info->num_lockbits))
912 {
913 LOG_ERROR("Can't protect unaligned or out-of-range pages.");
914 return ERROR_FLASH_SECTOR_INVALID;
915 }
916
917 /* Refresh flash controller timing */
918 stellaris_read_clock_info(bank);
919 stellaris_set_flash_timing(bank);
920
921 /* convert from pages to lockregions */
922 first /= 2;
923 last /= 2;
924
925 /* FIXME this assumes single FMPPE, for a max of 64K of flash!!
926 * Current parts can be much bigger.
927 */
928 if (last >= 32) {
929 LOG_ERROR("No support yet for protection > 64K");
930 return ERROR_FLASH_OPERATION_FAILED;
931 }
932
933 target_read_u32(target, SCB_BASE | FMPPE, &fmppe);
934
935 for (lockregion = first; lockregion <= last; lockregion++)
936 fmppe &= ~(1 << lockregion);
937
938 /* Clear and disable flash programming interrupts */
939 target_write_u32(target, FLASH_CIM, 0);
940 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
941
942 /* REVISIT this clobbers state set by any halted firmware ...
943 * it might want to process those IRQs.
944 */
945
946 LOG_DEBUG("fmppe 0x%" PRIx32 "",fmppe);
947 target_write_u32(target, SCB_BASE | FMPPE, fmppe);
948
949 /* Commit FMPPE */
950 target_write_u32(target, FLASH_FMA, 1);
951
952 /* Write commit command */
953 /* REVISIT safety check, since this cannot be undone
954 * except by the "Recover a locked device" procedure.
955 * REVISIT DustDevil-A0 parts have an erratum making FMPPE commits
956 * inadvisable ... it makes future mass erase operations fail.
957 */
958 LOG_WARNING("Flash protection cannot be removed once committed, commit is NOT executed !");
959 /* target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_COMT); */
960
961 /* Wait until erase complete */
962 do
963 {
964 target_read_u32(target, FLASH_FMC, &flash_fmc);
965 }
966 while (flash_fmc & FMC_COMT);
967
968 /* Check acess violations */
969 target_read_u32(target, FLASH_CRIS, &flash_cris);
970 if (flash_cris & (AMASK))
971 {
972 LOG_WARNING("Error setting flash page protection, flash_cris 0x%" PRIx32 "", flash_cris);
973 target_write_u32(target, FLASH_CRIS, 0);
974 return ERROR_FLASH_OPERATION_FAILED;
975 }
976
977 return ERROR_OK;
978 }
979
980 /* see contib/loaders/flash/stellaris.s for src */
981
982 static const uint8_t stellaris_write_code[] =
983 {
984 /*
985 Call with :
986 r0 = buffer address
987 r1 = destination address
988 r2 = bytecount (in) - endaddr (work)
989
990 Used registers:
991 r3 = pFLASH_CTRL_BASE
992 r4 = FLASHWRITECMD
993 r5 = #1
994 r6 = bytes written
995 r7 = temp reg
996 */
997 0x07,0x4B, /* ldr r3,pFLASH_CTRL_BASE */
998 0x08,0x4C, /* ldr r4,FLASHWRITECMD */
999 0x01,0x25, /* movs r5, 1 */
1000 0x00,0x26, /* movs r6, #0 */
1001 /* mainloop: */
1002 0x19,0x60, /* str r1, [r3, #0] */
1003 0x87,0x59, /* ldr r7, [r0, r6] */
1004 0x5F,0x60, /* str r7, [r3, #4] */
1005 0x9C,0x60, /* str r4, [r3, #8] */
1006 /* waitloop: */
1007 0x9F,0x68, /* ldr r7, [r3, #8] */
1008 0x2F,0x42, /* tst r7, r5 */
1009 0xFC,0xD1, /* bne waitloop */
1010 0x04,0x31, /* adds r1, r1, #4 */
1011 0x04,0x36, /* adds r6, r6, #4 */
1012 0x96,0x42, /* cmp r6, r2 */
1013 0xF4,0xD1, /* bne mainloop */
1014 0x00,0xBE, /* bkpt #0 */
1015 /* pFLASH_CTRL_BASE: */
1016 0x00,0xD0,0x0F,0x40, /* .word 0x400FD000 */
1017 /* FLASHWRITECMD: */
1018 0x01,0x00,0x42,0xA4 /* .word 0xA4420001 */
1019 };
1020
1021 static int stellaris_write_block(struct flash_bank *bank,
1022 uint8_t *buffer, uint32_t offset, uint32_t wcount)
1023 {
1024 struct target *target = bank->target;
1025 uint32_t buffer_size = 16384;
1026 struct working_area *source;
1027 struct working_area *write_algorithm;
1028 uint32_t address = bank->base + offset;
1029 struct reg_param reg_params[3];
1030 struct armv7m_algorithm armv7m_info;
1031 int retval = ERROR_OK;
1032
1033 /* power of two, and multiple of word size */
1034 static const unsigned buf_min = 128;
1035
1036 /* for small buffers it's faster not to download an algorithm */
1037 if (wcount * 4 < buf_min)
1038 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1039
1040 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32 " wcount=%08" PRIx32 "",
1041 bank, buffer, offset, wcount);
1042
1043 /* flash write code */
1044 if (target_alloc_working_area(target, sizeof(stellaris_write_code), &write_algorithm) != ERROR_OK)
1045 {
1046 LOG_DEBUG("no working area for block memory writes");
1047 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1048 };
1049
1050 /* plus a buffer big enough for this data */
1051 if (wcount * 4 < buffer_size)
1052 buffer_size = wcount * 4;
1053
1054 /* memory buffer */
1055 while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK)
1056 {
1057 buffer_size /= 2;
1058 if (buffer_size <= buf_min)
1059 {
1060 target_free_working_area(target, write_algorithm);
1061 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1062 }
1063 LOG_DEBUG("retry target_alloc_working_area(%s, size=%u)",
1064 target_name(target), (unsigned) buffer_size);
1065 };
1066
1067 retval = target_write_buffer(target, write_algorithm->address,
1068 sizeof(stellaris_write_code),
1069 (uint8_t *) stellaris_write_code);
1070
1071 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
1072 armv7m_info.core_mode = ARMV7M_MODE_ANY;
1073
1074 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
1075 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
1076 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
1077
1078 while (wcount > 0)
1079 {
1080 uint32_t thisrun_count = (wcount > (buffer_size / 4)) ? (buffer_size / 4) : wcount;
1081
1082 target_write_buffer(target, source->address, thisrun_count * 4, buffer);
1083
1084 buf_set_u32(reg_params[0].value, 0, 32, source->address);
1085 buf_set_u32(reg_params[1].value, 0, 32, address);
1086 buf_set_u32(reg_params[2].value, 0, 32, 4*thisrun_count);
1087 LOG_DEBUG("Algorithm flash write %u words to 0x%" PRIx32
1088 ", %u remaining",
1089 (unsigned) thisrun_count, address,
1090 (unsigned) (wcount - thisrun_count));
1091 retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
1092 write_algorithm->address,
1093 0,
1094 10000, &armv7m_info);
1095 if (retval != ERROR_OK)
1096 {
1097 LOG_ERROR("error %d executing stellaris "
1098 "flash write algorithm",
1099 retval);
1100 retval = ERROR_FLASH_OPERATION_FAILED;
1101 break;
1102 }
1103
1104 buffer += thisrun_count * 4;
1105 address += thisrun_count * 4;
1106 wcount -= thisrun_count;
1107 }
1108
1109 /* REVISIT we could speed up writing multi-section images by
1110 * not freeing the initialized write_algorithm this way.
1111 */
1112
1113 target_free_working_area(target, write_algorithm);
1114 target_free_working_area(target, source);
1115
1116 destroy_reg_param(&reg_params[0]);
1117 destroy_reg_param(&reg_params[1]);
1118 destroy_reg_param(&reg_params[2]);
1119
1120 return retval;
1121 }
1122
1123 static int stellaris_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
1124 {
1125 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
1126 struct target *target = bank->target;
1127 uint32_t address = offset;
1128 uint32_t flash_cris, flash_fmc;
1129 uint32_t words_remaining = (count / 4);
1130 uint32_t bytes_remaining = (count & 0x00000003);
1131 uint32_t bytes_written = 0;
1132 int retval;
1133
1134 if (bank->target->state != TARGET_HALTED)
1135 {
1136 LOG_ERROR("Target not halted");
1137 return ERROR_TARGET_NOT_HALTED;
1138 }
1139
1140 LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32 " count=%08" PRIx32 "",
1141 bank, buffer, offset, count);
1142
1143 if (stellaris_info->did1 == 0)
1144 return ERROR_FLASH_BANK_NOT_PROBED;
1145
1146 if (offset & 0x3)
1147 {
1148 LOG_WARNING("offset size must be word aligned");
1149 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
1150 }
1151
1152 if (offset + count > bank->size)
1153 return ERROR_FLASH_DST_OUT_OF_BANK;
1154
1155 /* Refresh flash controller timing */
1156 stellaris_read_clock_info(bank);
1157 stellaris_set_flash_timing(bank);
1158
1159 /* Clear and disable flash programming interrupts */
1160 target_write_u32(target, FLASH_CIM, 0);
1161 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
1162
1163 /* REVISIT this clobbers state set by any halted firmware ...
1164 * it might want to process those IRQs.
1165 */
1166
1167 /* multiple words to be programmed? */
1168 if (words_remaining > 0)
1169 {
1170 /* try using a block write */
1171 retval = stellaris_write_block(bank, buffer, offset,
1172 words_remaining);
1173 if (retval != ERROR_OK)
1174 {
1175 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
1176 {
1177 LOG_DEBUG("writing flash word-at-a-time");
1178 }
1179 else if (retval == ERROR_FLASH_OPERATION_FAILED)
1180 {
1181 /* if an error occured, we examine the reason, and quit */
1182 target_read_u32(target, FLASH_CRIS, &flash_cris);
1183
1184 LOG_ERROR("flash writing failed with CRIS: 0x%" PRIx32 "", flash_cris);
1185 return ERROR_FLASH_OPERATION_FAILED;
1186 }
1187 }
1188 else
1189 {
1190 buffer += words_remaining * 4;
1191 address += words_remaining * 4;
1192 words_remaining = 0;
1193 }
1194 }
1195
1196 while (words_remaining > 0)
1197 {
1198 if (!(address & 0xff))
1199 LOG_DEBUG("0x%" PRIx32 "", address);
1200
1201 /* Program one word */
1202 target_write_u32(target, FLASH_FMA, address);
1203 target_write_buffer(target, FLASH_FMD, 4, buffer);
1204 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
1205 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1206 /* Wait until write complete */
1207 do
1208 {
1209 target_read_u32(target, FLASH_FMC, &flash_fmc);
1210 } while (flash_fmc & FMC_WRITE);
1211
1212 buffer += 4;
1213 address += 4;
1214 words_remaining--;
1215 }
1216
1217 if (bytes_remaining)
1218 {
1219 uint8_t last_word[4] = {0xff, 0xff, 0xff, 0xff};
1220 int i = 0;
1221
1222 while (bytes_remaining > 0)
1223 {
1224 last_word[i++] = *(buffer + bytes_written);
1225 bytes_remaining--;
1226 bytes_written++;
1227 }
1228
1229 if (!(address & 0xff))
1230 LOG_DEBUG("0x%" PRIx32 "", address);
1231
1232 /* Program one word */
1233 target_write_u32(target, FLASH_FMA, address);
1234 target_write_buffer(target, FLASH_FMD, 4, last_word);
1235 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
1236 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
1237 /* Wait until write complete */
1238 do
1239 {
1240 target_read_u32(target, FLASH_FMC, &flash_fmc);
1241 } while (flash_fmc & FMC_WRITE);
1242 }
1243
1244 /* Check access violations */
1245 target_read_u32(target, FLASH_CRIS, &flash_cris);
1246 if (flash_cris & (AMASK))
1247 {
1248 LOG_DEBUG("flash_cris 0x%" PRIx32 "", flash_cris);
1249 return ERROR_FLASH_OPERATION_FAILED;
1250 }
1251 return ERROR_OK;
1252 }
1253
1254 static int stellaris_probe(struct flash_bank *bank)
1255 {
1256 struct stellaris_flash_bank *stellaris_info = bank->driver_priv;
1257 int retval;
1258
1259 /* If this is a stellaris chip, it has flash; probe() is just
1260 * to figure out how much is present. Only do it once.
1261 */
1262 if (stellaris_info->did1 != 0)
1263 return ERROR_OK;
1264
1265 /* stellaris_read_part_info() already handled error checking and
1266 * reporting. Note that it doesn't write, so we don't care about
1267 * whether the target is halted or not.
1268 */
1269 retval = stellaris_read_part_info(bank);
1270 if (retval != ERROR_OK)
1271 return retval;
1272
1273 if (bank->sectors)
1274 {
1275 free(bank->sectors);
1276 bank->sectors = NULL;
1277 }
1278
1279 /* provide this for the benefit of the NOR flash framework */
1280 bank->size = 1024 * stellaris_info->num_pages;
1281 bank->num_sectors = stellaris_info->num_pages;
1282 bank->sectors = calloc(bank->num_sectors, sizeof(struct flash_sector));
1283 for (int i = 0; i < bank->num_sectors; i++)
1284 {
1285 bank->sectors[i].offset = i * stellaris_info->pagesize;
1286 bank->sectors[i].size = stellaris_info->pagesize;
1287 bank->sectors[i].is_erased = -1;
1288 bank->sectors[i].is_protected = -1;
1289 }
1290
1291 return retval;
1292 }
1293
1294 static int stellaris_mass_erase(struct flash_bank *bank)
1295 {
1296 struct target *target = NULL;
1297 struct stellaris_flash_bank *stellaris_info = NULL;
1298 uint32_t flash_fmc;
1299
1300 stellaris_info = bank->driver_priv;
1301 target = bank->target;
1302
1303 if (target->state != TARGET_HALTED)
1304 {
1305 LOG_ERROR("Target not halted");
1306 return ERROR_TARGET_NOT_HALTED;
1307 }
1308
1309 if (stellaris_info->did1 == 0)
1310 return ERROR_FLASH_BANK_NOT_PROBED;
1311
1312 /* Refresh flash controller timing */
1313 stellaris_read_clock_info(bank);
1314 stellaris_set_flash_timing(bank);
1315
1316 /* Clear and disable flash programming interrupts */
1317 target_write_u32(target, FLASH_CIM, 0);
1318 target_write_u32(target, FLASH_MISC, PMISC | AMISC);
1319
1320 /* REVISIT this clobbers state set by any halted firmware ...
1321 * it might want to process those IRQs.
1322 */
1323
1324 target_write_u32(target, FLASH_FMA, 0);
1325 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
1326 /* Wait until erase complete */
1327 do
1328 {
1329 target_read_u32(target, FLASH_FMC, &flash_fmc);
1330 }
1331 while (flash_fmc & FMC_MERASE);
1332
1333 /* if device has > 128k, then second erase cycle is needed
1334 * this is only valid for older devices, but will not hurt */
1335 if (stellaris_info->num_pages * stellaris_info->pagesize > 0x20000)
1336 {
1337 target_write_u32(target, FLASH_FMA, 0x20000);
1338 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
1339 /* Wait until erase complete */
1340 do
1341 {
1342 target_read_u32(target, FLASH_FMC, &flash_fmc);
1343 }
1344 while (flash_fmc & FMC_MERASE);
1345 }
1346
1347 return ERROR_OK;
1348 }
1349
1350 COMMAND_HANDLER(stellaris_handle_mass_erase_command)
1351 {
1352 int i;
1353
1354 if (CMD_ARGC < 1)
1355 {
1356 command_print(CMD_CTX, "stellaris mass_erase <bank>");
1357 return ERROR_OK;
1358 }
1359
1360 struct flash_bank *bank;
1361 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1362 if (ERROR_OK != retval)
1363 return retval;
1364
1365 if (stellaris_mass_erase(bank) == ERROR_OK)
1366 {
1367 /* set all sectors as erased */
1368 for (i = 0; i < bank->num_sectors; i++)
1369 {
1370 bank->sectors[i].is_erased = 1;
1371 }
1372
1373 command_print(CMD_CTX, "stellaris mass erase complete");
1374 }
1375 else
1376 {
1377 command_print(CMD_CTX, "stellaris mass erase failed");
1378 }
1379
1380 return ERROR_OK;
1381 }
1382
1383 /**
1384 * Perform the Stellaris "Recovering a 'Locked' Device procedure.
1385 * This performs a mass erase and then restores all nonvolatile registers
1386 * (including USER_* registers and flash lock bits) to their defaults.
1387 * Accordingly, flash can be reprogrammed, and JTAG can be used.
1388 *
1389 * NOTE that DustDevil parts (at least rev A0 silicon) have errata which
1390 * can affect this operation if flash protection has been enabled.
1391 */
1392 COMMAND_HANDLER(stellaris_handle_recover_command)
1393 {
1394 struct flash_bank *bank;
1395 int retval;
1396
1397 retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1398 if (retval != ERROR_OK)
1399 return retval;
1400
1401 /* REVISIT ... it may be worth sanity checking that the AP is
1402 * inactive before we start. ARM documents that switching a DP's
1403 * mode while it's active can cause fault modes that need a power
1404 * cycle to recover.
1405 */
1406
1407 /* assert SRST */
1408 if (!(jtag_get_reset_config() & RESET_HAS_SRST)) {
1409 LOG_ERROR("Can't recover Stellaris flash without SRST");
1410 return ERROR_FAIL;
1411 }
1412 jtag_add_reset(0, 1);
1413
1414 for (int i = 0; i < 5; i++) {
1415 retval = dap_to_swd(bank->target);
1416 if (retval != ERROR_OK)
1417 goto done;
1418
1419 retval = dap_to_jtag(bank->target);
1420 if (retval != ERROR_OK)
1421 goto done;
1422 }
1423
1424 /* de-assert SRST */
1425 jtag_add_reset(0, 0);
1426 retval = jtag_execute_queue();
1427
1428 /* wait 400+ msec ... OK, "1+ second" is simpler */
1429 usleep(1000);
1430
1431 /* USER INTERVENTION required for the power cycle
1432 * Restarting OpenOCD is likely needed because of mode switching.
1433 */
1434 LOG_INFO("USER ACTION: "
1435 "power cycle Stellaris chip, then restart OpenOCD.");
1436
1437 done:
1438 return retval;
1439 }
1440
1441 static const struct command_registration stellaris_exec_command_handlers[] = {
1442 {
1443 .name = "mass_erase",
1444 .handler = stellaris_handle_mass_erase_command,
1445 .mode = COMMAND_EXEC,
1446 .usage = "bank_id",
1447 .help = "erase entire device",
1448 },
1449 {
1450 .name = "recover",
1451 .handler = stellaris_handle_recover_command,
1452 .mode = COMMAND_EXEC,
1453 .usage = "bank_id",
1454 .help = "recover (and erase) locked device",
1455 },
1456 COMMAND_REGISTRATION_DONE
1457 };
1458 static const struct command_registration stellaris_command_handlers[] = {
1459 {
1460 .name = "stellaris",
1461 .mode = COMMAND_EXEC,
1462 .help = "Stellaris flash command group",
1463 .chain = stellaris_exec_command_handlers,
1464 },
1465 COMMAND_REGISTRATION_DONE
1466 };
1467
1468 struct flash_driver stellaris_flash = {
1469 .name = "stellaris",
1470 .commands = stellaris_command_handlers,
1471 .flash_bank_command = stellaris_flash_bank_command,
1472 .erase = stellaris_erase,
1473 .protect = stellaris_protect,
1474 .write = stellaris_write,
1475 .read = default_flash_read,
1476 .probe = stellaris_probe,
1477 .auto_probe = stellaris_probe,
1478 .erase_check = default_flash_mem_blank_check,
1479 .protect_check = stellaris_protect_check,
1480 .info = get_stellaris_info,
1481 };

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)