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

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)