stellaris.c 29.6 KB
Newer Older
oharboe's avatar
oharboe committed
1
2
/***************************************************************************
 *   Copyright (C) 2006 by Magnus Lundin                                   *
oharboe's avatar
oharboe committed
3
4
 *   lundin@mlu.mine.nu                                                    *
 *                                                                         *
5
6
7
 *   Copyright (C) 2008 by Spencer Oliver                                  *
 *   spen@spen-soft.co.uk                                                  *
 *                                                                         *
oharboe's avatar
oharboe committed
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

/***************************************************************************
25
* STELLARIS is tested on LM3S811, LM3S6965
oharboe's avatar
oharboe committed
26
***************************************************************************/
oharboe's avatar
oharboe committed
27
28
29
30
31
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "stellaris.h"
32
#include "armv7m.h"
oharboe's avatar
oharboe committed
33
34
35
#include "binarybuffer.h"


zwelch's avatar
zwelch committed
36
#define DID0_VER(did0) ((did0 >> 28)&0x07)
mifi's avatar
mifi committed
37
38
39
40
static int stellaris_register_commands(struct command_context_s *cmd_ctx);
static int stellaris_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
static int stellaris_erase(struct flash_bank_s *bank, int first, int last);
static int stellaris_protect(struct flash_bank_s *bank, int set, int first, int last);
41
static int stellaris_write(struct flash_bank_s *bank, uint8_t *buffer, uint32_t offset, uint32_t count);
mifi's avatar
mifi committed
42
43
44
45
46
47
static int stellaris_auto_probe(struct flash_bank_s *bank);
static int stellaris_probe(struct flash_bank_s *bank);
static int stellaris_protect_check(struct flash_bank_s *bank);
static int stellaris_info(struct flash_bank_s *bank, char *buf, int buf_size);

static int stellaris_read_part_info(struct flash_bank_s *bank);
48
static uint32_t stellaris_get_flash_status(flash_bank_t *bank);
mifi's avatar
mifi committed
49
static void stellaris_set_flash_mode(flash_bank_t *bank,int mode);
50
//static uint32_t stellaris_wait_status_busy(flash_bank_t *bank, uint32_t waitbits, int timeout);
mifi's avatar
mifi committed
51
52
53

static int stellaris_handle_mass_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
static int stellaris_mass_erase(struct flash_bank_s *bank);
oharboe's avatar
oharboe committed
54
55
56
57
58
59
60
61
62
63
64

flash_driver_t stellaris_flash =
{
	.name = "stellaris",
	.register_commands = stellaris_register_commands,
	.flash_bank_command = stellaris_flash_bank_command,
	.erase = stellaris_erase,
	.protect = stellaris_protect,
	.write = stellaris_write,
	.probe = stellaris_probe,
	.auto_probe = stellaris_auto_probe,
65
	.erase_check = default_flash_mem_blank_check,
oharboe's avatar
oharboe committed
66
67
68
69
	.protect_check = stellaris_protect_check,
	.info = stellaris_info
};

mifi's avatar
mifi committed
70
static struct {
71
	uint32_t partno;
72
	char *partname;
oharboe's avatar
oharboe committed
73
74
75
76
}	StellarisParts[] =
{
	{0x01,"LM3S101"},
	{0x02,"LM3S102"},
77
78
79
80
81
	{0x03,"LM3S1625"},
	{0x04,"LM3S1626"},
	{0x05,"LM3S1627"},
	{0x06,"LM3S1607"},
	{0x10,"LM3S1776"},
oharboe's avatar
oharboe committed
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
	{0x19,"LM3S300"},
	{0x11,"LM3S301"},
	{0x12,"LM3S310"},
	{0x1A,"LM3S308"},
	{0x13,"LM3S315"},
	{0x14,"LM3S316"},
	{0x17,"LM3S317"},
	{0x18,"LM3S318"},
	{0x15,"LM3S328"},
	{0x2A,"LM3S600"},
	{0x21,"LM3S601"},
	{0x2B,"LM3S608"},
	{0x22,"LM3S610"},
	{0x23,"LM3S611"},
	{0x24,"LM3S612"},
	{0x25,"LM3S613"},
	{0x26,"LM3S615"},
	{0x28,"LM3S617"},
	{0x29,"LM3S618"},
	{0x27,"LM3S628"},
	{0x38,"LM3S800"},
	{0x31,"LM3S801"},
	{0x39,"LM3S808"},
	{0x32,"LM3S811"},
	{0x33,"LM3S812"},
107
	/*{0x33,"LM3S2616"},*/
oharboe's avatar
oharboe committed
108
109
110
111
	{0x34,"LM3S815"},
	{0x36,"LM3S817"},
	{0x37,"LM3S818"},
	{0x35,"LM3S828"},
112
113
114
115
116
117
118
119
120
	{0x39,"LM3S2276"},
	{0x3A,"LM3S2776"},
	{0x43,"LM3S3651"},
	{0x44,"LM3S3739"},
	{0x45,"LM3S3749"},
	{0x46,"LM3S3759"},
	{0x48,"LM3S3768"},
	{0x49,"LM3S3748"},
	{0x50,"LM3S2678"},
oharboe's avatar
oharboe committed
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
	{0x51,"LM3S2110"},
	{0x52,"LM3S2739"},
	{0x53,"LM3S2651"},
	{0x54,"LM3S2939"},
	{0x55,"LM3S2965"},
	{0x56,"LM3S2432"},
	{0x57,"LM3S2620"},
	{0x58,"LM3S2950"},
	{0x59,"LM3S2412"},
	{0x5A,"LM3S2533"},
	{0x61,"LM3S8630"},
	{0x62,"LM3S8970"},
	{0x63,"LM3S8730"},
	{0x64,"LM3S8530"},
	{0x65,"LM3S8930"},
	{0x71,"LM3S6610"},
	{0x72,"LM3S6950"},
	{0x73,"LM3S6965"},
	{0x74,"LM3S6110"},
	{0x75,"LM3S6432"},
	{0x76,"LM3S6537"},
	{0x77,"LM3S6753"},
	{0x78,"LM3S6952"},
144
145
	{0x80,"LM3S2671"},
	{0x81,"LM3S5632"},
oharboe's avatar
oharboe committed
146
147
148
149
150
151
152
	{0x82,"LM3S6422"},
	{0x83,"LM3S6633"},
	{0x84,"LM3S2139"},
	{0x85,"LM3S2637"},
	{0x86,"LM3S8738"},
	{0x88,"LM3S8938"},
	{0x89,"LM3S6938"},
153
	{0x8A,"LM3S5652"},
oharboe's avatar
oharboe committed
154
155
156
157
158
	{0x8B,"LM3S6637"},
	{0x8C,"LM3S8933"},
	{0x8D,"LM3S8733"},
	{0x8E,"LM3S8538"},
	{0x8F,"LM3S2948"},
159
160
161
162
163
164
165
166
167
	{0x91,"LM3S5662"},
	{0x96,"LM3S5732"},
	{0x97,"LM3S5737"},
	{0x99,"LM3S5747"},
	{0x9A,"LM3S5752"},
	{0x9B,"LM3S5757"},
	{0x9C,"LM3S5762"},
	{0x9D,"LM3S5767"},
	{0xA0,"LM3S5739"},
oharboe's avatar
oharboe committed
168
169
170
171
172
173
	{0xA1,"LM3S6100"},
	{0xA2,"LM3S2410"},
	{0xA3,"LM3S6730"},
	{0xA4,"LM3S2730"},
	{0xA5,"LM3S6420"},
	{0xA6,"LM3S8962"},
174
175
176
	{0xA7,"LM3S5749"},
	{0xA8,"LM3S5769"},
	{0xA9,"LM3S5768"},
oharboe's avatar
oharboe committed
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
	{0xB3,"LM3S1635"},
	{0xB4,"LM3S1850"},
	{0xB5,"LM3S1960"},
	{0xB7,"LM3S1937"},
	{0xB8,"LM3S1968"},
	{0xB9,"LM3S1751"},
	{0xBA,"LM3S1439"},
	{0xBB,"LM3S1512"},
	{0xBC,"LM3S1435"},
	{0xBD,"LM3S1637"},
	{0xBE,"LM3S1958"},
	{0xBF,"LM3S1110"},
	{0xC0,"LM3S1620"},
	{0xC1,"LM3S1150"},
	{0xC2,"LM3S1165"},
	{0xC3,"LM3S1133"},
	{0xC4,"LM3S1162"},
	{0xC5,"LM3S1138"},
	{0xC6,"LM3S1332"},
	{0xC7,"LM3S1538"},
	{0xD0,"LM3S6815"},
	{0xD1,"LM3S6816"},
	{0xD2,"LM3S6915"},
	{0xD3,"LM3S6916"},
	{0xD4,"LM3S2016"},
	{0xD5,"LM3S1615"},
	{0xD6,"LM3S1616"},
	{0xD7,"LM3S8971"},
	{0xD8,"LM3S1108"},
	{0xD9,"LM3S1101"},
	{0xDA,"LM3S1608"},
	{0xDB,"LM3S1601"},
	{0xDC,"LM3S1918"},
	{0xDD,"LM3S1911"},
	{0xDE,"LM3S2108"},
	{0xDF,"LM3S2101"},
	{0xE0,"LM3S2608"},
	{0xE1,"LM3S2601"},
	{0xE2,"LM3S2918"},
	{0xE3,"LM3S2911"},
	{0xE4,"LM3S6118"},
	{0xE5,"LM3S6111"},
	{0xE6,"LM3S6618"},
	{0xE7,"LM3S6611"},
	{0xE8,"LM3S6918"},
	{0xE9,"LM3S6911"},
	{0,"Unknown part"}
};

mifi's avatar
mifi committed
226
static char * StellarisClassname[5] =
oharboe's avatar
oharboe committed
227
228
{
	"Sandstorm",
229
230
231
232
	"Fury",
	"Unknown",
	"DustDevil",
	"Tempest"
oharboe's avatar
oharboe committed
233
234
235
236
237
238
239
240
};

/***************************************************************************
*	openocd command interface                                              *
***************************************************************************/

/* flash_bank stellaris <base> <size> 0 0 <target#>
 */
mifi's avatar
mifi committed
241
static int stellaris_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
oharboe's avatar
oharboe committed
242
243
{
	stellaris_flash_bank_t *stellaris_info;
zwelch's avatar
zwelch committed
244

oharboe's avatar
oharboe committed
245
246
	if (argc < 6)
	{
247
		LOG_WARNING("incomplete flash_bank stellaris configuration");
oharboe's avatar
oharboe committed
248
249
		return ERROR_FLASH_BANK_INVALID;
	}
zwelch's avatar
zwelch committed
250

251
	stellaris_info = calloc(sizeof(stellaris_flash_bank_t), 1);
oharboe's avatar
oharboe committed
252
253
	bank->base = 0x0;
	bank->driver_priv = stellaris_info;
zwelch's avatar
zwelch committed
254

oharboe's avatar
oharboe committed
255
	stellaris_info->target_name = "Unknown target";
zwelch's avatar
zwelch committed
256

oharboe's avatar
oharboe committed
257
258
	/* part wasn't probed for info yet */
	stellaris_info->did1 = 0;
zwelch's avatar
zwelch committed
259
260

	/* TODO Use an optional main oscillator clock rate in kHz from arg[6] */
oharboe's avatar
oharboe committed
261
262
263
	return ERROR_OK;
}

mifi's avatar
mifi committed
264
static int stellaris_register_commands(struct command_context_s *cmd_ctx)
oharboe's avatar
oharboe committed
265
{
266
	command_t *stm32x_cmd = register_command(cmd_ctx, NULL, "stellaris", NULL, COMMAND_ANY, "stellaris flash specific commands");
zwelch's avatar
zwelch committed
267

268
	register_command(cmd_ctx, stm32x_cmd, "mass_erase", stellaris_handle_mass_erase_command, COMMAND_EXEC, "mass erase device");
oharboe's avatar
oharboe committed
269
270
271
	return ERROR_OK;
}

mifi's avatar
mifi committed
272
static int stellaris_info(struct flash_bank_s *bank, char *buf, int buf_size)
oharboe's avatar
oharboe committed
273
274
275
{
	int printed, device_class;
	stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
zwelch's avatar
zwelch committed
276

oharboe's avatar
oharboe committed
277
278
279
280
281
282
283
284
285
	stellaris_read_part_info(bank);

	if (stellaris_info->did1 == 0)
	{
		printed = snprintf(buf, buf_size, "Cannot identify target as a Stellaris\n");
		buf += printed;
		buf_size -= printed;
		return ERROR_FLASH_OPERATION_FAILED;
	}
zwelch's avatar
zwelch committed
286

287
	if (DID0_VER(stellaris_info->did0) > 0)
oharboe's avatar
oharboe committed
288
	{
zwelch's avatar
zwelch committed
289
		device_class = (stellaris_info->did0 >> 16) & 0xFF;
oharboe's avatar
oharboe committed
290
291
292
293
	}
	else
	{
		device_class = 0;
zwelch's avatar
zwelch committed
294
	}
duane's avatar
duane committed
295
296
297
298
299
300
	printed = snprintf(buf, 
			   buf_size,
			   "\nLMI Stellaris information: Chip is class %i(%s) %s v%c.%i\n",
			   device_class, 
			   StellarisClassname[device_class], 
			   stellaris_info->target_name,
zwelch's avatar
zwelch committed
301
			   (int)('A' + ((stellaris_info->did0 >> 8) & 0xFF)),
duane's avatar
duane committed
302
			   (int)((stellaris_info->did0) & 0xFF));
oharboe's avatar
oharboe committed
303
304
305
	buf += printed;
	buf_size -= printed;

duane's avatar
duane committed
306
307
308
309
310
311
	printed = snprintf(buf, 
			   buf_size, 
			   "did1: 0x%8.8" PRIx32 ", arch: 0x%4.4" PRIx32 ", eproc: %s, ramsize:%ik, flashsize: %ik\n",
			   stellaris_info->did1, 
			   stellaris_info->did1, 
			   "ARMV7M", 
zwelch's avatar
zwelch committed
312
313
			   (int)((1 + ((stellaris_info->dc0 >> 16) & 0xFFFF))/4),
			   (int)((1 + (stellaris_info->dc0 & 0xFFFF))*2));
oharboe's avatar
oharboe committed
314
315
316
	buf += printed;
	buf_size -= printed;

duane's avatar
duane committed
317
318
319
320
321
	printed = snprintf(buf, 
			   buf_size,
			   "master clock(estimated): %ikHz, rcc is 0x%" PRIx32 " \n",
			   (int)(stellaris_info->mck_freq / 1000), 
			   stellaris_info->rcc);
oharboe's avatar
oharboe committed
322
323
324
	buf += printed;
	buf_size -= printed;

325
326
	if (stellaris_info->num_lockbits>0)
	{
duane's avatar
duane committed
327
328
329
330
331
332
333
		printed = snprintf(buf,
				   buf_size,
				   "pagesize: %" PRIi32 ", lockbits: %i 0x%4.4" PRIx32 ", pages in lock region: %i \n", 
				   stellaris_info->pagesize, 
				   stellaris_info->num_lockbits, 
				   stellaris_info->lockbits,
				   (int)(stellaris_info->num_pages/stellaris_info->num_lockbits));
oharboe's avatar
oharboe committed
334
335
336
337
338
339
340
341
342
343
		buf += printed;
		buf_size -= printed;
	}
	return ERROR_OK;
}

/***************************************************************************
*	chip identification and status                                         *
***************************************************************************/

344
static uint32_t stellaris_get_flash_status(flash_bank_t *bank)
oharboe's avatar
oharboe committed
345
346
{
	target_t *target = bank->target;
347
	uint32_t fmc;
zwelch's avatar
zwelch committed
348

zwelch's avatar
zwelch committed
349
	target_read_u32(target, FLASH_CONTROL_BASE | FLASH_FMC, &fmc);
zwelch's avatar
zwelch committed
350

oharboe's avatar
oharboe committed
351
352
353
354
	return fmc;
}

/** Read clock configuration and set stellaris_info->usec_clocks*/
zwelch's avatar
zwelch committed
355

mifi's avatar
mifi committed
356
static void stellaris_read_clock_info(flash_bank_t *bank)
oharboe's avatar
oharboe committed
357
358
359
{
	stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
	target_t *target = bank->target;
360
	uint32_t rcc, pllcfg, sysdiv, usesysdiv, bypass, oscsrc;
oharboe's avatar
oharboe committed
361
362
	unsigned long mainfreq;

zwelch's avatar
zwelch committed
363
	target_read_u32(target, SCB_BASE | RCC, &rcc);
duane's avatar
duane committed
364
	LOG_DEBUG("Stellaris RCC %" PRIx32 "", rcc);
zwelch's avatar
zwelch committed
365
	target_read_u32(target, SCB_BASE | PLLCFG, &pllcfg);
duane's avatar
duane committed
366
	LOG_DEBUG("Stellaris PLLCFG %" PRIx32 "", pllcfg);
oharboe's avatar
oharboe committed
367
	stellaris_info->rcc = rcc;
zwelch's avatar
zwelch committed
368

zwelch's avatar
zwelch committed
369
370
371
372
373
	sysdiv = (rcc >> 23) & 0xF;
	usesysdiv = (rcc >> 22) & 0x1;
	bypass = (rcc >> 11) & 0x1;
	oscsrc = (rcc >> 4) & 0x3;
	/* xtal = (rcc >> 6)&0xF; */
oharboe's avatar
oharboe committed
374
375
376
377
378
379
380
381
382
383
384
385
	switch (oscsrc)
	{
		case 0:
			mainfreq = 6000000;  /* Default xtal */
			break;
		case 1:
			mainfreq = 22500000; /* Internal osc. 15 MHz +- 50% */
			break;
		case 2:
			mainfreq = 5625000;  /* Internal osc. / 4 */
			break;
		case 3:
386
			LOG_WARNING("Invalid oscsrc (3) in rcc register");
oharboe's avatar
oharboe committed
387
388
			mainfreq = 6000000;
			break;
oharboe's avatar
oharboe committed
389
390
391
392

		default: /* NOTREACHED */
			mainfreq = 0;
			break;
oharboe's avatar
oharboe committed
393
	}
zwelch's avatar
zwelch committed
394

oharboe's avatar
oharboe committed
395
396
	if (!bypass)
		mainfreq = 200000000; /* PLL out frec */
zwelch's avatar
zwelch committed
397

oharboe's avatar
oharboe committed
398
	if (usesysdiv)
zwelch's avatar
zwelch committed
399
		stellaris_info->mck_freq = mainfreq/(1 + sysdiv);
oharboe's avatar
oharboe committed
400
401
	else
		stellaris_info->mck_freq = mainfreq;
zwelch's avatar
zwelch committed
402

oharboe's avatar
oharboe committed
403
	/* Forget old flash timing */
404
	stellaris_set_flash_mode(bank, 0);
oharboe's avatar
oharboe committed
405
406
407
}

/* Setup the timimg registers */
mifi's avatar
mifi committed
408
static void stellaris_set_flash_mode(flash_bank_t *bank,int mode)
oharboe's avatar
oharboe committed
409
410
411
412
{
	stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
	target_t *target = bank->target;

413
	uint32_t usecrl = (stellaris_info->mck_freq/1000000ul-1);
duane's avatar
duane committed
414
	LOG_DEBUG("usecrl = %i",(int)(usecrl));
zwelch's avatar
zwelch committed
415
	target_write_u32(target, SCB_BASE | USECRL, usecrl);
oharboe's avatar
oharboe committed
416
417
}

mifi's avatar
mifi committed
418
#if 0
419
static uint32_t stellaris_wait_status_busy(flash_bank_t *bank, uint32_t waitbits, int timeout)
oharboe's avatar
oharboe committed
420
{
421
	uint32_t status;
zwelch's avatar
zwelch committed
422

oharboe's avatar
oharboe committed
423
424
425
	/* Stellaris waits for cmdbit to clear */
	while (((status = stellaris_get_flash_status(bank)) & waitbits) && (timeout-- > 0))
	{
426
		LOG_DEBUG("status: 0x%x", status);
427
		alive_sleep(1);
oharboe's avatar
oharboe committed
428
	}
zwelch's avatar
zwelch committed
429

oharboe's avatar
oharboe committed
430
431
432
433
434
435
	/* Flash errors are reflected in the FLASH_CRIS register */

	return status;
}

/* Send one command to the flash controller */
zwelch's avatar
zwelch committed
436
static int stellaris_flash_command(struct flash_bank_s *bank,uint8_t cmd,uint16_t pagen)
oharboe's avatar
oharboe committed
437
{
438
	uint32_t fmc;
oharboe's avatar
oharboe committed
439
440
	target_t *target = bank->target;

zwelch's avatar
zwelch committed
441
	fmc = FMC_WRKEY | cmd;
zwelch's avatar
zwelch committed
442
	target_write_u32(target, FLASH_CONTROL_BASE | FLASH_FMC, fmc);
443
	LOG_DEBUG("Flash command: 0x%x", fmc);
oharboe's avatar
oharboe committed
444

zwelch's avatar
zwelch committed
445
	if (stellaris_wait_status_busy(bank, cmd, 100))
oharboe's avatar
oharboe committed
446
447
	{
		return ERROR_FLASH_OPERATION_FAILED;
zwelch's avatar
zwelch committed
448
	}
oharboe's avatar
oharboe committed
449
450
451

	return ERROR_OK;
}
mifi's avatar
mifi committed
452
#endif
oharboe's avatar
oharboe committed
453
454

/* Read device id register, main clock frequency register and fill in driver info structure */
mifi's avatar
mifi committed
455
static int stellaris_read_part_info(struct flash_bank_s *bank)
oharboe's avatar
oharboe committed
456
457
458
{
	stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
	target_t *target = bank->target;
459
	uint32_t did0, did1, ver, fam, status;
oharboe's avatar
oharboe committed
460
	int i;
zwelch's avatar
zwelch committed
461

oharboe's avatar
oharboe committed
462
	/* Read and parse chip identification register */
zwelch's avatar
zwelch committed
463
464
465
466
	target_read_u32(target, SCB_BASE | DID0, &did0);
	target_read_u32(target, SCB_BASE | DID1, &did1);
	target_read_u32(target, SCB_BASE | DC0, &stellaris_info->dc0);
	target_read_u32(target, SCB_BASE | DC1, &stellaris_info->dc1);
duane's avatar
duane committed
467
468
	LOG_DEBUG("did0 0x%" PRIx32 ", did1 0x%" PRIx32 ", dc0 0x%" PRIx32 ", dc1 0x%" PRIx32 "",
		  did0, did1, stellaris_info->dc0, stellaris_info->dc1);
oharboe's avatar
oharboe committed
469

470
	ver = did0 >> 28;
zwelch's avatar
zwelch committed
471
	if ((ver != 0) && (ver != 1))
oharboe's avatar
oharboe committed
472
	{
473
		LOG_WARNING("Unknown did0 version, cannot identify target");
ntfreak's avatar
ntfreak committed
474
		return ERROR_FLASH_OPERATION_FAILED;
oharboe's avatar
oharboe committed
475
476
	}

477
478
	if (did1 == 0)
	{
479
		LOG_WARNING("Cannot identify target as a Stellaris");
480
481
482
		return ERROR_FLASH_OPERATION_FAILED;
	}

483
484
	ver = did1 >> 28;
	fam = (did1 >> 24) & 0xF;
zwelch's avatar
zwelch committed
485
	if (((ver != 0) && (ver != 1)) || (fam != 0))
oharboe's avatar
oharboe committed
486
	{
487
		LOG_WARNING("Unknown did1 version/family, cannot positively identify target as a Stellaris");
oharboe's avatar
oharboe committed
488
489
	}

490
	for (i = 0; StellarisParts[i].partno; i++)
oharboe's avatar
oharboe committed
491
	{
492
		if (StellarisParts[i].partno == ((did1 >> 16) & 0xFF))
oharboe's avatar
oharboe committed
493
494
			break;
	}
zwelch's avatar
zwelch committed
495

oharboe's avatar
oharboe committed
496
	stellaris_info->target_name = StellarisParts[i].partname;
zwelch's avatar
zwelch committed
497

oharboe's avatar
oharboe committed
498
499
500
	stellaris_info->did0 = did0;
	stellaris_info->did1 = did1;

501
	stellaris_info->num_lockbits = 1 + (stellaris_info->dc0 & 0xFFFF);
zwelch's avatar
zwelch committed
502
	stellaris_info->num_pages = 2 *(1 + (stellaris_info->dc0 & 0xFFFF));
oharboe's avatar
oharboe committed
503
	stellaris_info->pagesize = 1024;
504
	bank->size = 1024 * stellaris_info->num_pages;
oharboe's avatar
oharboe committed
505
	stellaris_info->pages_in_lockregion = 2;
zwelch's avatar
zwelch committed
506
	target_read_u32(target, SCB_BASE | FMPPE, &stellaris_info->lockbits);
oharboe's avatar
oharboe committed
507

508
509
510
511
512
	/* provide this for the benefit of the higher flash driver layers */
	bank->num_sectors = stellaris_info->num_pages;
	bank->sectors = malloc(sizeof(flash_sector_t) * bank->num_sectors);
	for (i = 0; i < bank->num_sectors; i++)
	{
513
		bank->sectors[i].offset = i * stellaris_info->pagesize;
514
515
516
517
518
		bank->sectors[i].size = stellaris_info->pagesize;
		bank->sectors[i].is_erased = -1;
		bank->sectors[i].is_protected = -1;
	}

519
	/* Read main and master clock freqency register */
oharboe's avatar
oharboe committed
520
	stellaris_read_clock_info(bank);
zwelch's avatar
zwelch committed
521

oharboe's avatar
oharboe committed
522
	status = stellaris_get_flash_status(bank);
zwelch's avatar
zwelch committed
523

oharboe's avatar
oharboe committed
524
525
526
527
	return ERROR_OK;
}

/***************************************************************************
528
*	flash operations                                                       *
oharboe's avatar
oharboe committed
529
530
***************************************************************************/

mifi's avatar
mifi committed
531
static int stellaris_protect_check(struct flash_bank_s *bank)
oharboe's avatar
oharboe committed
532
{
533
	uint32_t status;
zwelch's avatar
zwelch committed
534

oharboe's avatar
oharboe committed
535
536
	stellaris_flash_bank_t *stellaris_info = bank->driver_priv;

537
538
	if (bank->target->state != TARGET_HALTED)
	{
oharboe's avatar
oharboe committed
539
		LOG_ERROR("Target not halted");
540
541
542
		return ERROR_TARGET_NOT_HALTED;
	}

oharboe's avatar
oharboe committed
543
544
545
546
547
548
549
	if (stellaris_info->did1 == 0)
	{
		stellaris_read_part_info(bank);
	}

	if (stellaris_info->did1 == 0)
	{
550
		LOG_WARNING("Cannot identify target as an AT91SAM");
oharboe's avatar
oharboe committed
551
552
		return ERROR_FLASH_OPERATION_FAILED;
	}
zwelch's avatar
zwelch committed
553

oharboe's avatar
oharboe committed
554
555
	status = stellaris_get_flash_status(bank);
	stellaris_info->lockbits = status >> 16;
zwelch's avatar
zwelch committed
556

oharboe's avatar
oharboe committed
557
558
559
	return ERROR_OK;
}

mifi's avatar
mifi committed
560
static int stellaris_erase(struct flash_bank_s *bank, int first, int last)
oharboe's avatar
oharboe committed
561
562
{
	int banknr;
563
	uint32_t flash_fmc, flash_cris;
oharboe's avatar
oharboe committed
564
565
	stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
	target_t *target = bank->target;
zwelch's avatar
zwelch committed
566

567
568
	if (bank->target->state != TARGET_HALTED)
	{
oharboe's avatar
oharboe committed
569
		LOG_ERROR("Target not halted");
570
571
572
		return ERROR_TARGET_NOT_HALTED;
	}

oharboe's avatar
oharboe committed
573
574
575
576
577
578
579
	if (stellaris_info->did1 == 0)
	{
		stellaris_read_part_info(bank);
	}

	if (stellaris_info->did1 == 0)
	{
580
		LOG_WARNING("Cannot identify target as Stellaris");
oharboe's avatar
oharboe committed
581
		return ERROR_FLASH_OPERATION_FAILED;
zwelch's avatar
zwelch committed
582
583
	}

584
	if ((first < 0) || (last < first) || (last >= (int)stellaris_info->num_pages))
oharboe's avatar
oharboe committed
585
586
587
	{
		return ERROR_FLASH_SECTOR_INVALID;
	}
zwelch's avatar
zwelch committed
588

589
	if ((first == 0) && (last == ((int)stellaris_info->num_pages-1)))
590
591
592
	{
		return stellaris_mass_erase(bank);
	}
zwelch's avatar
zwelch committed
593

oharboe's avatar
oharboe committed
594
	/* Configure the flash controller timing */
zwelch's avatar
zwelch committed
595
	stellaris_read_clock_info(bank);
oharboe's avatar
oharboe committed
596
597
598
599
	stellaris_set_flash_mode(bank,0);

	/* Clear and disable flash programming interrupts */
	target_write_u32(target, FLASH_CIM, 0);
zwelch's avatar
zwelch committed
600
	target_write_u32(target, FLASH_MISC, PMISC | AMISC);
zwelch's avatar
zwelch committed
601

602
	for (banknr = first; banknr <= last; banknr++)
oharboe's avatar
oharboe committed
603
604
	{
		/* Address is first word in page */
605
		target_write_u32(target, FLASH_FMA, banknr * stellaris_info->pagesize);
oharboe's avatar
oharboe committed
606
607
608
609
610
611
612
		/* Write erase command */
		target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_ERASE);
		/* Wait until erase complete */
		do
		{
			target_read_u32(target, FLASH_FMC, &flash_fmc);
		}
zwelch's avatar
zwelch committed
613
		while (flash_fmc & FMC_ERASE);
oharboe's avatar
oharboe committed
614
615
616

		/* Check acess violations */
		target_read_u32(target, FLASH_CRIS, &flash_cris);
zwelch's avatar
zwelch committed
617
		if (flash_cris & (AMASK))
oharboe's avatar
oharboe committed
618
		{
duane's avatar
duane committed
619
			LOG_WARNING("Error erasing flash page %i,  flash_cris 0x%" PRIx32 "", banknr, flash_cris);
oharboe's avatar
oharboe committed
620
621
622
			target_write_u32(target, FLASH_CRIS, 0);
			return ERROR_FLASH_OPERATION_FAILED;
		}
zwelch's avatar
zwelch committed
623

ntfreak's avatar
ntfreak committed
624
		bank->sectors[banknr].is_erased = 1;
oharboe's avatar
oharboe committed
625
626
627
628
629
	}

	return ERROR_OK;
}

mifi's avatar
mifi committed
630
static int stellaris_protect(struct flash_bank_s *bank, int set, int first, int last)
oharboe's avatar
oharboe committed
631
{
632
	uint32_t fmppe, flash_fmc, flash_cris;
oharboe's avatar
oharboe committed
633
	int lockregion;
zwelch's avatar
zwelch committed
634

oharboe's avatar
oharboe committed
635
636
	stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
	target_t *target = bank->target;
zwelch's avatar
zwelch committed
637

oharboe's avatar
oharboe committed
638
639
	if (bank->target->state != TARGET_HALTED)
	{
oharboe's avatar
oharboe committed
640
		LOG_ERROR("Target not halted");
oharboe's avatar
oharboe committed
641
642
		return ERROR_TARGET_NOT_HALTED;
	}
zwelch's avatar
zwelch committed
643

oharboe's avatar
oharboe committed
644
645
646
647
	if ((first < 0) || (last < first) || (last >= stellaris_info->num_lockbits))
	{
		return ERROR_FLASH_SECTOR_INVALID;
	}
zwelch's avatar
zwelch committed
648

oharboe's avatar
oharboe committed
649
650
651
652
653
654
655
	if (stellaris_info->did1 == 0)
	{
		stellaris_read_part_info(bank);
	}

	if (stellaris_info->did1 == 0)
	{
656
		LOG_WARNING("Cannot identify target as an Stellaris MCU");
oharboe's avatar
oharboe committed
657
658
		return ERROR_FLASH_OPERATION_FAILED;
	}
zwelch's avatar
zwelch committed
659

oharboe's avatar
oharboe committed
660
	/* Configure the flash controller timing */
ntfreak's avatar
ntfreak committed
661
	stellaris_read_clock_info(bank);
662
	stellaris_set_flash_mode(bank, 0);
oharboe's avatar
oharboe committed
663

ntfreak's avatar
ntfreak committed
664
	fmppe = stellaris_info->lockbits;
665
	for (lockregion = first; lockregion <= last; lockregion++)
oharboe's avatar
oharboe committed
666
667
	{
		if (set)
zwelch's avatar
zwelch committed
668
			fmppe &= ~(1 << lockregion);
oharboe's avatar
oharboe committed
669
		else
zwelch's avatar
zwelch committed
670
			fmppe |= (1 << lockregion);
oharboe's avatar
oharboe committed
671
672
673
674
	}

	/* Clear and disable flash programming interrupts */
	target_write_u32(target, FLASH_CIM, 0);
zwelch's avatar
zwelch committed
675
	target_write_u32(target, FLASH_MISC, PMISC | AMISC);
zwelch's avatar
zwelch committed
676

duane's avatar
duane committed
677
	LOG_DEBUG("fmppe 0x%" PRIx32 "",fmppe);
zwelch's avatar
zwelch committed
678
	target_write_u32(target, SCB_BASE | FMPPE, fmppe);
oharboe's avatar
oharboe committed
679
680
681
682
	/* Commit FMPPE */
	target_write_u32(target, FLASH_FMA, 1);
	/* Write commit command */
	/* TODO safety check, sice this cannot be undone */
683
	LOG_WARNING("Flash protection cannot be removed once commited, commit is NOT executed !");
oharboe's avatar
oharboe committed
684
685
686
687
688
689
	/* target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_COMT); */
	/* Wait until erase complete */
	do
	{
		target_read_u32(target, FLASH_FMC, &flash_fmc);
	}
zwelch's avatar
zwelch committed
690
	while (flash_fmc & FMC_COMT);
oharboe's avatar
oharboe committed
691
692
693

	/* Check acess violations */
	target_read_u32(target, FLASH_CRIS, &flash_cris);
zwelch's avatar
zwelch committed
694
	if (flash_cris & (AMASK))
oharboe's avatar
oharboe committed
695
	{
duane's avatar
duane committed
696
		LOG_WARNING("Error setting flash page protection,  flash_cris 0x%" PRIx32 "", flash_cris);
oharboe's avatar
oharboe committed
697
698
699
		target_write_u32(target, FLASH_CRIS, 0);
		return ERROR_FLASH_OPERATION_FAILED;
	}
zwelch's avatar
zwelch committed
700

zwelch's avatar
zwelch committed
701
	target_read_u32(target, SCB_BASE | FMPPE, &stellaris_info->lockbits);
zwelch's avatar
zwelch committed
702

oharboe's avatar
oharboe committed
703
704
705
	return ERROR_OK;
}

706
static uint8_t stellaris_write_code[] =
oharboe's avatar
oharboe committed
707
{
zwelch's avatar
zwelch committed
708
709
/*
	Call with :
oharboe's avatar
oharboe committed
710
711
	r0 = buffer address
	r1 = destination address
zwelch's avatar
zwelch committed
712
713
714
	r2 = bytecount (in) - endaddr (work)

	Used registers:
oharboe's avatar
oharboe committed
715
716
717
718
719
720
	r3 = pFLASH_CTRL_BASE
	r4 = FLASHWRITECMD
	r5 = #1
	r6 = bytes written
	r7 = temp reg
*/
721
722
723
724
	0x07,0x4B,			/* ldr r3,pFLASH_CTRL_BASE */
	0x08,0x4C,			/* ldr r4,FLASHWRITECMD */
	0x01,0x25,			/* movs r5, 1 */
	0x00,0x26,			/* movs r6, #0 */
oharboe's avatar
oharboe committed
725
/* mainloop: */
726
727
728
729
	0x19,0x60,			/* str	r1, [r3, #0] */
	0x87,0x59,			/* ldr	r7, [r0, r6] */
	0x5F,0x60,			/* str	r7, [r3, #4] */
	0x9C,0x60,			/* str	r4, [r3, #8] */
oharboe's avatar
oharboe committed
730
/* waitloop: */
731
732
733
734
735
736
737
	0x9F,0x68,			/* ldr	r7, [r3, #8] */
	0x2F,0x42,			/* tst	r7, r5 */
	0xFC,0xD1,			/* bne	waitloop */
	0x04,0x31,			/* adds	r1, r1, #4 */
	0x04,0x36,			/* adds	r6, r6, #4 */
	0x96,0x42,			/* cmp	r6, r2 */
	0xF4,0xD1,			/* bne	mainloop */
738
739
						/* exit: */
	0xFE,0xE7,			/* b exit */
oharboe's avatar
oharboe committed
740
/* pFLASH_CTRL_BASE: */
741
	0x00,0xD0,0x0F,0x40,	/* .word	0x400FD000 */
oharboe's avatar
oharboe committed
742
743
744
745
/* FLASHWRITECMD: */
	0x01,0x00,0x42,0xA4 	/* .word	0xA4420001 */
};

746
static int stellaris_write_block(struct flash_bank_s *bank, uint8_t *buffer, uint32_t offset, uint32_t wcount)
oharboe's avatar
oharboe committed
747
748
{
	target_t *target = bank->target;
749
	uint32_t buffer_size = 8192;
oharboe's avatar
oharboe committed
750
751
	working_area_t *source;
	working_area_t *write_algorithm;
752
	uint32_t address = bank->base + offset;
753
	reg_param_t reg_params[3];
oharboe's avatar
oharboe committed
754
	armv7m_algorithm_t armv7m_info;
755
	int retval = ERROR_OK;
zwelch's avatar
zwelch committed
756

duane's avatar
duane committed
757
	LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32 " wcount=%08" PRIx32 "",
oharboe's avatar
oharboe committed
758
			bank, buffer, offset, wcount);
oharboe's avatar
oharboe committed
759
760
761

	/* flash write code */
	if (target_alloc_working_area(target, sizeof(stellaris_write_code), &write_algorithm) != ERROR_OK)
762
763
764
765
	{
		LOG_WARNING("no working area available, can't do block memory writes");
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	};
oharboe's avatar
oharboe committed
766
767
768
769
770
771

	target_write_buffer(target, write_algorithm->address, sizeof(stellaris_write_code), stellaris_write_code);

	/* memory buffer */
	while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
	{
duane's avatar
duane committed
772
		LOG_DEBUG("called target_alloc_working_area(target=%p buffer_size=%08" PRIx32 " source=%p)",
zwelch's avatar
zwelch committed
773
				target, buffer_size, source);
oharboe's avatar
oharboe committed
774
775
776
777
778
779
		buffer_size /= 2;
		if (buffer_size <= 256)
		{
			/* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
			if (write_algorithm)
				target_free_working_area(target, write_algorithm);
zwelch's avatar
zwelch committed
780

781
			LOG_WARNING("no large enough working area available, can't do block memory writes");
oharboe's avatar
oharboe committed
782
783
784
			return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
		}
	};
zwelch's avatar
zwelch committed
785

oharboe's avatar
oharboe committed
786
787
	armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
	armv7m_info.core_mode = ARMV7M_MODE_ANY;
zwelch's avatar
zwelch committed
788

oharboe's avatar
oharboe committed
789
790
791
	init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
	init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
	init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
zwelch's avatar
zwelch committed
792

oharboe's avatar
oharboe committed
793
794
	while (wcount > 0)
	{
795
		uint32_t thisrun_count = (wcount > (buffer_size / 4)) ? (buffer_size / 4) : wcount;
zwelch's avatar
zwelch committed
796

oharboe's avatar
oharboe committed
797
		target_write_buffer(target, source->address, thisrun_count * 4, buffer);
zwelch's avatar
zwelch committed
798

oharboe's avatar
oharboe committed
799
800
801
		buf_set_u32(reg_params[0].value, 0, 32, source->address);
		buf_set_u32(reg_params[1].value, 0, 32, address);
		buf_set_u32(reg_params[2].value, 0, 32, 4*thisrun_count);
duane's avatar
duane committed
802
803
		LOG_INFO("Algorithm flash write %" PRIi32 " words to 0x%" PRIx32 ", %" PRIi32 " remaining", thisrun_count, address, wcount);
		LOG_DEBUG("Algorithm flash write %" PRIi32 " words to 0x%" PRIx32 ", %" PRIi32 " remaining", thisrun_count, address, wcount);
zwelch's avatar
zwelch committed
804
		if ((retval = target_run_algorithm(target, 0, NULL, 3, reg_params, write_algorithm->address, write_algorithm->address + sizeof(stellaris_write_code)-10, 10000, &armv7m_info)) != ERROR_OK)
oharboe's avatar
oharboe committed
805
		{
806
			LOG_ERROR("error executing stellaris flash write algorithm");
807
808
			retval = ERROR_FLASH_OPERATION_FAILED;
			break;
oharboe's avatar
oharboe committed
809
		}
zwelch's avatar
zwelch committed
810

oharboe's avatar
oharboe committed
811
812
813
814
		buffer += thisrun_count * 4;
		address += thisrun_count * 4;
		wcount -= thisrun_count;
	}
zwelch's avatar
zwelch committed
815

oharboe's avatar
oharboe committed
816
817
	target_free_working_area(target, write_algorithm);
	target_free_working_area(target, source);
zwelch's avatar
zwelch committed
818

oharboe's avatar
oharboe committed
819
820
821
	destroy_reg_param(&reg_params[0]);
	destroy_reg_param(&reg_params[1]);
	destroy_reg_param(&reg_params[2]);
zwelch's avatar
zwelch committed
822

823
	return retval;
oharboe's avatar
oharboe committed
824
825
}

826
static int stellaris_write(struct flash_bank_s *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
oharboe's avatar
oharboe committed
827
828
829
{
	stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
	target_t *target = bank->target;
830
831
832
833
834
	uint32_t address = offset;
	uint32_t flash_cris, flash_fmc;
	uint32_t words_remaining = (count / 4);
	uint32_t bytes_remaining = (count & 0x00000003);
	uint32_t bytes_written = 0;
835
	int retval;
zwelch's avatar
zwelch committed
836

837
838
	if (bank->target->state != TARGET_HALTED)
	{
oharboe's avatar
oharboe committed
839
		LOG_ERROR("Target not halted");
840
841
842
		return ERROR_TARGET_NOT_HALTED;
	}

duane's avatar
duane committed
843
	LOG_DEBUG("(bank=%p buffer=%p offset=%08" PRIx32 " count=%08" PRIx32 "",
oharboe's avatar
oharboe committed
844
			bank, buffer, offset, count);
oharboe's avatar
oharboe committed
845
846
847
848
849
850
851
852

	if (stellaris_info->did1 == 0)
	{
		stellaris_read_part_info(bank);
	}

	if (stellaris_info->did1 == 0)
	{
853
		LOG_WARNING("Cannot identify target as a Stellaris processor");
oharboe's avatar
oharboe committed
854
855
		return ERROR_FLASH_OPERATION_FAILED;
	}
zwelch's avatar
zwelch committed
856

857
	if (offset & 0x3)
oharboe's avatar
oharboe committed
858
	{
859
		LOG_WARNING("offset size must be word aligned");
oharboe's avatar
oharboe committed
860
861
		return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
	}
zwelch's avatar
zwelch committed
862

oharboe's avatar
oharboe committed
863
864
865
	if (offset + count > bank->size)
		return ERROR_FLASH_DST_OUT_OF_BANK;

zwelch's avatar
zwelch committed
866
867
	/* Configure the flash controller timing */
	stellaris_read_clock_info(bank);
868
	stellaris_set_flash_mode(bank, 0);
zwelch's avatar
zwelch committed
869

oharboe's avatar
oharboe committed
870
871
	/* Clear and disable flash programming interrupts */
	target_write_u32(target, FLASH_CIM, 0);
zwelch's avatar
zwelch committed
872
	target_write_u32(target, FLASH_MISC, PMISC | AMISC);
oharboe's avatar
oharboe committed
873
874

	/* multiple words to be programmed? */
zwelch's avatar
zwelch committed
875
	if (words_remaining > 0)
oharboe's avatar
oharboe committed
876
877
	{
		/* try using a block write */
878
		if ((retval = stellaris_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK)
oharboe's avatar
oharboe committed
879
880
881
882
		{
			if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
			{
				/* if block write failed (no sufficient working area),
zwelch's avatar
zwelch committed
883
				 * we use normal (slow) single dword accesses */
884
				LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
oharboe's avatar
oharboe committed
885
886
887
888
889
			}
			else if (retval == ERROR_FLASH_OPERATION_FAILED)
			{
				/* if an error occured, we examine the reason, and quit */
				target_read_u32(target, FLASH_CRIS, &flash_cris);
zwelch's avatar
zwelch committed
890

duane's avatar
duane committed
891
				LOG_ERROR("flash writing failed with CRIS: 0x%" PRIx32 "", flash_cris);
oharboe's avatar
oharboe committed
892
893
894
895
896
				return ERROR_FLASH_OPERATION_FAILED;
			}
		}
		else
		{
897
898
899
			buffer += words_remaining * 4;
			address += words_remaining * 4;
			words_remaining = 0;
oharboe's avatar
oharboe committed
900
901
		}
	}
zwelch's avatar
zwelch committed
902

903
	while (words_remaining > 0)
oharboe's avatar
oharboe committed
904
	{
905
		if (!(address & 0xff))
duane's avatar
duane committed
906
			LOG_DEBUG("0x%" PRIx32 "", address);
zwelch's avatar
zwelch committed
907

oharboe's avatar
oharboe committed
908
909
910
911
		/* Program one word */
		target_write_u32(target, FLASH_FMA, address);
		target_write_buffer(target, FLASH_FMD, 4, buffer);
		target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
912
		/* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
oharboe's avatar
oharboe committed
913
914
915
916
		/* Wait until write complete */
		do
		{
			target_read_u32(target, FLASH_FMC, &flash_fmc);
917
		} while (flash_fmc & FMC_WRITE);
zwelch's avatar
zwelch committed
918

oharboe's avatar
oharboe committed
919
920
		buffer += 4;
		address += 4;
921
		words_remaining--;
oharboe's avatar
oharboe committed
922
	}
zwelch's avatar
zwelch committed
923

924
925
	if (bytes_remaining)
	{
926
		uint8_t last_word[4] = {0xff, 0xff, 0xff, 0xff};
927
		int i = 0;
zwelch's avatar
zwelch committed
928

zwelch's avatar
zwelch committed
929
		while (bytes_remaining > 0)
930
		{
zwelch's avatar
zwelch committed
931
			last_word[i++] = *(buffer + bytes_written);
932
933
934
			bytes_remaining--;
			bytes_written++;
		}
zwelch's avatar
zwelch committed
935

936
		if (!(address & 0xff))
duane's avatar
duane committed
937
			LOG_DEBUG("0x%" PRIx32 "", address);
zwelch's avatar
zwelch committed
938

939
940
941
942
943
944
945
946
947
948
949
		/* Program one word */
		target_write_u32(target, FLASH_FMA, address);
		target_write_buffer(target, FLASH_FMD, 4, last_word);
		target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
		/* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
		/* Wait until write complete */
		do
		{
			target_read_u32(target, FLASH_FMC, &flash_fmc);
		} while (flash_fmc & FMC_WRITE);
	}
zwelch's avatar
zwelch committed
950

951
	/* Check access violations */
oharboe's avatar
oharboe committed
952
	target_read_u32(target, FLASH_CRIS, &flash_cris);
953
	if (flash_cris & (AMASK))
oharboe's avatar
oharboe committed
954
	{
duane's avatar
duane committed
955
		LOG_DEBUG("flash_cris 0x%" PRIx32 "", flash_cris);
oharboe's avatar
oharboe committed
956
957
958
959
960
		return ERROR_FLASH_OPERATION_FAILED;
	}
	return ERROR_OK;
}

mifi's avatar
mifi committed
961
static int stellaris_probe(struct flash_bank_s *bank)
oharboe's avatar
oharboe committed
962
963
964
965
{
	/* we can't probe on an stellaris
	 * if this is an stellaris, it has the configured flash
	 */
zwelch's avatar
zwelch committed
966

967
	if (bank->target->state != TARGET_HALTED)
oharboe's avatar
oharboe committed
968
	{
oharboe's avatar
oharboe committed
969
		LOG_ERROR("Target not halted");