795f60da188a75487fbf6cdc169f43d6c3aa57e9
[openocd.git] / src / flash / nor / non_cfi.c
1 /***************************************************************************
2 * Copyright (C) 2007 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * Copyright (C) 2009 Michael Schwingen *
5 * michael@schwingen.org *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the *
19 * Free Software Foundation, Inc., *
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21 ***************************************************************************/
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "imp.h"
27 #include "cfi.h"
28 #include "non_cfi.h"
29
30
31 #define KB 1024
32 #define MB (1024*1024)
33 #define ERASE_REGION(num, size) (((size/256) << 16) | (num-1))
34
35 /* non-CFI compatible flashes */
36 static struct non_cfi non_cfi_flashes[] = {
37 {
38 .mfr = CFI_MFR_SST,
39 .id = 0xd4,
40 .pri_id = 0x02,
41 .dev_size = 64*KB,
42 .interface_desc = 0x0, /* x8 only device */
43 .max_buf_write_size = 0x0,
44 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
45 .num_erase_regions = 1,
46 .erase_region_info =
47 {
48 ERASE_REGION(16, 4*KB)
49 }
50 },
51 {
52 .mfr = CFI_MFR_SST,
53 .id = 0xd5,
54 .pri_id = 0x02,
55 .dev_size = 128*KB,
56 .interface_desc = 0x0, /* x8 only device */
57 .max_buf_write_size = 0x0,
58 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
59 .num_erase_regions = 1,
60 .erase_region_info =
61 {
62 ERASE_REGION(32, 4*KB)
63 }
64 },
65 {
66 .mfr = CFI_MFR_SST,
67 .id = 0xd6,
68 .pri_id = 0x02,
69 .dev_size = 256*KB,
70 .interface_desc = 0x0, /* x8 only device */
71 .max_buf_write_size = 0x0,
72 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
73 .num_erase_regions = 1,
74 .erase_region_info =
75 {
76 ERASE_REGION(64, 4*KB)
77 }
78 },
79 {
80 .mfr = CFI_MFR_SST,
81 .id = 0xd7,
82 .pri_id = 0x02,
83 .dev_size = 512*KB,
84 .interface_desc = 0x0, /* x8 only device */
85 .max_buf_write_size = 0x0,
86 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
87 .num_erase_regions = 1,
88 .erase_region_info =
89 {
90 ERASE_REGION(128, 4*KB)
91 }
92 },
93 {
94 .mfr = CFI_MFR_SST,
95 .id = 0x2780,
96 .pri_id = 0x02,
97 .dev_size = 512*KB,
98 .interface_desc = 0x2, /* x8 or x16 device */
99 .max_buf_write_size = 0x0,
100 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
101 .num_erase_regions = 1,
102 .erase_region_info =
103 {
104 ERASE_REGION(128, 4*KB)
105 }
106 },
107 {
108 .mfr = CFI_MFR_ST,
109 .id = 0xd6, /* ST29F400BB */
110 .pri_id = 0x02,
111 .dev_size = 512*KB,
112 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
113 .max_buf_write_size = 0x0,
114 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
115 .num_erase_regions = 4,
116 .erase_region_info =
117 {
118 ERASE_REGION(1, 16*KB),
119 ERASE_REGION(2, 8*KB),
120 ERASE_REGION(1, 32*KB),
121 ERASE_REGION(7, 64*KB)
122 }
123 },
124 {
125 .mfr = CFI_MFR_ST,
126 .id = 0xd5, /* ST29F400BT */
127 .pri_id = 0x02,
128 .dev_size = 512*KB,
129 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
130 .max_buf_write_size = 0x0,
131 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
132 .num_erase_regions = 4,
133 .erase_region_info =
134 {
135 ERASE_REGION(7, 64*KB),
136 ERASE_REGION(1, 32*KB),
137 ERASE_REGION(2, 8*KB),
138 ERASE_REGION(1, 16*KB)
139 }
140 },
141
142 /* SST 39VF* do not support DQ5 status polling - this currently is
143 only supported by the host algorithm, not by the target code using
144 the work area.
145 Only true for 8-bit and 32-bit wide memories. 16-bit wide memories
146 without DQ5 status polling are supported by the target code.
147 */
148 {
149 .mfr = CFI_MFR_SST,
150 .id = 0x2782, /* SST39xF160 */
151 .pri_id = 0x02,
152 .dev_size = 2*MB,
153 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
154 .max_buf_write_size = 0x0,
155 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
156 .num_erase_regions = 1,
157 .erase_region_info =
158 {
159 ERASE_REGION(512, 4*KB)
160 }
161 },
162 {
163 .mfr = CFI_MFR_SST,
164 .id = 0x2783, /* SST39VF320 */
165 .pri_id = 0x02,
166 .dev_size = 4*MB,
167 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
168 .max_buf_write_size = 0x0,
169 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
170 .num_erase_regions = 1,
171 .erase_region_info =
172 {
173 ERASE_REGION(1024, 4*KB)
174 }
175 },
176 {
177 .mfr = CFI_MFR_SST,
178 .id = 0x234b, /* SST39VF1601 */
179 .pri_id = 0x02,
180 .dev_size = 2*MB,
181 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
182 .max_buf_write_size = 0x0,
183 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
184 .num_erase_regions = 1,
185 .erase_region_info =
186 {
187 ERASE_REGION(512, 4*KB)
188 }
189 },
190 {
191 .mfr = CFI_MFR_SST,
192 .id = 0x234a, /* SST39VF1602 */
193 .pri_id = 0x02,
194 .dev_size = 2*MB,
195 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
196 .max_buf_write_size = 0x0,
197 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
198 .num_erase_regions = 1,
199 .erase_region_info =
200 {
201 ERASE_REGION(512, 4*KB)
202 }
203 },
204 {
205 .mfr = CFI_MFR_SST,
206 .id = 0x235b, /* SST39VF3201 */
207 .pri_id = 0x02,
208 .dev_size = 4*MB,
209 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
210 .max_buf_write_size = 0x0,
211 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
212 .num_erase_regions = 1,
213 .erase_region_info =
214 {
215 ERASE_REGION(1024, 4*KB)
216 }
217 },
218 {
219 .mfr = CFI_MFR_SST,
220 .id = 0x235a, /* SST39VF3202 */
221 .pri_id = 0x02,
222 .dev_size = 4*MB,
223 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
224 .max_buf_write_size = 0x0,
225 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
226 .num_erase_regions = 1,
227 .erase_region_info =
228 {
229 ERASE_REGION(1024, 4*KB)
230 }
231 },
232 {
233 .mfr = CFI_MFR_SST,
234 .id = 0x236d, /* SST39VF6401B */
235 .pri_id = 0x02,
236 .dev_size = 8*MB,
237 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
238 .max_buf_write_size = 0x0,
239 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
240 .num_erase_regions = 1,
241 .erase_region_info =
242 {
243 ERASE_REGION(2048, 4*KB)
244 }
245 },
246 {
247 .mfr = CFI_MFR_AMD,
248 .id = 0x22ab, /* AM29F400BB */
249 .pri_id = 0x02,
250 .dev_size = 512*KB,
251 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
252 .max_buf_write_size = 0x0,
253 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
254 .num_erase_regions = 4,
255 .erase_region_info =
256 {
257 ERASE_REGION(1, 16*KB),
258 ERASE_REGION(2, 8*KB),
259 ERASE_REGION(1, 32*KB),
260 ERASE_REGION(7, 64*KB)
261 }
262 },
263 {
264 .mfr = CFI_MFR_AMD,
265 .id = 0x2223, /* AM29F400BT */
266 .pri_id = 0x02,
267 .dev_size = 512*KB,
268 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
269 .max_buf_write_size = 0x0,
270 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
271 .num_erase_regions = 4,
272 .erase_region_info =
273 {
274 ERASE_REGION(7, 64*KB),
275 ERASE_REGION(1, 32*KB),
276 ERASE_REGION(2, 8*KB),
277 ERASE_REGION(1, 16*KB)
278 }
279 },
280 {
281 .mfr = CFI_MFR_FUJITSU,
282 .id = 0x226b, /* AM29SL800DB */
283 .pri_id = 0x02,
284 .dev_size = 1*MB,
285 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
286 .max_buf_write_size = 0x0,
287 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
288 .num_erase_regions = 4,
289 .erase_region_info =
290 {
291 ERASE_REGION(1, 16*KB),
292 ERASE_REGION(2, 8*KB),
293 ERASE_REGION(1, 32*KB),
294 ERASE_REGION(15, 64*KB)
295 }
296 },
297 {
298 .mfr = CFI_MFR_FUJITSU,
299 .id = 0x22ea, /* MBM29SL800TE */
300 .pri_id = 0x02,
301 .dev_size = 1*MB,
302 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
303 .max_buf_write_size = 0x0,
304 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
305 .num_erase_regions = 4,
306 .erase_region_info =
307 {
308 ERASE_REGION(15, 64*KB),
309 ERASE_REGION(1, 32*KB),
310 ERASE_REGION(2, 8*KB),
311 ERASE_REGION(1, 16*KB)
312 }
313 },
314 {
315 .mfr = CFI_MFR_FUJITSU,
316 .id = 0xba, /* 29LV400BC */
317 .pri_id = 0x02,
318 .dev_size = 512*KB,
319 .interface_desc = 0x1, /* x8 or x16 device w/ nBYTE */
320 .max_buf_write_size = 0x00,
321 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
322 .num_erase_regions = 4,
323 .erase_region_info =
324 {
325 ERASE_REGION(1, 16*KB),
326 ERASE_REGION(2, 8*KB),
327 ERASE_REGION(1, 32*KB),
328 ERASE_REGION(7, 64*KB)
329 }
330 },
331 {
332 .mfr = CFI_MFR_AMIC,
333 .id = 0xb31a, /* A29L800A */
334 .pri_id = 0x02,
335 .dev_size = 1*MB,
336 .interface_desc = 0x2,
337 .max_buf_write_size = 0x0,
338 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
339 .num_erase_regions = 4,
340 .erase_region_info =
341 {
342 ERASE_REGION(1, 16*KB),
343 ERASE_REGION(2, 8*KB),
344 ERASE_REGION(1, 32*KB),
345 ERASE_REGION(15, 64*KB)
346 }
347 },
348 {
349 .mfr = CFI_MFR_MX,
350 .id = 0x225b, /* MX29LV800B */
351 .pri_id = 0x02,
352 .dev_size = 1*MB,
353 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
354 .max_buf_write_size = 0x0,
355 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
356 .num_erase_regions = 4,
357 .erase_region_info =
358 {
359 ERASE_REGION(1, 16*KB),
360 ERASE_REGION(2, 8*KB),
361 ERASE_REGION(1, 32*KB),
362 ERASE_REGION(15, 64*KB)
363 }
364 },
365
366 {
367 .mfr = CFI_MFR_MX,
368 .id = 0x2249, /* MX29LV160AB: 2MB */
369 .pri_id = 0x02,
370 .dev_size = 2*MB,
371 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
372 .max_buf_write_size = 0x0,
373 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
374 .num_erase_regions = 4,
375 .erase_region_info =
376 {
377 ERASE_REGION(1, 16*KB),
378 ERASE_REGION(2, 8*KB),
379 ERASE_REGION(1, 32*KB),
380 ERASE_REGION(31, 64*KB)
381 }
382 },
383 {
384 .mfr = CFI_MFR_MX,
385 .id = 0x22C4, /* MX29LV160AT: 2MB */
386 .pri_id = 0x02,
387 .dev_size = 2*MB,
388 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
389 .max_buf_write_size = 0x0,
390 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
391 .num_erase_regions = 4,
392 .erase_region_info =
393 {
394 ERASE_REGION(31, 64*KB),
395 ERASE_REGION(1, 32*KB),
396 ERASE_REGION(2, 8*KB),
397 ERASE_REGION(1, 16*KB)
398 }
399 },
400 {
401 .mfr = CFI_MFR_ATMEL,
402 .id = 0x00c0, /* Atmel 49BV1614 */
403 .pri_id = 0x02,
404 .dev_size = 2*MB,
405 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
406 .max_buf_write_size = 0x0,
407 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
408 .num_erase_regions = 3,
409 .erase_region_info =
410 {
411 ERASE_REGION(8, 8*KB),
412 ERASE_REGION(2, 32*KB),
413 ERASE_REGION(30, 64*KB)
414 }
415 },
416 {
417 .mfr = CFI_MFR_ATMEL,
418 .id = 0xC2, /* Atmel 49BV1614T */
419 .pri_id = 0x02,
420 .dev_size = 2*MB,
421 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
422 .max_buf_write_size = 0x0,
423 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
424 .num_erase_regions = 3,
425 .erase_region_info =
426 {
427 ERASE_REGION(30, 64*KB),
428 ERASE_REGION(2, 32*KB),
429 ERASE_REGION(8, 8*KB)
430 }
431 },
432 {
433 .mfr = CFI_MFR_AMD,
434 .id = 0x225b, /* S29AL008D */
435 .pri_id = 0x02,
436 .dev_size = 1*MB,
437 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
438 .max_buf_write_size = 0x0,
439 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
440 .num_erase_regions = 4,
441 .erase_region_info =
442 {
443 ERASE_REGION(1, 16*KB),
444 ERASE_REGION(2, 8*KB),
445 ERASE_REGION(1, 32*KB),
446 ERASE_REGION(15, 64*KB)
447 }
448 },
449 {
450 .mfr = 0,
451 .id = 0,
452 }
453 };
454
455 void cfi_fixup_non_cfi(struct flash_bank *bank)
456 {
457 unsigned int mask;
458 struct cfi_flash_bank *cfi_info = bank->driver_priv;
459 struct non_cfi *non_cfi = non_cfi_flashes;
460
461 if(cfi_info->x16_as_x8)
462 mask = 0xFF;
463 else
464 mask = 0xFFFF;
465
466 for (non_cfi = non_cfi_flashes; non_cfi->mfr; non_cfi++)
467 {
468 if ((cfi_info->manufacturer == non_cfi->mfr)
469 && (cfi_info->device_id == (non_cfi->id & mask)))
470 {
471 break;
472 }
473 }
474
475 /* only fixup jedec flashs found in table */
476 if (!non_cfi->mfr)
477 return;
478
479 cfi_info->not_cfi = 1;
480
481 /* fill in defaults for non-critical data */
482 cfi_info->vcc_min = 0x0;
483 cfi_info->vcc_max = 0x0;
484 cfi_info->vpp_min = 0x0;
485 cfi_info->vpp_max = 0x0;
486 /* these are used for timeouts - use vales that should be long enough
487 for normal operation. */
488 cfi_info->word_write_timeout_typ = 0x0a;
489 cfi_info->buf_write_timeout_typ = 0x0d;
490 cfi_info->block_erase_timeout_typ = 0x0d;
491 cfi_info->chip_erase_timeout_typ = 0x10;
492 cfi_info->word_write_timeout_max = 0x0;
493 cfi_info->buf_write_timeout_max = 0x0;
494 cfi_info->block_erase_timeout_max = 0x0;
495 cfi_info->chip_erase_timeout_max = 0x0;
496
497 cfi_info->qry[0] = 'Q';
498 cfi_info->qry[1] = 'R';
499 cfi_info->qry[2] = 'Y';
500
501 cfi_info->pri_id = non_cfi->pri_id;
502 cfi_info->pri_addr = 0x0;
503 cfi_info->alt_id = 0x0;
504 cfi_info->alt_addr = 0x0;
505 cfi_info->alt_ext = NULL;
506
507 cfi_info->interface_desc = non_cfi->interface_desc;
508 cfi_info->max_buf_write_size = non_cfi->max_buf_write_size;
509 cfi_info->status_poll_mask = non_cfi->status_poll_mask;
510 cfi_info->num_erase_regions = non_cfi->num_erase_regions;
511 size_t erase_region_info_size = sizeof(*cfi_info->erase_region_info) *
512 cfi_info->num_erase_regions;
513 cfi_info->erase_region_info = malloc(erase_region_info_size);
514 memcpy(cfi_info->erase_region_info,
515 non_cfi->erase_region_info, erase_region_info_size);
516 cfi_info->dev_size = non_cfi->dev_size;
517
518 if (cfi_info->pri_id == 0x2)
519 {
520 struct cfi_spansion_pri_ext *pri_ext = malloc(sizeof(struct cfi_spansion_pri_ext));
521
522 pri_ext->pri[0] = 'P';
523 pri_ext->pri[1] = 'R';
524 pri_ext->pri[2] = 'I';
525
526 pri_ext->major_version = '1';
527 pri_ext->minor_version = '0';
528
529 pri_ext->SiliconRevision = 0x0;
530 pri_ext->EraseSuspend = 0x0;
531 pri_ext->EraseSuspend = 0x0;
532 pri_ext->BlkProt = 0x0;
533 pri_ext->TmpBlkUnprotect = 0x0;
534 pri_ext->BlkProtUnprot = 0x0;
535 pri_ext->SimultaneousOps = 0x0;
536 pri_ext->BurstMode = 0x0;
537 pri_ext->PageMode = 0x0;
538 pri_ext->VppMin = 0x0;
539 pri_ext->VppMax = 0x0;
540 pri_ext->TopBottom = 0x0;
541
542 pri_ext->_unlock1 = 0x5555;
543 pri_ext->_unlock2 = 0x2AAA;
544 pri_ext->_reversed_geometry = 0;
545
546 cfi_info->pri_ext = pri_ext;
547 } else if ((cfi_info->pri_id == 0x1) || (cfi_info->pri_id == 0x3))
548 {
549 LOG_ERROR("BUG: non-CFI flashes using the Intel commandset are not yet supported");
550 exit(-1);
551 }
552 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)