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

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)