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

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)