tms470.c 35.7 KB
Newer Older
mifi's avatar
mifi committed
1
/***************************************************************************
oharboe's avatar
oharboe committed
2
 *   Copyright (C) 2007,2008 by Christopher Kilgour                        *
mifi's avatar
mifi committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 *   techie |_at_| whiterocker |_dot_| com                                 *
 *                                                                         *
 *   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.             *
 ***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "tms470.h"
25

mifi's avatar
mifi committed
26

mifi's avatar
mifi committed
27
28
29
30
static int tms470_register_commands(struct command_context_s *cmd_ctx);
static int tms470_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
static int tms470_erase(struct flash_bank_s *bank, int first, int last);
static int tms470_protect(struct flash_bank_s *bank, int set, int first, int last);
31
static int tms470_write(struct flash_bank_s *bank, uint8_t * buffer, uint32_t offset, uint32_t count);
mifi's avatar
mifi committed
32
33
34
35
36
static int tms470_probe(struct flash_bank_s *bank);
static int tms470_auto_probe(struct flash_bank_s *bank);
static int tms470_erase_check(struct flash_bank_s *bank);
static int tms470_protect_check(struct flash_bank_s *bank);
static int tms470_info(struct flash_bank_s *bank, char *buf, int buf_size);
37
38
39
40
41
42
43
44
45
46
47
48
49
50

flash_driver_t tms470_flash = {
	.name = "tms470",
	.register_commands = tms470_register_commands,
	.flash_bank_command = tms470_flash_bank_command,
	.erase = tms470_erase,
	.protect = tms470_protect,
	.write = tms470_write,
	.probe = tms470_probe,
	.auto_probe = tms470_auto_probe,
	.erase_check = tms470_erase_check,
	.protect_check = tms470_protect_check,
	.info = tms470_info
};
mifi's avatar
mifi committed
51
52
53
54
55

/* ---------------------------------------------------------------------- 
                      Internal Support, Helpers
   ---------------------------------------------------------------------- */

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
const flash_sector_t TMS470R1A256_SECTORS[] = {
	{0x00000000, 0x00002000, -1, -1},
	{0x00002000, 0x00002000, -1, -1},
	{0x00004000, 0x00002000, -1, -1},
	{0x00006000, 0x00002000, -1, -1},
	{0x00008000, 0x00008000, -1, -1},
	{0x00010000, 0x00008000, -1, -1},
	{0x00018000, 0x00008000, -1, -1},
	{0x00020000, 0x00008000, -1, -1},
	{0x00028000, 0x00008000, -1, -1},
	{0x00030000, 0x00008000, -1, -1},
	{0x00038000, 0x00002000, -1, -1},
	{0x0003A000, 0x00002000, -1, -1},
	{0x0003C000, 0x00002000, -1, -1},
	{0x0003E000, 0x00002000, -1, -1},
};
mifi's avatar
mifi committed
72
73

#define TMS470R1A256_NUM_SECTORS \
74
	(sizeof(TMS470R1A256_SECTORS)/sizeof(TMS470R1A256_SECTORS[0]))
mifi's avatar
mifi committed
75

76
77
78
79
80
81
const flash_sector_t TMS470R1A288_BANK0_SECTORS[] = {
	{0x00000000, 0x00002000, -1, -1},
	{0x00002000, 0x00002000, -1, -1},
	{0x00004000, 0x00002000, -1, -1},
	{0x00006000, 0x00002000, -1, -1},
};
mifi's avatar
mifi committed
82
83

#define TMS470R1A288_BANK0_NUM_SECTORS \
84
	(sizeof(TMS470R1A288_BANK0_SECTORS)/sizeof(TMS470R1A288_BANK0_SECTORS[0]))
mifi's avatar
mifi committed
85

86
87
88
89
90
91
const flash_sector_t TMS470R1A288_BANK1_SECTORS[] = {
	{0x00040000, 0x00010000, -1, -1},
	{0x00050000, 0x00010000, -1, -1},
	{0x00060000, 0x00010000, -1, -1},
	{0x00070000, 0x00010000, -1, -1},
};
mifi's avatar
mifi committed
92
93

#define TMS470R1A288_BANK1_NUM_SECTORS \
94
	(sizeof(TMS470R1A288_BANK1_SECTORS)/sizeof(TMS470R1A288_BANK1_SECTORS[0]))
mifi's avatar
mifi committed
95

96
const flash_sector_t TMS470R1A384_BANK0_SECTORS[] = {
97
98
99
100
101
102
103
104
105
106
	{0x00000000, 0x00002000, -1, -1},
	{0x00002000, 0x00002000, -1, -1},
	{0x00004000, 0x00004000, -1, -1},
	{0x00008000, 0x00004000, -1, -1},
	{0x0000C000, 0x00004000, -1, -1},
	{0x00010000, 0x00004000, -1, -1},
	{0x00014000, 0x00004000, -1, -1},
	{0x00018000, 0x00002000, -1, -1},
	{0x0001C000, 0x00002000, -1, -1},
	{0x0001E000, 0x00002000, -1, -1},
107
108
109
};

#define TMS470R1A384_BANK0_NUM_SECTORS \
110
	(sizeof(TMS470R1A384_BANK0_SECTORS)/sizeof(TMS470R1A384_BANK0_SECTORS[0]))
111
112

const flash_sector_t TMS470R1A384_BANK1_SECTORS[] = {
113
114
115
116
	{0x00020000, 0x00008000, -1, -1},
	{0x00028000, 0x00008000, -1, -1},
	{0x00030000, 0x00008000, -1, -1},
	{0x00038000, 0x00008000, -1, -1},
117
118
119
};

#define TMS470R1A384_BANK1_NUM_SECTORS \
120
	(sizeof(TMS470R1A384_BANK1_SECTORS)/sizeof(TMS470R1A384_BANK1_SECTORS[0]))
121
122

const flash_sector_t TMS470R1A384_BANK2_SECTORS[] = {
123
124
125
126
	{0x00040000, 0x00008000, -1, -1},
	{0x00048000, 0x00008000, -1, -1},
	{0x00050000, 0x00008000, -1, -1},
	{0x00058000, 0x00008000, -1, -1},
127
128
129
};

#define TMS470R1A384_BANK2_NUM_SECTORS \
130
	(sizeof(TMS470R1A384_BANK2_SECTORS)/sizeof(TMS470R1A384_BANK2_SECTORS[0]))
131

mifi's avatar
mifi committed
132
133
/* ---------------------------------------------------------------------- */

mifi's avatar
mifi committed
134
static int tms470_read_part_info(struct flash_bank_s *bank)
mifi's avatar
mifi committed
135
{
136
137
	tms470_flash_bank_t *tms470_info = bank->driver_priv;
	target_t *target = bank->target;
138
139
140
141
142
	uint32_t device_ident_reg;
	uint32_t silicon_version;
	uint32_t technology_family;
	uint32_t rom_flash;
	uint32_t part_number;
143
144
	char *part_name;

145
146
147
148
	/* we shall not rely on the caller in this test, this function allocates memory,
	   thus and executing the code more than once may cause memory leak */
	if (tms470_info->device_ident_reg)
	  return ERROR_OK;
149
150
151
152

	/* read and parse the device identification register */
	target_read_u32(target, 0xFFFFFFF0, &device_ident_reg);

zwelch's avatar
zwelch committed
153
	LOG_INFO("device_ident_reg = 0x%08" PRIx32 "", device_ident_reg);
154
155
156

	if ((device_ident_reg & 7) == 0)
	{
157
		LOG_WARNING("Cannot identify target as a TMS470 family.");
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
		return ERROR_FLASH_OPERATION_FAILED;
	}

	silicon_version = (device_ident_reg >> 12) & 0xF;
	technology_family = (device_ident_reg >> 11) & 1;
	rom_flash = (device_ident_reg >> 10) & 1;
	part_number = (device_ident_reg >> 3) & 0x7f;

	/*
	 * If the part number is known, determine if the flash bank is valid
	 * based on the base address being within the known flash bank
	 * ranges.  Then fixup/complete the remaining fields of the flash
	 * bank structure.
	 */
	switch (part_number)
	{
	case 0x0a:
		part_name = "TMS470R1A256";

		if (bank->base >= 0x00040000)
		{
duane's avatar
duane committed
179
			LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".", part_name, bank->base);
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
			return ERROR_FLASH_OPERATION_FAILED;
		}
		tms470_info->ordinal = 0;
		bank->base = 0x00000000;
		bank->size = 256 * 1024;
		bank->num_sectors = TMS470R1A256_NUM_SECTORS;
		bank->sectors = malloc(sizeof(TMS470R1A256_SECTORS));
		if (!bank->sectors)
		{
			return ERROR_FLASH_OPERATION_FAILED;
		}
		(void)memcpy(bank->sectors, TMS470R1A256_SECTORS, sizeof(TMS470R1A256_SECTORS));
		break;

	case 0x2b:
		part_name = "TMS470R1A288";

197
		if (bank->base < 0x00008000)
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
		{
			tms470_info->ordinal = 0;
			bank->base = 0x00000000;
			bank->size = 32 * 1024;
			bank->num_sectors = TMS470R1A288_BANK0_NUM_SECTORS;
			bank->sectors = malloc(sizeof(TMS470R1A288_BANK0_SECTORS));
			if (!bank->sectors)
			{
				return ERROR_FLASH_OPERATION_FAILED;
			}
			(void)memcpy(bank->sectors, TMS470R1A288_BANK0_SECTORS, sizeof(TMS470R1A288_BANK0_SECTORS));
		}
		else if ((bank->base >= 0x00040000) && (bank->base < 0x00080000))
		{
			tms470_info->ordinal = 1;
			bank->base = 0x00040000;
			bank->size = 256 * 1024;
			bank->num_sectors = TMS470R1A288_BANK1_NUM_SECTORS;
			bank->sectors = malloc(sizeof(TMS470R1A288_BANK1_SECTORS));
			if (!bank->sectors)
			{
				return ERROR_FLASH_OPERATION_FAILED;
			}
			(void)memcpy(bank->sectors, TMS470R1A288_BANK1_SECTORS, sizeof(TMS470R1A288_BANK1_SECTORS));
		}
		else
		{
duane's avatar
duane committed
225
			LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".", part_name, bank->base);
226
227
228
229
			return ERROR_FLASH_OPERATION_FAILED;
		}
		break;

230
231
232
	case 0x2d:
		part_name = "TMS470R1A384";

233
		if (bank->base < 0x00020000)
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
		{
			tms470_info->ordinal = 0;
			bank->base = 0x00000000;
			bank->size = 128 * 1024;
			bank->num_sectors = TMS470R1A384_BANK0_NUM_SECTORS;
			bank->sectors = malloc(sizeof(TMS470R1A384_BANK0_SECTORS));
			if (!bank->sectors)
			{
				return ERROR_FLASH_OPERATION_FAILED;
			}
			(void)memcpy(bank->sectors, TMS470R1A384_BANK0_SECTORS, sizeof(TMS470R1A384_BANK0_SECTORS));
		}
		else if ((bank->base >= 0x00020000) && (bank->base < 0x00040000))
		{
			tms470_info->ordinal = 1;
			bank->base = 0x00020000;
			bank->size = 128 * 1024;
			bank->num_sectors = TMS470R1A384_BANK1_NUM_SECTORS;
			bank->sectors = malloc(sizeof(TMS470R1A384_BANK1_SECTORS));
			if (!bank->sectors)
			{
				return ERROR_FLASH_OPERATION_FAILED;
			}
			(void)memcpy(bank->sectors, TMS470R1A384_BANK1_SECTORS, sizeof(TMS470R1A384_BANK1_SECTORS));
		}
		else if ((bank->base >= 0x00040000) && (bank->base < 0x00060000))
		{
			tms470_info->ordinal = 2;
			bank->base = 0x00040000;
			bank->size = 128 * 1024;
			bank->num_sectors = TMS470R1A384_BANK2_NUM_SECTORS;
			bank->sectors = malloc(sizeof(TMS470R1A384_BANK2_SECTORS));
			if (!bank->sectors)
			{
				return ERROR_FLASH_OPERATION_FAILED;
			}
			(void)memcpy(bank->sectors, TMS470R1A384_BANK2_SECTORS, sizeof(TMS470R1A384_BANK2_SECTORS));
		}
		else
		{
duane's avatar
duane committed
274
			LOG_ERROR("No %s flash bank contains base address 0x%08" PRIx32 ".", part_name, bank->base);
275
276
277
278
279
			return ERROR_FLASH_OPERATION_FAILED;
		}
		break;

	default:
duane's avatar
duane committed
280
		LOG_WARNING("Could not identify part 0x%02x as a member of the TMS470 family.", (unsigned)part_number);
281
282
283
284
285
286
287
288
289
290
		return ERROR_FLASH_OPERATION_FAILED;
	}

	/* turn off memory selects */
	target_write_u32(target, 0xFFFFFFE4, 0x00000000);
	target_write_u32(target, 0xFFFFFFE0, 0x00000000);

	bank->chip_width = 32;
	bank->bus_width = 32;

duane's avatar
duane committed
291
292
293
294
295
	LOG_INFO("Identified %s, ver=%d, core=%s, nvmem=%s.", 
		 part_name,
		 (int)(silicon_version),
		 (technology_family ? "1.8v" : "3.3v"), 
		 (rom_flash ? "rom" : "flash"));
296
297
298
299
300
301
302
303
304
305
306
307
308
309

	tms470_info->device_ident_reg = device_ident_reg;
	tms470_info->silicon_version = silicon_version;
	tms470_info->technology_family = technology_family;
	tms470_info->rom_flash = rom_flash;
	tms470_info->part_number = part_number;
	tms470_info->part_name = part_name;

	/*
	 * Disable reset on address access violation.
	 */
	target_write_u32(target, 0xFFFFFFE0, 0x00004007);

	return ERROR_OK;
mifi's avatar
mifi committed
310
311
312
313
}

/* ---------------------------------------------------------------------- */

314
315
static uint32_t keysSet = 0;
static uint32_t flashKeys[4];
mifi's avatar
mifi committed
316

mifi's avatar
mifi committed
317
static int tms470_handle_flash_keyset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
mifi's avatar
mifi committed
318
{
319
320
321
322
323
324
325
326
327
328
329
330
331
	if (argc > 4)
	{
		command_print(cmd_ctx, "tms470 flash_keyset <key0> <key1> <key2> <key3>");
		return ERROR_INVALID_ARGUMENTS;
	}
	else if (argc == 4)
	{
		int i;

		for (i = 0; i < 4; i++)
		{
			int start = (0 == strncmp(args[i], "0x", 2)) ? 2 : 0;

duane's avatar
duane committed
332
			if (1 != sscanf(&args[i][start], "%" SCNx32 "", &flashKeys[i]))
333
334
			{
				command_print(cmd_ctx, "could not process flash key %s", args[i]);
335
				LOG_ERROR("could not process flash key %s", args[i]);
336
337
338
339
340
341
342
343
344
345
346
347
348
349
				return ERROR_INVALID_ARGUMENTS;
			}
		}

		keysSet = 1;
	}
	else if (argc != 0)
	{
		command_print(cmd_ctx, "tms470 flash_keyset <key0> <key1> <key2> <key3>");
		return ERROR_INVALID_ARGUMENTS;
	}

	if (keysSet)
	{
duane's avatar
duane committed
350
351
		command_print(cmd_ctx, "using flash keys 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 "", 
			      flashKeys[0], flashKeys[1], flashKeys[2], flashKeys[3]);
352
353
354
355
356
357
358
	}
	else
	{
		command_print(cmd_ctx, "flash keys not set");
	}

	return ERROR_OK;
mifi's avatar
mifi committed
359
360
}

361
static const uint32_t FLASH_KEYS_ALL_ONES[] = { 0xFFFFFFFF, 0xFFFFFFFF,
362
363
	0xFFFFFFFF, 0xFFFFFFFF,
};
mifi's avatar
mifi committed
364

365
static const uint32_t FLASH_KEYS_ALL_ZEROS[] = { 0x00000000, 0x00000000,
366
367
	0x00000000, 0x00000000,
};
mifi's avatar
mifi committed
368

369
static const uint32_t FLASH_KEYS_MIX1[] = { 0xf0fff0ff, 0xf0fff0ff,
370
371
	0xf0fff0ff, 0xf0fff0ff
};
mifi's avatar
mifi committed
372

373
static const uint32_t FLASH_KEYS_MIX2[] = { 0x0000ffff, 0x0000ffff,
374
375
	0x0000ffff, 0x0000ffff
};
mifi's avatar
mifi committed
376
377
378

/* ---------------------------------------------------------------------- */

mifi's avatar
mifi committed
379
static int oscMHz = 12;
mifi's avatar
mifi committed
380

mifi's avatar
mifi committed
381
static int tms470_handle_osc_megahertz_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
mifi's avatar
mifi committed
382
{
383
384
385
386
387
388
389
390
391
392
393
394
	if (argc > 1)
	{
		command_print(cmd_ctx, "tms470 osc_megahertz <MHz>");
		return ERROR_INVALID_ARGUMENTS;
	}
	else if (argc == 1)
	{
		sscanf(args[0], "%d", &oscMHz);
	}

	if (oscMHz <= 0)
	{
395
		LOG_ERROR("osc_megahertz must be positive and non-zero!");
396
397
398
399
400
401
402
403
		command_print(cmd_ctx, "osc_megahertz must be positive and non-zero!");
		oscMHz = 12;
		return ERROR_INVALID_ARGUMENTS;
	}

	command_print(cmd_ctx, "osc_megahertz=%d", oscMHz);

	return ERROR_OK;
mifi's avatar
mifi committed
404
405
406
407
}

/* ---------------------------------------------------------------------- */

mifi's avatar
mifi committed
408
static int plldis = 0;
mifi's avatar
mifi committed
409

mifi's avatar
mifi committed
410
static int tms470_handle_plldis_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
mifi's avatar
mifi committed
411
{
412
413
	if (argc > 1)
	{
zwelch's avatar
zwelch committed
414
		command_print(cmd_ctx, "tms470 plldis <0 | 1>");
415
416
417
418
419
420
421
422
423
424
425
		return ERROR_INVALID_ARGUMENTS;
	}
	else if (argc == 1)
	{
		sscanf(args[0], "%d", &plldis);
		plldis = plldis ? 1 : 0;
	}

	command_print(cmd_ctx, "plldis=%d", plldis);

	return ERROR_OK;
mifi's avatar
mifi committed
426
427
428
429
}

/* ---------------------------------------------------------------------- */

mifi's avatar
mifi committed
430
static int tms470_check_flash_unlocked(target_t * target)
mifi's avatar
mifi committed
431
{
432
	uint32_t fmbbusy;
mifi's avatar
mifi committed
433

434
	target_read_u32(target, 0xFFE89C08, &fmbbusy);
zwelch's avatar
zwelch committed
435
	LOG_INFO("tms470 fmbbusy = 0x%08" PRIx32 " -> %s", fmbbusy, fmbbusy & 0x8000 ? "unlocked" : "LOCKED");
436
	return fmbbusy & 0x8000 ? ERROR_OK : ERROR_FLASH_OPERATION_FAILED;
mifi's avatar
mifi committed
437
438
439
440
}

/* ---------------------------------------------------------------------- */

441
static int tms470_try_flash_keys(target_t * target, const uint32_t * key_set)
mifi's avatar
mifi committed
442
{
443
	uint32_t glbctrl, fmmstat;
444
445
446
447
448
449
450
451
452
453
454
	int retval = ERROR_FLASH_OPERATION_FAILED;

	/* set GLBCTRL.4  */
	target_read_u32(target, 0xFFFFFFDC, &glbctrl);
	target_write_u32(target, 0xFFFFFFDC, glbctrl | 0x10);

	/* only perform the key match when 3VSTAT is clear */
	target_read_u32(target, 0xFFE8BC0C, &fmmstat);
	if (!(fmmstat & 0x08))
	{
		unsigned i;
455
		uint32_t fmbptr, fmbac2, orig_fmregopt;
456
457
458
459
460
461
462

		target_write_u32(target, 0xFFE8BC04, fmmstat & ~0x07);

		/* wait for pump ready */
		do
		{
			target_read_u32(target, 0xFFE8A814, &fmbptr);
463
			alive_sleep(1);
464
465
466
467
468
469
470
471
472
473
474
475
476
		}
		while (!(fmbptr & 0x0200));

		/* force max wait states */
		target_read_u32(target, 0xFFE88004, &fmbac2);
		target_write_u32(target, 0xFFE88004, fmbac2 | 0xff);

		/* save current access mode, force normal read mode */
		target_read_u32(target, 0xFFE89C00, &orig_fmregopt);
		target_write_u32(target, 0xFFE89C00, 0x00);

		for (i = 0; i < 4; i++)
		{
477
			uint32_t tmp;
478
479
480
481
482
483
484

			/* There is no point displaying the value of tmp, it is
			 * filtered by the chip.  The purpose of this read is to
			 * prime the unlocking logic rather than read out the value.
			 */
			target_read_u32(target, 0x00001FF0 + 4 * i, &tmp);

zwelch's avatar
zwelch committed
485
			LOG_INFO("tms470 writing fmpkey = 0x%08" PRIx32 "", key_set[i]);
486
487
488
489
490
491
492
493
494
495
496
497
			target_write_u32(target, 0xFFE89C0C, key_set[i]);
		}

		if (ERROR_OK == tms470_check_flash_unlocked(target))
		{
			/* 
			 * There seems to be a side-effect of reading the FMPKEY
			 * register in that it re-enables the protection.  So we
			 * re-enable it.
			 */
			for (i = 0; i < 4; i++)
			{
498
				uint32_t tmp;
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514

				target_read_u32(target, 0x00001FF0 + 4 * i, &tmp);
				target_write_u32(target, 0xFFE89C0C, key_set[i]);
			}
			retval = ERROR_OK;
		}

		/* restore settings */
		target_write_u32(target, 0xFFE89C00, orig_fmregopt);
		target_write_u32(target, 0xFFE88004, fmbac2);
	}

	/* clear config bit */
	target_write_u32(target, 0xFFFFFFDC, glbctrl);

	return retval;
mifi's avatar
mifi committed
515
516
517
518
}

/* ---------------------------------------------------------------------- */

mifi's avatar
mifi committed
519
static int tms470_unlock_flash(struct flash_bank_s *bank)
mifi's avatar
mifi committed
520
{
521
	target_t *target = bank->target;
522
	const uint32_t *p_key_sets[5];
523
524
525
526
	unsigned i, key_set_count;

	if (keysSet)
	{
oharboe's avatar
oharboe committed
527
		key_set_count = 5;
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
		p_key_sets[0] = flashKeys;
		p_key_sets[1] = FLASH_KEYS_ALL_ONES;
		p_key_sets[2] = FLASH_KEYS_ALL_ZEROS;
		p_key_sets[3] = FLASH_KEYS_MIX1;
		p_key_sets[4] = FLASH_KEYS_MIX2;
	}
	else
	{
		key_set_count = 4;
		p_key_sets[0] = FLASH_KEYS_ALL_ONES;
		p_key_sets[1] = FLASH_KEYS_ALL_ZEROS;
		p_key_sets[2] = FLASH_KEYS_MIX1;
		p_key_sets[3] = FLASH_KEYS_MIX2;
	}

	for (i = 0; i < key_set_count; i++)
	{
		if (tms470_try_flash_keys(target, p_key_sets[i]) == ERROR_OK)
		{
547
			LOG_INFO("tms470 flash is unlocked");
548
549
550
551
			return ERROR_OK;
		}
	}

552
	LOG_WARNING("tms470 could not unlock flash memory protection level 2");
553
	return ERROR_FLASH_OPERATION_FAILED;
mifi's avatar
mifi committed
554
555
556
557
}

/* ---------------------------------------------------------------------- */

mifi's avatar
mifi committed
558
static int tms470_flash_initialize_internal_state_machine(struct flash_bank_s *bank)
mifi's avatar
mifi committed
559
{
560
	uint32_t fmmac2, fmmac1, fmmaxep, k, delay, glbctrl, sysclk;
561
562
563
564
565
566
567
568
569
570
571
572
	target_t *target = bank->target;
	tms470_flash_bank_t *tms470_info = bank->driver_priv;
	int result = ERROR_OK;

	/*
	 * Select the desired bank to be programmed by writing BANK[2:0] of
	 * FMMAC2.
	 */
	target_read_u32(target, 0xFFE8BC04, &fmmac2);
	fmmac2 &= ~0x0007;
	fmmac2 |= (tms470_info->ordinal & 7);
	target_write_u32(target, 0xFFE8BC04, fmmac2);
zwelch's avatar
zwelch committed
573
	LOG_DEBUG("set fmmac2 = 0x%04" PRIx32 "", fmmac2);
574
575
576
577
578
579
580

	/*
	 * Disable level 1 sector protection by setting bit 15 of FMMAC1.
	 */
	target_read_u32(target, 0xFFE8BC00, &fmmac1);
	fmmac1 |= 0x8000;
	target_write_u32(target, 0xFFE8BC00, fmmac1);
zwelch's avatar
zwelch committed
581
	LOG_DEBUG("set fmmac1 = 0x%04" PRIx32 "", fmmac1);
582
583

	/*
zwelch's avatar
zwelch committed
584
	 * FMTCREG = 0x2fc0;
585
586
	 */
	target_write_u32(target, 0xFFE8BC10, 0x2fc0);
zwelch's avatar
zwelch committed
587
	LOG_DEBUG("set fmtcreg = 0x2fc0");
588
589

	/*
zwelch's avatar
zwelch committed
590
	 * MAXPP = 50
591
592
	 */
	target_write_u32(target, 0xFFE8A07C, 50);
zwelch's avatar
zwelch committed
593
	LOG_DEBUG("set fmmaxpp = 50");
594
595

	/*
zwelch's avatar
zwelch committed
596
	 * MAXCP = 0xf000 + 2000
597
598
	 */
	target_write_u32(target, 0xFFE8A084, 0xf000 + 2000);
zwelch's avatar
zwelch committed
599
	LOG_DEBUG("set fmmaxcp = 0x%04x", 0xf000 + 2000);
600
601
602
603
604
605
606
607
608

	/*
	 * configure VHV
	 */
	target_read_u32(target, 0xFFE8A080, &fmmaxep);
	if (fmmaxep == 0xf000)
	{
		fmmaxep = 0xf000 + 4095;
		target_write_u32(target, 0xFFE8A80C, 0x9964);
zwelch's avatar
zwelch committed
609
		LOG_DEBUG("set fmptr3 = 0x9964");
610
611
612
613
614
	}
	else
	{
		fmmaxep = 0xa000 + 4095;
		target_write_u32(target, 0xFFE8A80C, 0x9b64);
zwelch's avatar
zwelch committed
615
		LOG_DEBUG("set fmptr3 = 0x9b64");
616
617
	}
	target_write_u32(target, 0xFFE8A080, fmmaxep);
zwelch's avatar
zwelch committed
618
	LOG_DEBUG("set fmmaxep = 0x%04" PRIx32 "", fmmaxep);
619
620

	/*
zwelch's avatar
zwelch committed
621
	 * FMPTR4 = 0xa000
622
623
	 */
	target_write_u32(target, 0xFFE8A810, 0xa000);
zwelch's avatar
zwelch committed
624
	LOG_DEBUG("set fmptr4 = 0xa000");
625
626
627
628
629
630
631
632
633
634
635
636
637

	/*
	 * FMPESETUP, delay parameter selected based on clock frequency.
	 *
	 * According to the TI App Note SPNU257 and flashing code, delay is
	 * int((sysclk(MHz) + 1) / 2), with a minimum of 5.  The system
	 * clock is usually derived from the ZPLL module, and selected by
	 * the plldis global.
	 */
	target_read_u32(target, 0xFFFFFFDC, &glbctrl);
	sysclk = (plldis ? 1 : (glbctrl & 0x08) ? 4 : 8) * oscMHz / (1 + (glbctrl & 7));
	delay = (sysclk > 10) ? (sysclk + 1) / 2 : 5;
	target_write_u32(target, 0xFFE8A018, (delay << 4) | (delay << 8));
zwelch's avatar
zwelch committed
638
	LOG_DEBUG("set fmpsetup = 0x%04" PRIx32 "", (delay << 4) | (delay << 8));
639
640
641
642
643
644

	/*
	 * FMPVEVACCESS, based on delay.
	 */
	k = delay | (delay << 8);
	target_write_u32(target, 0xFFE8A05C, k);
zwelch's avatar
zwelch committed
645
	LOG_DEBUG("set fmpvevaccess = 0x%04" PRIx32 "", k);
646
647
648
649
650
651

	/*
	 * FMPCHOLD, FMPVEVHOLD, FMPVEVSETUP, based on delay.
	 */
	k <<= 1;
	target_write_u32(target, 0xFFE8A034, k);
zwelch's avatar
zwelch committed
652
	LOG_DEBUG("set fmpchold = 0x%04" PRIx32 "", k);
653
	target_write_u32(target, 0xFFE8A040, k);
zwelch's avatar
zwelch committed
654
	LOG_DEBUG("set fmpvevhold = 0x%04" PRIx32 "", k);
655
	target_write_u32(target, 0xFFE8A024, k);
zwelch's avatar
zwelch committed
656
	LOG_DEBUG("set fmpvevsetup = 0x%04" PRIx32 "", k);
657
658
659
660
661
662

	/*
	 * FMCVACCESS, based on delay.
	 */
	k = delay * 16;
	target_write_u32(target, 0xFFE8A060, k);
zwelch's avatar
zwelch committed
663
	LOG_DEBUG("set fmcvaccess = 0x%04" PRIx32 "", k);
664
665
666
667
668
669

	/*
	 * FMCSETUP, based on delay.
	 */
	k = 0x3000 | delay * 20;
	target_write_u32(target, 0xFFE8A020, k);
zwelch's avatar
zwelch committed
670
	LOG_DEBUG("set fmcsetup = 0x%04" PRIx32 "", k);
671
672
673
674
675
676

	/*
	 * FMEHOLD, based on delay.
	 */
	k = (delay * 20) << 2;
	target_write_u32(target, 0xFFE8A038, k);
zwelch's avatar
zwelch committed
677
	LOG_DEBUG("set fmehold = 0x%04" PRIx32 "", k);
678
679
680
681
682

	/*
	 * PWIDTH, CWIDTH, EWIDTH, based on delay.
	 */
	target_write_u32(target, 0xFFE8A050, delay * 8);
zwelch's avatar
zwelch committed
683
	LOG_DEBUG("set fmpwidth = 0x%04" PRIx32 "", delay * 8);
684
	target_write_u32(target, 0xFFE8A058, delay * 1000);
zwelch's avatar
zwelch committed
685
	LOG_DEBUG("set fmcwidth = 0x%04" PRIx32 "", delay * 1000);
686
	target_write_u32(target, 0xFFE8A054, delay * 5400);
zwelch's avatar
zwelch committed
687
	LOG_DEBUG("set fmewidth = 0x%04" PRIx32 "", delay * 5400);
688
689

	return result;
mifi's avatar
mifi committed
690
691
692
693
}

/* ---------------------------------------------------------------------- */

694
int tms470_flash_status(struct flash_bank_s *bank)
mifi's avatar
mifi committed
695
{
696
697
	target_t *target = bank->target;
	int result = ERROR_OK;
698
	uint32_t fmmstat;
699
700

	target_read_u32(target, 0xFFE8BC0C, &fmmstat);
zwelch's avatar
zwelch committed
701
	LOG_DEBUG("set fmmstat = 0x%04" PRIx32 "", fmmstat);
702
703
704

	if (fmmstat & 0x0080)
	{
705
		LOG_WARNING("tms470 flash command: erase still active after busy clear.");
706
707
708
709
710
		result = ERROR_FLASH_OPERATION_FAILED;
	}

	if (fmmstat & 0x0040)
	{
711
		LOG_WARNING("tms470 flash command: program still active after busy clear.");
712
713
714
715
716
		result = ERROR_FLASH_OPERATION_FAILED;
	}

	if (fmmstat & 0x0020)
	{
717
		LOG_WARNING("tms470 flash command: invalid data command.");
718
719
720
721
722
		result = ERROR_FLASH_OPERATION_FAILED;
	}

	if (fmmstat & 0x0010)
	{
723
		LOG_WARNING("tms470 flash command: program, erase or validate sector failed.");
724
725
726
727
728
		result = ERROR_FLASH_OPERATION_FAILED;
	}

	if (fmmstat & 0x0008)
	{
729
		LOG_WARNING("tms470 flash command: voltage instability detected.");
730
731
732
733
734
		result = ERROR_FLASH_OPERATION_FAILED;
	}

	if (fmmstat & 0x0006)
	{
735
		LOG_WARNING("tms470 flash command: command suspend detected.");
736
737
738
739
740
		result = ERROR_FLASH_OPERATION_FAILED;
	}

	if (fmmstat & 0x0001)
	{
741
		LOG_WARNING("tms470 flash command: sector was locked.");
742
743
744
745
		result = ERROR_FLASH_OPERATION_FAILED;
	}

	return result;
mifi's avatar
mifi committed
746
747
748
749
}

/* ---------------------------------------------------------------------- */

mifi's avatar
mifi committed
750
static int tms470_erase_sector(struct flash_bank_s *bank, int sector)
mifi's avatar
mifi committed
751
{
752
	uint32_t glbctrl, orig_fmregopt, fmbsea, fmbseb, fmmstat;
753
	target_t *target = bank->target;
754
	uint32_t flashAddr = bank->base + bank->sectors[sector].offset;
755
756
757
758
759
760
761
762
	int result = ERROR_OK;

	/* 
	 * Set the bit GLBCTRL4 of the GLBCTRL register (in the System
	 * module) to enable writing to the flash registers }.
	 */
	target_read_u32(target, 0xFFFFFFDC, &glbctrl);
	target_write_u32(target, 0xFFFFFFDC, glbctrl | 0x10);
zwelch's avatar
zwelch committed
763
	LOG_DEBUG("set glbctrl = 0x%08" PRIx32 "", glbctrl | 0x10);
764
765
766
767

	/* Force normal read mode. */
	target_read_u32(target, 0xFFE89C00, &orig_fmregopt);
	target_write_u32(target, 0xFFE89C00, 0);
zwelch's avatar
zwelch committed
768
	LOG_DEBUG("set fmregopt = 0x%08x", 0);
769
770
771
772
773
774
775
776
777
778
779

	(void)tms470_flash_initialize_internal_state_machine(bank);

	/*
	 * Select one or more bits in FMBSEA or FMBSEB to disable Level 1
	 * protection for the particular sector to be erased/written.
	 */
	if (sector < 16)
	{
		target_read_u32(target, 0xFFE88008, &fmbsea);
		target_write_u32(target, 0xFFE88008, fmbsea | (1 << sector));
zwelch's avatar
zwelch committed
780
		LOG_DEBUG("set fmbsea = 0x%04" PRIx32 "", fmbsea | (1 << sector));
781
782
783
784
785
	}
	else
	{
		target_read_u32(target, 0xFFE8800C, &fmbseb);
		target_write_u32(target, 0xFFE8800C, fmbseb | (1 << (sector - 16)));
zwelch's avatar
zwelch committed
786
		LOG_DEBUG("set fmbseb = 0x%04" PRIx32 "", fmbseb | (1 << (sector - 16)));
787
788
789
790
791
792
793
	}
	bank->sectors[sector].is_protected = 0;

	/* 
	 * clear status regiser, sent erase command, kickoff erase 
	 */
	target_write_u16(target, flashAddr, 0x0040);
duane's avatar
duane committed
794
	LOG_DEBUG("write *(uint16_t *)0x%08" PRIx32 "=0x0040", flashAddr);
795
	target_write_u16(target, flashAddr, 0x0020);
duane's avatar
duane committed
796
	LOG_DEBUG("write *(uint16_t *)0x%08" PRIx32 "=0x0020", flashAddr);
797
	target_write_u16(target, flashAddr, 0xffff);
duane's avatar
duane committed
798
	LOG_DEBUG("write *(uint16_t *)0x%08" PRIx32 "=0xffff", flashAddr);
799
800
801
802
803
804
805
806
807
808

	/*
	 * Monitor FMMSTAT, busy until clear, then check and other flags for
	 * ultimate result of the operation.
	 */
	do
	{
		target_read_u32(target, 0xFFE8BC0C, &fmmstat);
		if (fmmstat & 0x0100)
		{
809
			alive_sleep(1);
810
811
812
813
814
815
816
817
818
		}
	}
	while (fmmstat & 0x0100);

	result = tms470_flash_status(bank);

	if (sector < 16)
	{
		target_write_u32(target, 0xFFE88008, fmbsea);
zwelch's avatar
zwelch committed
819
		LOG_DEBUG("set fmbsea = 0x%04" PRIx32 "", fmbsea);
820
821
822
823
824
		bank->sectors[sector].is_protected = fmbsea & (1 << sector) ? 0 : 1;
	}
	else
	{
		target_write_u32(target, 0xFFE8800C, fmbseb);
zwelch's avatar
zwelch committed
825
		LOG_DEBUG("set fmbseb = 0x%04" PRIx32 "", fmbseb);
826
827
828
		bank->sectors[sector].is_protected = fmbseb & (1 << (sector - 16)) ? 0 : 1;
	}
	target_write_u32(target, 0xFFE89C00, orig_fmregopt);
zwelch's avatar
zwelch committed
829
	LOG_DEBUG("set fmregopt = 0x%08" PRIx32 "", orig_fmregopt);
830
	target_write_u32(target, 0xFFFFFFDC, glbctrl);
zwelch's avatar
zwelch committed
831
	LOG_DEBUG("set glbctrl = 0x%08" PRIx32 "", glbctrl);
832
833
834
835
836
837
838

	if (result == ERROR_OK)
	{
		bank->sectors[sector].is_erased = 1;
	}

	return result;
mifi's avatar
mifi committed
839
840
841
842
843
844
}

/* ---------------------------------------------------------------------- 
              Implementation of Flash Driver Interfaces
   ---------------------------------------------------------------------- */

mifi's avatar
mifi committed
845
static int tms470_register_commands(struct command_context_s *cmd_ctx)
mifi's avatar
mifi committed
846
{
847
848
849
850
851
852
853
	command_t *tms470_cmd = register_command(cmd_ctx, NULL, "tms470", NULL, COMMAND_ANY, "applies to TI tms470 family");

	register_command(cmd_ctx, tms470_cmd, "flash_keyset", tms470_handle_flash_keyset_command, COMMAND_ANY, "tms470 flash_keyset <key0> <key1> <key2> <key3>");
	register_command(cmd_ctx, tms470_cmd, "osc_megahertz", tms470_handle_osc_megahertz_command, COMMAND_ANY, "tms470 osc_megahertz <MHz>");
	register_command(cmd_ctx, tms470_cmd, "plldis", tms470_handle_plldis_command, COMMAND_ANY, "tms470 plldis <0/1>");

	return ERROR_OK;
mifi's avatar
mifi committed
854
855
856
857
}

/* ---------------------------------------------------------------------- */

mifi's avatar
mifi committed
858
static int tms470_erase(struct flash_bank_s *bank, int first, int last)
mifi's avatar
mifi committed
859
{
860
861
862
	tms470_flash_bank_t *tms470_info = bank->driver_priv;
	int sector, result = ERROR_OK;

863
	if (bank->target->state != TARGET_HALTED)
864
	{
oharboe's avatar
oharboe committed
865
		LOG_ERROR("Target not halted");
866
		return ERROR_TARGET_NOT_HALTED;
867
868
	}

869
870
	tms470_read_part_info(bank);

871
872
	if ((first < 0) || (first >= bank->num_sectors) || (last < 0) || (last >= bank->num_sectors) || (first > last))
	{
873
		LOG_ERROR("Sector range %d to %d invalid.", first, last);
874
875
876
877
878
879
880
881
882
883
884
		return ERROR_FLASH_SECTOR_INVALID;
	}

	result = tms470_unlock_flash(bank);
	if (result != ERROR_OK)
	{
		return result;
	}

	for (sector = first; sector <= last; sector++)
	{
885
		LOG_INFO("Erasing tms470 bank %d sector %d...", tms470_info->ordinal, sector);
886
887
888
889
890

		result = tms470_erase_sector(bank, sector);

		if (result != ERROR_OK)
		{
891
			LOG_ERROR("tms470 could not erase flash sector.");
892
893
894
895
			break;
		}
		else
		{
896
			LOG_INFO("sector erased successfully.");
897
898
899
900
		}
	}

	return result;
mifi's avatar
mifi committed
901
902
903
904
}

/* ---------------------------------------------------------------------- */

mifi's avatar
mifi committed
905
static int tms470_protect(struct flash_bank_s *bank, int set, int first, int last)
mifi's avatar
mifi committed
906
{
907
908
	tms470_flash_bank_t *tms470_info = bank->driver_priv;
	target_t *target = bank->target;
909
	uint32_t fmmac2, fmbsea, fmbseb;
910
911
	int sector;

912
	if (target->state != TARGET_HALTED)
913
	{
oharboe's avatar
oharboe committed
914
		LOG_ERROR("Target not halted");
915
		return ERROR_TARGET_NOT_HALTED;
916
917
	}

918
919
	tms470_read_part_info(bank);

920
921
	if ((first < 0) || (first >= bank->num_sectors) || (last < 0) || (last >= bank->num_sectors) || (first > last))
	{
922
		LOG_ERROR("Sector range %d to %d invalid.", first, last);
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
		return ERROR_FLASH_SECTOR_INVALID;
	}

	/* enable the appropriate bank */
	target_read_u32(target, 0xFFE8BC04, &fmmac2);
	target_write_u32(target, 0xFFE8BC04, (fmmac2 & ~7) | tms470_info->ordinal);

	/* get the original sector proection flags for this bank */
	target_read_u32(target, 0xFFE88008, &fmbsea);
	target_read_u32(target, 0xFFE8800C, &fmbseb);

	for (sector = 0; sector < bank->num_sectors; sector++)
	{
		if (sector < 16)
		{
			fmbsea = set ? fmbsea & ~(1 << sector) : fmbsea | (1 << sector);
			bank->sectors[sector].is_protected = set ? 1 : 0;
		}
		else
		{
			fmbseb = set ? fmbseb & ~(1 << (sector - 16)) : fmbseb | (1 << (sector - 16));
			bank->sectors[sector].is_protected = set ? 1 : 0;
		}
	}

	/* update the protection bits */
	target_write_u32(target, 0xFFE88008, fmbsea);
	target_write_u32(target, 0xFFE8800C, fmbseb);

	return ERROR_OK;
mifi's avatar
mifi committed
953
954
955
956
}

/* ---------------------------------------------------------------------- */

957
static int tms470_write(struct flash_bank_s *bank, uint8_t * buffer, uint32_t offset, uint32_t count)
mifi's avatar
mifi committed
958
{
959
	target_t *target = bank->target;
960
	uint32_t glbctrl, fmbac2, orig_fmregopt, fmbsea, fmbseb, fmmaxpp, fmmstat;
961
	int result = ERROR_OK;
962
	uint32_t i;
963

964
	if (target->state != TARGET_HALTED)
965
	{
oharboe's avatar
oharboe committed
966
		LOG_ERROR("Target not halted");
967
		return ERROR_TARGET_NOT_HALTED;
968
969
	}

970
971
	tms470_read_part_info(bank);

duane's avatar
duane committed
972
	LOG_INFO("Writing %" PRId32 " bytes starting at 0x%08" PRIx32 "", count, bank->base + offset);
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000

	/* set GLBCTRL.4  */
	target_read_u32(target, 0xFFFFFFDC, &glbctrl);
	target_write_u32(target, 0xFFFFFFDC, glbctrl | 0x10);

	(void)tms470_flash_initialize_internal_state_machine(bank);

	/* force max wait states */
	target_read_u32(target, 0xFFE88004, &fmbac2);
	target_write_u32(target, 0xFFE88004, fmbac2 | 0xff);

	/* save current access mode, force normal read mode */
	target_read_u32(target, 0xFFE89C00, &orig_fmregopt);
	target_write_u32(target, 0xFFE89C00, 0x00);

	/*
	 * Disable Level 1 protection for all sectors to be erased/written.
	 */
	target_read_u32(target, 0xFFE88008, &fmbsea);
	target_write_u32(target, 0xFFE88008, 0xffff);
	target_read_u32(target, 0xFFE8800C, &fmbseb);
	target_write_u32(target, 0xFFE8800C, 0xffff);

	/* read MAXPP */
	target_read_u32(target, 0xFFE8A07C, &fmmaxpp);

	for (i = 0; i < count; i += 2)
	{
For faster browsing, not all history is shown. View entire blame