cfi.c 82.7 KB
Newer Older
1
2
3
/***************************************************************************
 *   Copyright (C) 2005, 2007 by Dominic Rath                              *
 *   Dominic.Rath@gmx.de                                                   *
4
5
 *   Copyright (C) 2009 Michael Schwingen                                  *
 *   michael@schwingen.org                                                 *
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 *                                                                         *
 *   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 "cfi.h"
27
#include "non_cfi.h"
28
29
30
31
32
33
34
35
36
37
#include "armv4_5.h"
#include "binarybuffer.h"


#define CFI_MAX_BUS_WIDTH	4
#define CFI_MAX_CHIP_WIDTH	4

/* defines internal maximum size for code fragment in cfi_intel_write_block() */
#define CFI_MAX_INTEL_CODESIZE 256

38
static struct cfi_unlock_addresses cfi_unlock_addresses[] =
39
40
41
42
43
44
{
	[CFI_UNLOCK_555_2AA] = { .unlock1 = 0x555, .unlock2 = 0x2aa },
	[CFI_UNLOCK_5555_2AAA] = { .unlock1 = 0x5555, .unlock2 = 0x2aaa },
};

/* CFI fixups foward declarations */
mifi's avatar
mifi committed
45
46
47
static void cfi_fixup_0002_erase_regions(flash_bank_t *flash, void *param);
static void cfi_fixup_0002_unlock_addresses(flash_bank_t *flash, void *param);
static void cfi_fixup_atmel_reversed_erase_regions(flash_bank_t *flash, void *param);
48
49

/* fixup after reading cmdset 0002 primary query table */
50
static const struct cfi_fixup cfi_0002_fixups[] = {
51
52
53
54
55
56
	{CFI_MFR_SST, 0x00D4, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
	{CFI_MFR_SST, 0x00D5, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
	{CFI_MFR_SST, 0x00D6, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
	{CFI_MFR_SST, 0x00D7, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
	{CFI_MFR_SST, 0x2780, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
	{CFI_MFR_ATMEL, 0x00C8, cfi_fixup_atmel_reversed_erase_regions, NULL},
57
	{CFI_MFR_FUJITSU, 0x226b, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
58
	{CFI_MFR_AMIC, 0xb31a, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_555_2AA]},
59
	{CFI_MFR_MX, 0x225b, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_555_2AA]},
60
	{CFI_MFR_AMD, 0x225b, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_555_2AA]},
61
62
63
64
65
	{CFI_MFR_ANY, CFI_ID_ANY, cfi_fixup_0002_erase_regions, NULL},
	{0, 0, NULL, NULL}
};

/* fixup after reading cmdset 0001 primary query table */
66
static const struct cfi_fixup cfi_0001_fixups[] = {
67
68
69
	{0, 0, NULL, NULL}
};

70
static void cfi_fixup(flash_bank_t *bank, const struct cfi_fixup *fixups)
71
{
72
	struct cfi_flash_bank *cfi_info = bank->driver_priv;
73
	const struct cfi_fixup *f;
74
75
76
77
78
79
80
81
82
83
84

	for (f = fixups; f->fixup; f++)
	{
		if (((f->mfr == CFI_MFR_ANY) || (f->mfr == cfi_info->manufacturer)) &&
			((f->id  == CFI_ID_ANY)  || (f->id  == cfi_info->device_id)))
		{
			f->fixup(bank, f->param);
		}
	}
}

85
86
/* inline uint32_t flash_address(flash_bank_t *bank, int sector, uint32_t offset) */
static __inline__ uint32_t flash_address(flash_bank_t *bank, int sector, uint32_t offset)
87
{
88
	struct cfi_flash_bank *cfi_info = bank->driver_priv;
89

zwelch's avatar
zwelch committed
90
	if (cfi_info->x16_as_x8) offset *= 2;
91

92
93
	/* while the sector list isn't built, only accesses to sector 0 work */
	if (sector == 0)
94
		return bank->base + offset * bank->bus_width;
95
96
97
98
	else
	{
		if (!bank->sectors)
		{
99
			LOG_ERROR("BUG: sector list not yet built");
100
101
			exit(-1);
		}
102
		return bank->base + bank->sectors[sector].offset + offset * bank->bus_width;
103
104
105
106
	}

}

107
static void cfi_command(flash_bank_t *bank, uint8_t cmd, uint8_t *cmd_buf)
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
{
	int i;

	/* clear whole buffer, to ensure bits that exceed the bus_width
	 * are set to zero
	 */
	for (i = 0; i < CFI_MAX_BUS_WIDTH; i++)
		cmd_buf[i] = 0;

	if (bank->target->endianness == TARGET_LITTLE_ENDIAN)
	{
		for (i = bank->bus_width; i > 0; i--)
		{
			*cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;
		}
	}
	else
	{
		for (i = 1; i <= bank->bus_width; i++)
		{
			*cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;
		}
	}
}

/* read unsigned 8-bit value from the bank
 * flash banks are expected to be made of similar chips
 * the query result should be the same for all
 */
137
static uint8_t cfi_query_u8(flash_bank_t *bank, int sector, uint32_t offset)
138
139
{
	target_t *target = bank->target;
140
	uint8_t data[CFI_MAX_BUS_WIDTH];
141

zwelch's avatar
zwelch committed
142
	target_read_memory(target, flash_address(bank, sector, offset), bank->bus_width, 1, data);
143
144
145
146
147
148
149
150
151
152
153

	if (bank->target->endianness == TARGET_LITTLE_ENDIAN)
		return data[0];
	else
		return data[bank->bus_width - 1];
}

/* read unsigned 8-bit value from the bank
 * in case of a bank made of multiple chips,
 * the individual values are ORed
 */
154
static uint8_t cfi_get_u8(flash_bank_t *bank, int sector, uint32_t offset)
155
156
{
	target_t *target = bank->target;
157
	uint8_t data[CFI_MAX_BUS_WIDTH];
158
159
	int i;

zwelch's avatar
zwelch committed
160
	target_read_memory(target, flash_address(bank, sector, offset), bank->bus_width, 1, data);
161
162
163
164
165
166
167
168
169
170

	if (bank->target->endianness == TARGET_LITTLE_ENDIAN)
	{
		for (i = 0; i < bank->bus_width / bank->chip_width; i++)
			data[0] |= data[i];

		return data[0];
	}
	else
	{
171
		uint8_t value = 0;
172
173
174
175
176
177
178
		for (i = 0; i < bank->bus_width / bank->chip_width; i++)
			value |= data[bank->bus_width - 1 - i];

		return value;
	}
}

179
static uint16_t cfi_query_u16(flash_bank_t *bank, int sector, uint32_t offset)
180
181
{
	target_t *target = bank->target;
182
	struct cfi_flash_bank *cfi_info = bank->driver_priv;
183
	uint8_t data[CFI_MAX_BUS_WIDTH * 2];
184

zwelch's avatar
zwelch committed
185
	if (cfi_info->x16_as_x8)
186
	{
187
		uint8_t i;
zwelch's avatar
zwelch committed
188
		for (i = 0;i < 2;i++)
zwelch's avatar
zwelch committed
189
			target_read_memory(target, flash_address(bank, sector, offset + i), bank->bus_width, 1,
190
				&data[i*bank->bus_width]);
191
192
	}
	else
zwelch's avatar
zwelch committed
193
		target_read_memory(target, flash_address(bank, sector, offset), bank->bus_width, 2, data);
194
195
196
197
198
199
200

	if (bank->target->endianness == TARGET_LITTLE_ENDIAN)
		return data[0] | data[bank->bus_width] << 8;
	else
		return data[bank->bus_width - 1] | data[(2 * bank->bus_width) - 1] << 8;
}

201
static uint32_t cfi_query_u32(flash_bank_t *bank, int sector, uint32_t offset)
202
203
{
	target_t *target = bank->target;
204
	struct cfi_flash_bank *cfi_info = bank->driver_priv;
205
	uint8_t data[CFI_MAX_BUS_WIDTH * 4];
206

zwelch's avatar
zwelch committed
207
	if (cfi_info->x16_as_x8)
208
	{
209
		uint8_t i;
zwelch's avatar
zwelch committed
210
		for (i = 0;i < 4;i++)
zwelch's avatar
zwelch committed
211
			target_read_memory(target, flash_address(bank, sector, offset + i), bank->bus_width, 1,
212
				&data[i*bank->bus_width]);
213
214
	}
	else
zwelch's avatar
zwelch committed
215
		target_read_memory(target, flash_address(bank, sector, offset), bank->bus_width, 4, data);
216
217
218
219
220
221
222
223

	if (bank->target->endianness == TARGET_LITTLE_ENDIAN)
		return data[0] | data[bank->bus_width] << 8 | data[bank->bus_width * 2] << 16 | data[bank->bus_width * 3] << 24;
	else
		return data[bank->bus_width - 1] | data[(2* bank->bus_width) - 1] << 8 |
				data[(3 * bank->bus_width) - 1] << 16 | data[(4 * bank->bus_width) - 1] << 24;
}

mifi's avatar
mifi committed
224
static void cfi_intel_clear_status_register(flash_bank_t *bank)
225
226
{
	target_t *target = bank->target;
227
	uint8_t command[8];
228
229
230

	if (target->state != TARGET_HALTED)
	{
231
		LOG_ERROR("BUG: attempted to clear status register while target wasn't halted");
232
233
234
235
		exit(-1);
	}

	cfi_command(bank, 0x50, command);
zwelch's avatar
zwelch committed
236
	target_write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
237
238
}

239
uint8_t cfi_intel_wait_status_busy(flash_bank_t *bank, int timeout)
240
{
241
	uint8_t status;
242
243
244

	while ((!((status = cfi_get_u8(bank, 0, 0x0)) & 0x80)) && (timeout-- > 0))
	{
245
		LOG_DEBUG("status: 0x%x", status);
246
		alive_sleep(1);
247
248
249
250
251
	}

	/* mask out bit 0 (reserved) */
	status = status & 0xfe;

252
	LOG_DEBUG("status: 0x%x", status);
253
254
255

	if ((status & 0x80) != 0x80)
	{
256
		LOG_ERROR("timeout while waiting for WSM to become ready");
257
258
259
	}
	else if (status != 0x80)
	{
260
		LOG_ERROR("status register: 0x%x", status);
261
		if (status & 0x2)
262
			LOG_ERROR("Block Lock-Bit Detected, Operation Abort");
263
		if (status & 0x4)
264
			LOG_ERROR("Program suspended");
265
		if (status & 0x8)
266
			LOG_ERROR("Low Programming Voltage Detected, Operation Aborted");
267
		if (status & 0x10)
268
			LOG_ERROR("Program Error / Error in Setting Lock-Bit");
269
		if (status & 0x20)
270
			LOG_ERROR("Error in Block Erasure or Clear Lock-Bits");
271
		if (status & 0x40)
272
			LOG_ERROR("Block Erase Suspended");
273
274
275
276
277
278
279
280
281

		cfi_intel_clear_status_register(bank);
	}

	return status;
}

int cfi_spansion_wait_status_busy(flash_bank_t *bank, int timeout)
{
282
	uint8_t status, oldstatus;
283
	struct cfi_flash_bank *cfi_info = bank->driver_priv;
284
285
286
287
288
289

	oldstatus = cfi_get_u8(bank, 0, 0x0);

	do {
		status = cfi_get_u8(bank, 0, 0x0);
		if ((status ^ oldstatus) & 0x40) {
290
			if (status & cfi_info->status_poll_mask & 0x20) {
291
292
293
				oldstatus = cfi_get_u8(bank, 0, 0x0);
				status = cfi_get_u8(bank, 0, 0x0);
				if ((status ^ oldstatus) & 0x40) {
294
					LOG_ERROR("dq5 timeout, status: 0x%x", status);
295
296
					return(ERROR_FLASH_OPERATION_FAILED);
				} else {
297
					LOG_DEBUG("status: 0x%x", status);
298
299
300
					return(ERROR_OK);
				}
			}
301
		} else { /* no toggle: finished, OK */
302
			LOG_DEBUG("status: 0x%x", status);
303
304
305
306
			return(ERROR_OK);
		}

		oldstatus = status;
307
		alive_sleep(1);
308
309
	} while (timeout-- > 0);

310
	LOG_ERROR("timeout, status: 0x%x", status);
311
312
313
314

	return(ERROR_FLASH_BUSY);
}

mifi's avatar
mifi committed
315
static int cfi_read_intel_pri_ext(flash_bank_t *bank)
316
{
317
	int retval;
318
	struct cfi_flash_bank *cfi_info = bank->driver_priv;
319
	struct cfi_intel_pri_ext *pri_ext = malloc(sizeof(struct cfi_intel_pri_ext));
320
	target_t *target = bank->target;
321
	uint8_t command[8];
322
323
324
325
326
327
328
329
330
331

	cfi_info->pri_ext = pri_ext;

	pri_ext->pri[0] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0);
	pri_ext->pri[1] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 1);
	pri_ext->pri[2] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 2);

	if ((pri_ext->pri[0] != 'P') || (pri_ext->pri[1] != 'R') || (pri_ext->pri[2] != 'I'))
	{
		cfi_command(bank, 0xf0, command);
zwelch's avatar
zwelch committed
332
		if ((retval = target_write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command)) != ERROR_OK)
333
334
335
		{
			return retval;
		}
336
		cfi_command(bank, 0xff, command);
zwelch's avatar
zwelch committed
337
		if ((retval = target_write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command)) != ERROR_OK)
338
339
340
		{
			return retval;
		}
341
		LOG_ERROR("Could not read bank flash bank information");
342
343
344
345
346
347
		return ERROR_FLASH_BANK_INVALID;
	}

	pri_ext->major_version = cfi_query_u8(bank, 0, cfi_info->pri_addr + 3);
	pri_ext->minor_version = cfi_query_u8(bank, 0, cfi_info->pri_addr + 4);

348
	LOG_DEBUG("pri: '%c%c%c', version: %c.%c", pri_ext->pri[0], pri_ext->pri[1], pri_ext->pri[2], pri_ext->major_version, pri_ext->minor_version);
349
350
351
352
353

	pri_ext->feature_support = cfi_query_u32(bank, 0, cfi_info->pri_addr + 5);
	pri_ext->suspend_cmd_support = cfi_query_u8(bank, 0, cfi_info->pri_addr + 9);
	pri_ext->blk_status_reg_mask = cfi_query_u16(bank, 0, cfi_info->pri_addr + 0xa);

354
355
356
	LOG_DEBUG("feature_support: 0x%" PRIx32 ", suspend_cmd_support: 0x%x, blk_status_reg_mask: 0x%x",
		  pri_ext->feature_support,
		  pri_ext->suspend_cmd_support,
duane's avatar
duane committed
357
		  pri_ext->blk_status_reg_mask);
358
359
360
361

	pri_ext->vcc_optimal = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0xc);
	pri_ext->vpp_optimal = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0xd);

362
	LOG_DEBUG("Vcc opt: %1.1x.%1.1x, Vpp opt: %1.1x.%1.1x",
363
364
365
366
367
368
		  (pri_ext->vcc_optimal & 0xf0) >> 4, pri_ext->vcc_optimal & 0x0f,
		  (pri_ext->vpp_optimal & 0xf0) >> 4, pri_ext->vpp_optimal & 0x0f);

	pri_ext->num_protection_fields = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0xe);
	if (pri_ext->num_protection_fields != 1)
	{
369
		LOG_WARNING("expected one protection register field, but found %i", pri_ext->num_protection_fields);
370
371
372
373
374
375
	}

	pri_ext->prot_reg_addr = cfi_query_u16(bank, 0, cfi_info->pri_addr + 0xf);
	pri_ext->fact_prot_reg_size = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0x11);
	pri_ext->user_prot_reg_size = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0x12);

376
	LOG_DEBUG("protection_fields: %i, prot_reg_addr: 0x%x, factory pre-programmed: %i, user programmable: %i", pri_ext->num_protection_fields, pri_ext->prot_reg_addr, 1 << pri_ext->fact_prot_reg_size, 1 << pri_ext->user_prot_reg_size);
377
378
379
380

	return ERROR_OK;
}

mifi's avatar
mifi committed
381
static int cfi_read_spansion_pri_ext(flash_bank_t *bank)
382
{
383
	int retval;
384
	struct cfi_flash_bank *cfi_info = bank->driver_priv;
385
	struct cfi_spansion_pri_ext *pri_ext = malloc(sizeof(struct cfi_spansion_pri_ext));
386
	target_t *target = bank->target;
387
	uint8_t command[8];
388
389
390
391
392
393
394
395
396
397

	cfi_info->pri_ext = pri_ext;

	pri_ext->pri[0] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0);
	pri_ext->pri[1] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 1);
	pri_ext->pri[2] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 2);

	if ((pri_ext->pri[0] != 'P') || (pri_ext->pri[1] != 'R') || (pri_ext->pri[2] != 'I'))
	{
		cfi_command(bank, 0xf0, command);
zwelch's avatar
zwelch committed
398
		if ((retval = target_write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command)) != ERROR_OK)
399
400
401
		{
			return retval;
		}
402
		LOG_ERROR("Could not read spansion bank information");
403
404
405
406
407
408
		return ERROR_FLASH_BANK_INVALID;
	}

	pri_ext->major_version = cfi_query_u8(bank, 0, cfi_info->pri_addr + 3);
	pri_ext->minor_version = cfi_query_u8(bank, 0, cfi_info->pri_addr + 4);

409
	LOG_DEBUG("pri: '%c%c%c', version: %c.%c", pri_ext->pri[0], pri_ext->pri[1], pri_ext->pri[2], pri_ext->major_version, pri_ext->minor_version);
410
411
412
413
414
415
416
417
418
419
420
421
422

	pri_ext->SiliconRevision = cfi_query_u8(bank, 0, cfi_info->pri_addr + 5);
	pri_ext->EraseSuspend    = cfi_query_u8(bank, 0, cfi_info->pri_addr + 6);
	pri_ext->BlkProt         = cfi_query_u8(bank, 0, cfi_info->pri_addr + 7);
	pri_ext->TmpBlkUnprotect = cfi_query_u8(bank, 0, cfi_info->pri_addr + 8);
	pri_ext->BlkProtUnprot   = cfi_query_u8(bank, 0, cfi_info->pri_addr + 9);
	pri_ext->SimultaneousOps = cfi_query_u8(bank, 0, cfi_info->pri_addr + 10);
	pri_ext->BurstMode       = cfi_query_u8(bank, 0, cfi_info->pri_addr + 11);
	pri_ext->PageMode        = cfi_query_u8(bank, 0, cfi_info->pri_addr + 12);
	pri_ext->VppMin          = cfi_query_u8(bank, 0, cfi_info->pri_addr + 13);
	pri_ext->VppMax          = cfi_query_u8(bank, 0, cfi_info->pri_addr + 14);
	pri_ext->TopBottom       = cfi_query_u8(bank, 0, cfi_info->pri_addr + 15);

423
	LOG_DEBUG("Silicon Revision: 0x%x, Erase Suspend: 0x%x, Block protect: 0x%x", pri_ext->SiliconRevision,
424
425
	      pri_ext->EraseSuspend, pri_ext->BlkProt);

426
	LOG_DEBUG("Temporary Unprotect: 0x%x, Block Protect Scheme: 0x%x, Simultaneous Ops: 0x%x", pri_ext->TmpBlkUnprotect,
427
428
	      pri_ext->BlkProtUnprot, pri_ext->SimultaneousOps);

429
	LOG_DEBUG("Burst Mode: 0x%x, Page Mode: 0x%x, ", pri_ext->BurstMode, pri_ext->PageMode);
430
431


432
	LOG_DEBUG("Vpp min: %2.2d.%1.1d, Vpp max: %2.2d.%1.1x",
433
434
435
		  (pri_ext->VppMin & 0xf0) >> 4, pri_ext->VppMin & 0x0f,
		  (pri_ext->VppMax & 0xf0) >> 4, pri_ext->VppMax & 0x0f);

436
	LOG_DEBUG("WP# protection 0x%x", pri_ext->TopBottom);
437
438
439
440
441
442
443
444
445

	/* default values for implementation specific workarounds */
	pri_ext->_unlock1 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock1;
	pri_ext->_unlock2 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock2;
	pri_ext->_reversed_geometry = 0;

	return ERROR_OK;
}

mifi's avatar
mifi committed
446
static int cfi_read_atmel_pri_ext(flash_bank_t *bank)
447
{
448
	int retval;
449
	struct cfi_atmel_pri_ext atmel_pri_ext;
450
	struct cfi_flash_bank *cfi_info = bank->driver_priv;
451
	struct cfi_spansion_pri_ext *pri_ext = malloc(sizeof(struct cfi_spansion_pri_ext));
452
	target_t *target = bank->target;
453
	uint8_t command[8];
454
455
456
457
458
459

	/* ATMEL devices use the same CFI primary command set (0x2) as AMD/Spansion,
	 * but a different primary extended query table.
	 * We read the atmel table, and prepare a valid AMD/Spansion query table.
	 */

460
	memset(pri_ext, 0, sizeof(struct cfi_spansion_pri_ext));
461
462
463
464
465
466
467
468
469
470

	cfi_info->pri_ext = pri_ext;

	atmel_pri_ext.pri[0] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0);
	atmel_pri_ext.pri[1] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 1);
	atmel_pri_ext.pri[2] = cfi_query_u8(bank, 0, cfi_info->pri_addr + 2);

	if ((atmel_pri_ext.pri[0] != 'P') || (atmel_pri_ext.pri[1] != 'R') || (atmel_pri_ext.pri[2] != 'I'))
	{
		cfi_command(bank, 0xf0, command);
zwelch's avatar
zwelch committed
471
		if ((retval = target_write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command)) != ERROR_OK)
472
473
474
		{
			return retval;
		}
475
		LOG_ERROR("Could not read atmel bank information");
476
477
478
479
480
481
482
483
484
485
		return ERROR_FLASH_BANK_INVALID;
	}

	pri_ext->pri[0] = atmel_pri_ext.pri[0];
	pri_ext->pri[1] = atmel_pri_ext.pri[1];
	pri_ext->pri[2] = atmel_pri_ext.pri[2];

	atmel_pri_ext.major_version = cfi_query_u8(bank, 0, cfi_info->pri_addr + 3);
	atmel_pri_ext.minor_version = cfi_query_u8(bank, 0, cfi_info->pri_addr + 4);

486
	LOG_DEBUG("pri: '%c%c%c', version: %c.%c", atmel_pri_ext.pri[0], atmel_pri_ext.pri[1], atmel_pri_ext.pri[2], atmel_pri_ext.major_version, atmel_pri_ext.minor_version);
487
488
489
490
491
492
493
494
495

	pri_ext->major_version = atmel_pri_ext.major_version;
	pri_ext->minor_version = atmel_pri_ext.minor_version;

	atmel_pri_ext.features = cfi_query_u8(bank, 0, cfi_info->pri_addr + 5);
	atmel_pri_ext.bottom_boot = cfi_query_u8(bank, 0, cfi_info->pri_addr + 6);
	atmel_pri_ext.burst_mode = cfi_query_u8(bank, 0, cfi_info->pri_addr + 7);
	atmel_pri_ext.page_mode = cfi_query_u8(bank, 0, cfi_info->pri_addr + 8);

496
	LOG_DEBUG("features: 0x%2.2x, bottom_boot: 0x%2.2x, burst_mode: 0x%2.2x, page_mode: 0x%2.2x",
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
		atmel_pri_ext.features, atmel_pri_ext.bottom_boot, atmel_pri_ext.burst_mode, atmel_pri_ext.page_mode);

	if (atmel_pri_ext.features & 0x02)
		pri_ext->EraseSuspend = 2;

	if (atmel_pri_ext.bottom_boot)
		pri_ext->TopBottom = 2;
	else
		pri_ext->TopBottom = 3;

	pri_ext->_unlock1 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock1;
	pri_ext->_unlock2 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock2;

	return ERROR_OK;
}

mifi's avatar
mifi committed
513
static int cfi_read_0002_pri_ext(flash_bank_t *bank)
514
{
515
	struct cfi_flash_bank *cfi_info = bank->driver_priv;
516
517
518
519
520
521
522
523
524
525
526

	if (cfi_info->manufacturer == CFI_MFR_ATMEL)
	{
		return cfi_read_atmel_pri_ext(bank);
	}
	else
	{
		return cfi_read_spansion_pri_ext(bank);
	}
}

mifi's avatar
mifi committed
527
static int cfi_spansion_info(struct flash_bank_s *bank, char *buf, int buf_size)
528
529
{
	int printed;
530
	struct cfi_flash_bank *cfi_info = bank->driver_priv;
531
	struct cfi_spansion_pri_ext *pri_ext = cfi_info->pri_ext;
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561

	printed = snprintf(buf, buf_size, "\nSpansion primary algorithm extend information:\n");
	buf += printed;
	buf_size -= printed;

	printed = snprintf(buf, buf_size, "pri: '%c%c%c', version: %c.%c\n", pri_ext->pri[0],
			   pri_ext->pri[1], pri_ext->pri[2],
			   pri_ext->major_version, pri_ext->minor_version);
	buf += printed;
	buf_size -= printed;

	printed = snprintf(buf, buf_size, "Silicon Rev.: 0x%x, Address Sensitive unlock: 0x%x\n",
			   (pri_ext->SiliconRevision) >> 2,
			   (pri_ext->SiliconRevision) & 0x03);
	buf += printed;
	buf_size -= printed;

	printed = snprintf(buf, buf_size, "Erase Suspend: 0x%x, Sector Protect: 0x%x\n",
			   pri_ext->EraseSuspend,
			   pri_ext->BlkProt);
	buf += printed;
	buf_size -= printed;

	printed = snprintf(buf, buf_size, "VppMin: %2.2d.%1.1x, VppMax: %2.2d.%1.1x\n",
		(pri_ext->VppMin & 0xf0) >> 4, pri_ext->VppMin & 0x0f,
		(pri_ext->VppMax & 0xf0) >> 4, pri_ext->VppMax & 0x0f);

	return ERROR_OK;
}

mifi's avatar
mifi committed
562
static int cfi_intel_info(struct flash_bank_s *bank, char *buf, int buf_size)
563
564
{
	int printed;
565
	struct cfi_flash_bank *cfi_info = bank->driver_priv;
566
	struct cfi_intel_pri_ext *pri_ext = cfi_info->pri_ext;
567
568
569
570
571
572
573
574
575

	printed = snprintf(buf, buf_size, "\nintel primary algorithm extend information:\n");
	buf += printed;
	buf_size -= printed;

	printed = snprintf(buf, buf_size, "pri: '%c%c%c', version: %c.%c\n", pri_ext->pri[0], pri_ext->pri[1], pri_ext->pri[2], pri_ext->major_version, pri_ext->minor_version);
	buf += printed;
	buf_size -= printed;

duane's avatar
duane committed
576
	printed = snprintf(buf, buf_size, "feature_support: 0x%" PRIx32 ", suspend_cmd_support: 0x%x, blk_status_reg_mask: 0x%x\n", pri_ext->feature_support, pri_ext->suspend_cmd_support, pri_ext->blk_status_reg_mask);
577
578
579
580
581
582
583
584
585
586
587
588
589
590
	buf += printed;
	buf_size -= printed;

	printed = snprintf(buf, buf_size, "Vcc opt: %1.1x.%1.1x, Vpp opt: %1.1x.%1.1x\n",
		(pri_ext->vcc_optimal & 0xf0) >> 4, pri_ext->vcc_optimal & 0x0f,
		(pri_ext->vpp_optimal & 0xf0) >> 4, pri_ext->vpp_optimal & 0x0f);
	buf += printed;
	buf_size -= printed;

	printed = snprintf(buf, buf_size, "protection_fields: %i, prot_reg_addr: 0x%x, factory pre-programmed: %i, user programmable: %i\n", pri_ext->num_protection_fields, pri_ext->prot_reg_addr, 1 << pri_ext->fact_prot_reg_size, 1 << pri_ext->user_prot_reg_size);

	return ERROR_OK;
}

mifi's avatar
mifi committed
591
static int cfi_register_commands(struct command_context_s *cmd_ctx)
592
593
594
595
596
597
598
599
600
601
602
603
{
	/*command_t *cfi_cmd = */
	register_command(cmd_ctx, NULL, "cfi", NULL, COMMAND_ANY, "flash bank cfi <base> <size> <chip_width> <bus_width> <targetNum> [jedec_probe/x16_as_x8]");
	/*
	register_command(cmd_ctx, cfi_cmd, "part_id", cfi_handle_part_id_command, COMMAND_EXEC,
					 "print part id of cfi flash bank <num>");
	*/
	return ERROR_OK;
}

/* flash_bank cfi <base> <size> <chip_width> <bus_width> <target#> [options]
 */
604
FLASH_BANK_COMMAND_HANDLER(cfi_flash_bank_command)
605
{
606
	struct cfi_flash_bank *cfi_info;
607
608
609

	if (argc < 6)
	{
610
		LOG_WARNING("incomplete flash_bank cfi configuration");
611
612
613
		return ERROR_FLASH_BANK_INVALID;
	}

614
615
616
617
618
619
	uint16_t chip_width, bus_width;
	COMMAND_PARSE_NUMBER(u16, args[3], bus_width);
	COMMAND_PARSE_NUMBER(u16, args[4], chip_width);

	if ((chip_width > CFI_MAX_CHIP_WIDTH)
			|| (bus_width > CFI_MAX_BUS_WIDTH))
620
	{
621
		LOG_ERROR("chip and bus width have to specified in bytes");
622
623
624
		return ERROR_FLASH_BANK_INVALID;
	}

625
	cfi_info = malloc(sizeof(struct cfi_flash_bank));
626
627
628
629
630
631
632
633
634
	cfi_info->probed = 0;
	bank->driver_priv = cfi_info;

	cfi_info->write_algorithm = NULL;

	cfi_info->x16_as_x8 = 0;
	cfi_info->jedec_probe = 0;
	cfi_info->not_cfi = 0;

635
	for (unsigned i = 6; i < argc; i++)
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
	{
		if (strcmp(args[i], "x16_as_x8") == 0)
		{
			cfi_info->x16_as_x8 = 1;
		}
		else if (strcmp(args[i], "jedec_probe") == 0)
		{
			cfi_info->jedec_probe = 1;
		}
	}

	cfi_info->write_algorithm = NULL;

	/* bank wasn't probed yet */
	cfi_info->qry[0] = -1;

	return ERROR_OK;
}

mifi's avatar
mifi committed
655
static int cfi_intel_erase(struct flash_bank_s *bank, int first, int last)
656
{
657
	int retval;
658
	struct cfi_flash_bank *cfi_info = bank->driver_priv;
659
	target_t *target = bank->target;
660
	uint8_t command[8];
661
662
663
664
665
666
667
	int i;

	cfi_intel_clear_status_register(bank);

	for (i = first; i <= last; i++)
	{
		cfi_command(bank, 0x20, command);
zwelch's avatar
zwelch committed
668
		if ((retval = target_write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command)) != ERROR_OK)
669
670
671
		{
			return retval;
		}
672
673

		cfi_command(bank, 0xd0, command);
zwelch's avatar
zwelch committed
674
		if ((retval = target_write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command)) != ERROR_OK)
675
676
677
		{
			return retval;
		}
678
679
680
681
682
683

		if (cfi_intel_wait_status_busy(bank, 1000 * (1 << cfi_info->block_erase_timeout_typ)) == 0x80)
			bank->sectors[i].is_erased = 1;
		else
		{
			cfi_command(bank, 0xff, command);
zwelch's avatar
zwelch committed
684
			if ((retval = target_write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command)) != ERROR_OK)
685
686
687
			{
				return retval;
			}
688

duane's avatar
duane committed
689
			LOG_ERROR("couldn't erase block %i of flash bank at base 0x%" PRIx32 , i, bank->base);
690
691
692
693
694
			return ERROR_FLASH_OPERATION_FAILED;
		}
	}

	cfi_command(bank, 0xff, command);
zwelch's avatar
zwelch committed
695
	return target_write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
696
697
698

}

mifi's avatar
mifi committed
699
static int cfi_spansion_erase(struct flash_bank_s *bank, int first, int last)
700
{
701
	int retval;
702
	struct cfi_flash_bank *cfi_info = bank->driver_priv;
703
	struct cfi_spansion_pri_ext *pri_ext = cfi_info->pri_ext;
704
	target_t *target = bank->target;
705
	uint8_t command[8];
706
707
708
709
710
	int i;

	for (i = first; i <= last; i++)
	{
		cfi_command(bank, 0xaa, command);
zwelch's avatar
zwelch committed
711
		if ((retval = target_write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command)) != ERROR_OK)
712
713
714
		{
			return retval;
		}
715
716

		cfi_command(bank, 0x55, command);
zwelch's avatar
zwelch committed
717
		if ((retval = target_write_memory(target, flash_address(bank, 0, pri_ext->_unlock2), bank->bus_width, 1, command)) != ERROR_OK)
718
719
720
		{
			return retval;
		}
721
722

		cfi_command(bank, 0x80, command);
zwelch's avatar
zwelch committed
723
		if ((retval = target_write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command)) != ERROR_OK)
724
725
726
		{
			return retval;
		}
727
728

		cfi_command(bank, 0xaa, command);
zwelch's avatar
zwelch committed
729
		if ((retval = target_write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command)) != ERROR_OK)
730
731
732
		{
			return retval;
		}
733
734

		cfi_command(bank, 0x55, command);
zwelch's avatar
zwelch committed
735
		if ((retval = target_write_memory(target, flash_address(bank, 0, pri_ext->_unlock2), bank->bus_width, 1, command)) != ERROR_OK)
736
737
738
		{
			return retval;
		}
739
740

		cfi_command(bank, 0x30, command);
zwelch's avatar
zwelch committed
741
		if ((retval = target_write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command)) != ERROR_OK)
742
743
744
		{
			return retval;
		}
745
746
747
748
749
750

		if (cfi_spansion_wait_status_busy(bank, 1000 * (1 << cfi_info->block_erase_timeout_typ)) == ERROR_OK)
			bank->sectors[i].is_erased = 1;
		else
		{
			cfi_command(bank, 0xf0, command);
zwelch's avatar
zwelch committed
751
			if ((retval = target_write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command)) != ERROR_OK)
752
753
754
			{
				return retval;
			}
755

duane's avatar
duane committed
756
			LOG_ERROR("couldn't erase block %i of flash bank at base 0x%" PRIx32, i, bank->base);
757
758
759
760
761
			return ERROR_FLASH_OPERATION_FAILED;
		}
	}

	cfi_command(bank, 0xf0, command);
zwelch's avatar
zwelch committed
762
	return target_write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
763
764
}

mifi's avatar
mifi committed
765
static int cfi_erase(struct flash_bank_s *bank, int first, int last)
766
{
767
	struct cfi_flash_bank *cfi_info = bank->driver_priv;
768
769
770

	if (bank->target->state != TARGET_HALTED)
	{
oharboe's avatar
oharboe committed
771
		LOG_ERROR("Target not halted");
772
773
774
775
776
777
778
779
780
781
782
		return ERROR_TARGET_NOT_HALTED;
	}

	if ((first < 0) || (last < first) || (last >= bank->num_sectors))
	{
		return ERROR_FLASH_SECTOR_INVALID;
	}

	if (cfi_info->qry[0] != 'Q')
		return ERROR_FLASH_BANK_NOT_PROBED;

zwelch's avatar
zwelch committed
783
	switch (cfi_info->pri_id)
784
785
786
787
788
789
790
791
792
	{
		case 1:
		case 3:
			return cfi_intel_erase(bank, first, last);
			break;
		case 2:
			return cfi_spansion_erase(bank, first, last);
			break;
		default:
793
			LOG_ERROR("cfi primary command set %i unsupported", cfi_info->pri_id);
794
795
796
797
798
799
			break;
	}

	return ERROR_OK;
}

mifi's avatar
mifi committed
800
static int cfi_intel_protect(struct flash_bank_s *bank, int set, int first, int last)
801
{
802
	int retval;
803
	struct cfi_flash_bank *cfi_info = bank->driver_priv;
804
	struct cfi_intel_pri_ext *pri_ext = cfi_info->pri_ext;
805
	target_t *target = bank->target;
806
	uint8_t command[8];
807
808
809
810
811
812
813
814
815
816
817
818
819
820
	int retry = 0;
	int i;

	/* if the device supports neither legacy lock/unlock (bit 3) nor
	 * instant individual block locking (bit 5).
	 */
	if (!(pri_ext->feature_support & 0x28))
		return ERROR_FLASH_OPERATION_FAILED;

	cfi_intel_clear_status_register(bank);

	for (i = first; i <= last; i++)
	{
		cfi_command(bank, 0x60, command);
duane's avatar
duane committed
821
		LOG_DEBUG("address: 0x%4.4" PRIx32 ", command: 0x%4.4" PRIx32, flash_address(bank, i, 0x0), target_buffer_get_u32(target, command));
zwelch's avatar
zwelch committed
822
		if ((retval = target_write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command)) != ERROR_OK)
823
824
825
		{
			return retval;
		}
826
827
828
		if (set)
		{
			cfi_command(bank, 0x01, command);
duane's avatar
duane committed
829
			LOG_DEBUG("address: 0x%4.4" PRIx32 ", command: 0x%4.4" PRIx32 , flash_address(bank, i, 0x0), target_buffer_get_u32(target, command));
zwelch's avatar
zwelch committed
830
			if ((retval = target_write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command)) != ERROR_OK)
831
832
833
			{
				return retval;
			}
834
835
836
837
838
			bank->sectors[i].is_protected = 1;
		}
		else
		{
			cfi_command(bank, 0xd0, command);
duane's avatar
duane committed
839
			LOG_DEBUG("address: 0x%4.4" PRIx32 ", command: 0x%4.4" PRIx32, flash_address(bank, i, 0x0), target_buffer_get_u32(target, command));
zwelch's avatar
zwelch committed
840
			if ((retval = target_write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command)) != ERROR_OK)
841
842
843
			{
				return retval;
			}
844
845
846
847
848
849
850
851
852
853
854
			bank->sectors[i].is_protected = 0;
		}

		/* instant individual block locking doesn't require reading of the status register */
		if (!(pri_ext->feature_support & 0x20))
		{
			/* Clear lock bits operation may take up to 1.4s */
			cfi_intel_wait_status_busy(bank, 1400);
		}
		else
		{
855
			uint8_t block_status;
856
857
			/* read block lock bit, to verify status */
			cfi_command(bank, 0x90, command);
zwelch's avatar
zwelch committed
858
			if ((retval = target_write_memory(target, flash_address(bank, 0, 0x55), bank->bus_width, 1, command)) != ERROR_OK)
859
860
861
			{
				return retval;
			}
862
863
864
865
			block_status = cfi_get_u8(bank, i, 0x2);

			if ((block_status & 0x1) != set)
			{
866
				LOG_ERROR("couldn't change block lock status (set = %i, block_status = 0x%2.2x)", set, block_status);
867
				cfi_command(bank, 0x70, command);
zwelch's avatar
zwelch committed
868
				if ((retval = target_write_memory(target, flash_address(bank, 0, 0x55), bank->bus_width, 1, command)) != ERROR_OK)
869
870
871
				{
					return retval;
				}
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
				cfi_intel_wait_status_busy(bank, 10);

				if (retry > 10)
					return ERROR_FLASH_OPERATION_FAILED;
				else
				{
					i--;
					retry++;
				}
			}
		}
	}

	/* if the device doesn't support individual block lock bits set/clear,
	 * all blocks have been unlocked in parallel, so we set those that should be protected
	 */
	if ((!set) && (!(pri_ext->feature_support & 0x20)))
	{
		for (i = 0; i < bank->num_sectors; i++)
		{
			if (bank->sectors[i].is_protected == 1)
			{
				cfi_intel_clear_status_register(bank);

				cfi_command(bank, 0x60, command);
zwelch's avatar
zwelch committed
897
				if ((retval = target_write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command)) != ERROR_OK)
898
899
900
				{
					return retval;
				}
901
902

				cfi_command(bank, 0x01, command);
zwelch's avatar
zwelch committed
903
				if ((retval = target_write_memory(target, flash_address(bank, i, 0x0), bank->bus_width, 1, command)) != ERROR_OK)
904
905
906
				{
					return retval;
				}
907
908
909
910
911
912
913

				cfi_intel_wait_status_busy(bank, 100);
			}
		}
	}

	cfi_command(bank, 0xff, command);
zwelch's avatar
zwelch committed
914
	return target_write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command);
915
916
}

mifi's avatar
mifi committed
917
static int cfi_protect(struct flash_bank_s *bank, int set, int first, int last)
918
{
919
	struct cfi_flash_bank *cfi_info = bank->driver_priv;
920
921
922

	if (bank->target->state != TARGET_HALTED)
	{
oharboe's avatar
oharboe committed
923
		LOG_ERROR("Target not halted");
924
925
926
927
928
929
930
931
932
933
934
		return ERROR_TARGET_NOT_HALTED;
	}

	if ((first < 0) || (last < first) || (last >= bank->num_sectors))
	{
		return ERROR_FLASH_SECTOR_INVALID;
	}

	if (cfi_info->qry[0] != 'Q')
		return ERROR_FLASH_BANK_NOT_PROBED;

zwelch's avatar
zwelch committed
935
	switch (cfi_info->pri_id)
936
937
938
939
940
941
	{
		case 1:
		case 3:
			cfi_intel_protect(bank, set, first, last);
			break;
		default:
942
			LOG_ERROR("protect: cfi primary command set %i unsupported", cfi_info->pri_id);
943
944
945
946
947
948
949
			break;
	}

	return ERROR_OK;
}

/* FIXME Replace this by a simple memcpy() - still unsure about sideeffects */
950
static void cfi_add_byte(struct flash_bank_s *bank, uint8_t *word, uint8_t byte)
951
{
952
	/* target_t *target = bank->target; */
953
954
955

	int i;

956
957
958
	/* NOTE:
	 * The data to flash must not be changed in endian! We write a bytestrem in
	 * target byte order already. Only the control and status byte lane of the flash
959
	 * WSM is interpreted by the CPU in different ways, when read a uint16_t or uint32_t
zwelch's avatar
zwelch committed
960
	 * word (data seems to be in the upper or lower byte lane for uint16_t accesses).
961
	 */
962

963
964
965
966
#if 0
	if (target->endianness == TARGET_LITTLE_ENDIAN)
	{
#endif
967
968
969
970
		/* shift bytes */
		for (i = 0; i < bank->bus_width - 1; i++)
			word[i] = word[i + 1];
		word[bank->bus_width - 1] = byte;
971
972
973
974
975
976
977
978
979
980
#if 0
	}
	else
	{
		/* shift bytes */
		for (i = bank->bus_width - 1; i > 0; i--)
			word[i] = word[i - 1];
		word[0] = byte;
	}
#endif
981
982
983
}

/* Convert code image to target endian */
984
/* FIXME create general block conversion fcts in target.c?) */
985
static void cfi_fix_code_endian(target_t *target, uint8_t *dest, const uint32_t *src, uint32_t count)
986
{
987
	uint32_t i;
zwelch's avatar
zwelch committed
988
	for (i = 0; i< count; i++)
989
	{
990
		target_buffer_set_u32(target, dest, *src);
zwelch's avatar
zwelch committed
991
		dest += 4;
992
993
994
995
		src++;
	}
}

996
static uint32_t cfi_command_val(flash_bank_t *bank, uint8_t cmd)
997
998
999
{
	target_t *target = bank->target;

1000
	uint8_t buf[CFI_MAX_BUS_WIDTH];
For faster browsing, not all history is shown. View entire blame