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

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)