5c05fb3b7ec41056b5e7d6b9481d3feb58d59e80
[openocd.git] / src / flash / nor / non_cfi.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 /***************************************************************************
4 * Copyright (C) 2007 by Dominic Rath *
5 * Dominic.Rath@gmx.de *
6 * Copyright (C) 2009 Michael Schwingen *
7 * michael@schwingen.org *
8 ***************************************************************************/
9
10 #ifdef HAVE_CONFIG_H
11 #include "config.h"
12 #endif
13
14 #include "imp.h"
15 #include "cfi.h"
16 #include "non_cfi.h"
17
18 #define KB 1024
19 #define MB (1024*1024)
20 #define ERASE_REGION(num, size) (((size/256) << 16) | (num-1))
21
22 /* non-CFI compatible flashes */
23 static const struct non_cfi non_cfi_flashes[] = {
24 {
25 .mfr = CFI_MFR_SST,
26 .id = 0xd4,
27 .pri_id = 0x02,
28 .dev_size = 64*KB,
29 .interface_desc = 0x0, /* x8 only device */
30 .max_buf_write_size = 0x0,
31 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
32 .num_erase_regions = 1,
33 .erase_region_info = {
34 ERASE_REGION(16, 4*KB)
35 }
36 },
37 {
38 .mfr = CFI_MFR_SST,
39 .id = 0xd5,
40 .pri_id = 0x02,
41 .dev_size = 128*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 ERASE_REGION(32, 4*KB)
48 }
49 },
50 {
51 .mfr = CFI_MFR_SST,
52 .id = 0xd6,
53 .pri_id = 0x02,
54 .dev_size = 256*KB,
55 .interface_desc = 0x0, /* x8 only device */
56 .max_buf_write_size = 0x0,
57 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
58 .num_erase_regions = 1,
59 .erase_region_info = {
60 ERASE_REGION(64, 4*KB)
61 }
62 },
63 {
64 .mfr = CFI_MFR_SST,
65 .id = 0xd7,
66 .pri_id = 0x02,
67 .dev_size = 512*KB,
68 .interface_desc = 0x0, /* x8 only device */
69 .max_buf_write_size = 0x0,
70 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
71 .num_erase_regions = 1,
72 .erase_region_info = {
73 ERASE_REGION(128, 4*KB)
74 }
75 },
76 {
77 .mfr = CFI_MFR_AMD, /* Spansion AM29LV040B */
78 .id = 0x4f,
79 .pri_id = 0x02,
80 .dev_size = 512*KB,
81 .interface_desc = 0x0, /* x8 only device */
82 .max_buf_write_size = 0x0,
83 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
84 .num_erase_regions = 1,
85 .erase_region_info = {
86 ERASE_REGION(8, 64*KB)
87 }
88 },
89 {
90 .mfr = CFI_MFR_SST,
91 .id = 0x2780,
92 .pri_id = 0x02,
93 .dev_size = 512*KB,
94 .interface_desc = 0x2, /* x8 or x16 device */
95 .max_buf_write_size = 0x0,
96 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
97 .num_erase_regions = 1,
98 .erase_region_info = {
99 ERASE_REGION(128, 4*KB)
100 }
101 },
102 {
103 .mfr = CFI_MFR_ST,
104 .id = 0xd6, /* ST29F400BB */
105 .pri_id = 0x02,
106 .dev_size = 512*KB,
107 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
108 .max_buf_write_size = 0x0,
109 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
110 .num_erase_regions = 4,
111 .erase_region_info = {
112 ERASE_REGION(1, 16*KB),
113 ERASE_REGION(2, 8*KB),
114 ERASE_REGION(1, 32*KB),
115 ERASE_REGION(7, 64*KB)
116 }
117 },
118 {
119 .mfr = CFI_MFR_ST,
120 .id = 0xd5, /* ST29F400BT */
121 .pri_id = 0x02,
122 .dev_size = 512*KB,
123 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
124 .max_buf_write_size = 0x0,
125 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
126 .num_erase_regions = 4,
127 .erase_region_info = {
128 ERASE_REGION(7, 64*KB),
129 ERASE_REGION(1, 32*KB),
130 ERASE_REGION(2, 8*KB),
131 ERASE_REGION(1, 16*KB)
132 }
133 },
134
135 /* SST 39VF* do not support DQ5 status polling - this currently is
136 only supported by the host algorithm, not by the target code using
137 the work area.
138 Only true for 8-bit and 32-bit wide memories. 16-bit wide memories
139 without DQ5 status polling are supported by the target code.
140 */
141 {
142 .mfr = CFI_MFR_SST,
143 .id = 0x2782, /* SST39xF160 */
144 .pri_id = 0x02,
145 .dev_size = 2*MB,
146 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
147 .max_buf_write_size = 0x0,
148 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
149 .num_erase_regions = 1,
150 .erase_region_info = {
151 ERASE_REGION(512, 4*KB)
152 }
153 },
154 {
155 .mfr = CFI_MFR_SST,
156 .id = 0x2783, /* SST39VF320 */
157 .pri_id = 0x02,
158 .dev_size = 4*MB,
159 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
160 .max_buf_write_size = 0x0,
161 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
162 .num_erase_regions = 1,
163 .erase_region_info = {
164 ERASE_REGION(1024, 4*KB)
165 }
166 },
167 {
168 .mfr = CFI_MFR_SST,
169 .id = 0x234b, /* SST39VF1601 */
170 .pri_id = 0x02,
171 .dev_size = 2*MB,
172 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
173 .max_buf_write_size = 0x0,
174 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
175 .num_erase_regions = 1,
176 .erase_region_info = {
177 ERASE_REGION(512, 4*KB)
178 }
179 },
180 {
181 .mfr = CFI_MFR_SST,
182 .id = 0x274b, /* SST39WF1601 */
183 .pri_id = 0x02,
184 .dev_size = 2*MB,
185 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
186 .max_buf_write_size = 0x0,
187 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
188 .num_erase_regions = 1,
189 .erase_region_info = {
190 ERASE_REGION(512, 4*KB)
191 }
192 },
193 {
194 .mfr = CFI_MFR_SST,
195 .id = 0x234a, /* SST39VF1602 */
196 .pri_id = 0x02,
197 .dev_size = 2*MB,
198 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
199 .max_buf_write_size = 0x0,
200 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
201 .num_erase_regions = 1,
202 .erase_region_info = {
203 ERASE_REGION(512, 4*KB)
204 }
205 },
206 {
207 .mfr = CFI_MFR_SST,
208 .id = 0x235b, /* SST39VF3201 */
209 .pri_id = 0x02,
210 .dev_size = 4*MB,
211 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
212 .max_buf_write_size = 0x0,
213 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
214 .num_erase_regions = 1,
215 .erase_region_info = {
216 ERASE_REGION(1024, 4*KB)
217 }
218 },
219 {
220 .mfr = CFI_MFR_SST,
221 .id = 0x235a, /* SST39VF3202 */
222 .pri_id = 0x02,
223 .dev_size = 4*MB,
224 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
225 .max_buf_write_size = 0x0,
226 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
227 .num_erase_regions = 1,
228 .erase_region_info = {
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 ERASE_REGION(2048, 4*KB)
243 }
244 },
245 {
246 .mfr = CFI_MFR_AMD,
247 .id = 0x22ab, /* AM29F400BB */
248 .pri_id = 0x02,
249 .dev_size = 512*KB,
250 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
251 .max_buf_write_size = 0x0,
252 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
253 .num_erase_regions = 4,
254 .erase_region_info = {
255 ERASE_REGION(1, 16*KB),
256 ERASE_REGION(2, 8*KB),
257 ERASE_REGION(1, 32*KB),
258 ERASE_REGION(7, 64*KB)
259 }
260 },
261 {
262 .mfr = CFI_MFR_AMD,
263 .id = 0x2223, /* AM29F400BT */
264 .pri_id = 0x02,
265 .dev_size = 512*KB,
266 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
267 .max_buf_write_size = 0x0,
268 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
269 .num_erase_regions = 4,
270 .erase_region_info = {
271 ERASE_REGION(7, 64*KB),
272 ERASE_REGION(1, 32*KB),
273 ERASE_REGION(2, 8*KB),
274 ERASE_REGION(1, 16*KB)
275 }
276 },
277 {
278 .mfr = CFI_MFR_FUJITSU,
279 .id = 0x226b, /* AM29SL800DB */
280 .pri_id = 0x02,
281 .dev_size = 1*MB,
282 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
283 .max_buf_write_size = 0x0,
284 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
285 .num_erase_regions = 4,
286 .erase_region_info = {
287 ERASE_REGION(1, 16*KB),
288 ERASE_REGION(2, 8*KB),
289 ERASE_REGION(1, 32*KB),
290 ERASE_REGION(15, 64*KB)
291 }
292 },
293 {
294 .mfr = CFI_MFR_FUJITSU,
295 .id = 0x22ea, /* MBM29SL800TE */
296 .pri_id = 0x02,
297 .dev_size = 1*MB,
298 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
299 .max_buf_write_size = 0x0,
300 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
301 .num_erase_regions = 4,
302 .erase_region_info = {
303 ERASE_REGION(15, 64*KB),
304 ERASE_REGION(1, 32*KB),
305 ERASE_REGION(2, 8*KB),
306 ERASE_REGION(1, 16*KB)
307 }
308 },
309 {
310 .mfr = CFI_MFR_FUJITSU,
311 .id = 0xba, /* 29LV400BC */
312 .pri_id = 0x02,
313 .dev_size = 512*KB,
314 .interface_desc = 0x1, /* x8 or x16 device w/ nBYTE */
315 .max_buf_write_size = 0x00,
316 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
317 .num_erase_regions = 4,
318 .erase_region_info = {
319 ERASE_REGION(1, 16*KB),
320 ERASE_REGION(2, 8*KB),
321 ERASE_REGION(1, 32*KB),
322 ERASE_REGION(7, 64*KB)
323 }
324 },
325 {
326 .mfr = CFI_MFR_AMIC,
327 .id = 0xb31a, /* A29L800A */
328 .pri_id = 0x02,
329 .dev_size = 1*MB,
330 .interface_desc = 0x2,
331 .max_buf_write_size = 0x0,
332 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
333 .num_erase_regions = 4,
334 .erase_region_info = {
335 ERASE_REGION(1, 16*KB),
336 ERASE_REGION(2, 8*KB),
337 ERASE_REGION(1, 32*KB),
338 ERASE_REGION(15, 64*KB)
339 }
340 },
341 {
342 .mfr = CFI_MFR_MX,
343 .id = 0x225b, /* MX29LV800B */
344 .pri_id = 0x02,
345 .dev_size = 1*MB,
346 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
347 .max_buf_write_size = 0x0,
348 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
349 .num_erase_regions = 4,
350 .erase_region_info = {
351 ERASE_REGION(1, 16*KB),
352 ERASE_REGION(2, 8*KB),
353 ERASE_REGION(1, 32*KB),
354 ERASE_REGION(15, 64*KB)
355 }
356 },
357
358 {
359 .mfr = CFI_MFR_MX,
360 .id = 0x2249, /* MX29LV160AB: 2MB */
361 .pri_id = 0x02,
362 .dev_size = 2*MB,
363 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
364 .max_buf_write_size = 0x0,
365 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
366 .num_erase_regions = 4,
367 .erase_region_info = {
368 ERASE_REGION(1, 16*KB),
369 ERASE_REGION(2, 8*KB),
370 ERASE_REGION(1, 32*KB),
371 ERASE_REGION(31, 64*KB)
372 }
373 },
374 {
375 .mfr = CFI_MFR_MX,
376 .id = 0x22C4, /* MX29LV160AT: 2MB */
377 .pri_id = 0x02,
378 .dev_size = 2*MB,
379 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
380 .max_buf_write_size = 0x0,
381 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
382 .num_erase_regions = 4,
383 .erase_region_info = {
384 ERASE_REGION(31, 64*KB),
385 ERASE_REGION(1, 32*KB),
386 ERASE_REGION(2, 8*KB),
387 ERASE_REGION(1, 16*KB)
388 }
389 },
390 {
391 .mfr = CFI_MFR_EON,
392 .id = 0x225b, /* EN29LV800BB */
393 .pri_id = 0x02,
394 .dev_size = 1*MB,
395 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
396 .max_buf_write_size = 0x0,
397 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
398 .num_erase_regions = 4,
399 .erase_region_info = {
400 ERASE_REGION(1, 16*KB),
401 ERASE_REGION(2, 8*KB),
402 ERASE_REGION(1, 32*KB),
403 ERASE_REGION(15, 64*KB)
404 }
405 },
406 {
407 .mfr = CFI_MFR_ATMEL,
408 .id = 0x00c0, /* Atmel 49BV1614 */
409 .pri_id = 0x02,
410 .dev_size = 2*MB,
411 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
412 .max_buf_write_size = 0x0,
413 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
414 .num_erase_regions = 3,
415 .erase_region_info = {
416 ERASE_REGION(8, 8*KB),
417 ERASE_REGION(2, 32*KB),
418 ERASE_REGION(30, 64*KB)
419 }
420 },
421 {
422 .mfr = CFI_MFR_ATMEL,
423 .id = 0xC2, /* Atmel 49BV1614T */
424 .pri_id = 0x02,
425 .dev_size = 2*MB,
426 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
427 .max_buf_write_size = 0x0,
428 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
429 .num_erase_regions = 3,
430 .erase_region_info = {
431 ERASE_REGION(30, 64*KB),
432 ERASE_REGION(2, 32*KB),
433 ERASE_REGION(8, 8*KB)
434 }
435 },
436 {
437 .mfr = CFI_MFR_AMD,
438 .id = 0x225b, /* S29AL008D */
439 .pri_id = 0x02,
440 .dev_size = 1*MB,
441 .interface_desc = 0x2, /* x8 or x16 device with nBYTE */
442 .max_buf_write_size = 0x0,
443 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
444 .num_erase_regions = 4,
445 .erase_region_info = {
446 ERASE_REGION(1, 16*KB),
447 ERASE_REGION(2, 8*KB),
448 ERASE_REGION(1, 32*KB),
449 ERASE_REGION(15, 64*KB)
450 }
451 },
452 {
453 .mfr = 0,
454 .id = 0,
455 }
456 };
457
458 void cfi_fixup_non_cfi(struct flash_bank *bank)
459 {
460 unsigned int mask;
461 struct cfi_flash_bank *cfi_info = bank->driver_priv;
462 const struct non_cfi *non_cfi = non_cfi_flashes;
463
464 if (cfi_info->x16_as_x8)
465 mask = 0xFF;
466 else
467 mask = 0xFFFF;
468
469 for (non_cfi = non_cfi_flashes; non_cfi->mfr; non_cfi++) {
470 if ((cfi_info->manufacturer == non_cfi->mfr)
471 && (cfi_info->device_id == (non_cfi->id & mask)))
472 break;
473 }
474
475 /* only fixup jedec flashes found in table */
476 if (!non_cfi->mfr)
477 return;
478
479 cfi_info->not_cfi = true;
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 struct cfi_spansion_pri_ext *pri_ext = malloc(sizeof(struct cfi_spansion_pri_ext));
520
521 pri_ext->pri[0] = 'P';
522 pri_ext->pri[1] = 'R';
523 pri_ext->pri[2] = 'I';
524
525 pri_ext->major_version = '1';
526 pri_ext->minor_version = '0';
527
528 pri_ext->silicon_revision = 0x0;
529 pri_ext->erase_suspend = 0x0;
530 pri_ext->blk_prot = 0x0;
531 pri_ext->tmp_blk_unprotected = 0x0;
532 pri_ext->blk_prot_unprot = 0x0;
533 pri_ext->simultaneous_ops = 0x0;
534 pri_ext->burst_mode = 0x0;
535 pri_ext->page_mode = 0x0;
536 pri_ext->vpp_min = 0x0;
537 pri_ext->vpp_max = 0x0;
538 pri_ext->top_bottom = 0x0;
539
540 pri_ext->_unlock1 = 0x5555;
541 pri_ext->_unlock2 = 0x2AAA;
542 pri_ext->_reversed_geometry = 0;
543
544 cfi_info->pri_ext = pri_ext;
545 } else if ((cfi_info->pri_id == 0x1) || (cfi_info->pri_id == 0x3)) {
546 LOG_ERROR("BUG: non-CFI flashes using the Intel commandset are not yet supported");
547 exit(-1);
548 }
549 }

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)