]> git.sur5r.net Git - openocd/blob - src/flash/nor/non_cfi.c
add support for spansion flash on mindspeed c300 eval board
[openocd] / 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_AMD,             /* Spansion AM29LV040B */
95                 .id = 0x4f,
96                 .pri_id = 0x02,
97                 .dev_size = 512*KB,
98                 .interface_desc = 0x0,          /* x8 only 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(8, 64*KB)
105                 }
106         },
107         {
108                 .mfr = CFI_MFR_SST,
109                 .id = 0x2780,
110                 .pri_id = 0x02,
111                 .dev_size = 512*KB,
112                 .interface_desc = 0x2,          /* x8 or x16 device */
113                 .max_buf_write_size = 0x0,
114                 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
115                 .num_erase_regions = 1,
116                 .erase_region_info =
117                 {
118                         ERASE_REGION(128, 4*KB)
119                 }
120         },
121         {
122                 .mfr = CFI_MFR_ST,
123                 .id = 0xd6,                                     /* ST29F400BB */
124                 .pri_id = 0x02,
125                 .dev_size = 512*KB,
126                 .interface_desc = 0x2,          /* x8 or x16 device with nBYTE */
127                 .max_buf_write_size = 0x0,
128                 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
129                 .num_erase_regions = 4,
130                 .erase_region_info =
131                 {
132                         ERASE_REGION(1, 16*KB),
133                         ERASE_REGION(2,  8*KB),
134                         ERASE_REGION(1, 32*KB),
135                         ERASE_REGION(7, 64*KB)
136                 }
137         },
138         {
139                 .mfr = CFI_MFR_ST,
140                 .id = 0xd5,                                     /* ST29F400BT */
141                 .pri_id = 0x02,
142                 .dev_size = 512*KB,
143                 .interface_desc = 0x2,          /* x8 or x16 device with nBYTE */
144                 .max_buf_write_size = 0x0,
145                 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
146                 .num_erase_regions = 4,
147                 .erase_region_info =
148                 {
149                         ERASE_REGION(7, 64*KB),
150                         ERASE_REGION(1, 32*KB),
151                         ERASE_REGION(2,  8*KB),
152                         ERASE_REGION(1, 16*KB)
153                 }
154         },
155
156         /* SST 39VF* do not support DQ5 status polling - this currently is
157            only supported by the host algorithm, not by the target code using
158            the work area.
159            Only true for 8-bit and 32-bit wide memories. 16-bit wide memories
160            without DQ5 status polling are supported by the target code.
161         */
162         {
163                 .mfr = CFI_MFR_SST,
164                 .id = 0x2782,                           /* SST39xF160 */
165                 .pri_id = 0x02,
166                 .dev_size = 2*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(512, 4*KB)
174                 }
175         },
176         {
177                 .mfr = CFI_MFR_SST,
178                 .id = 0x2783,                           /* SST39VF320 */
179                 .pri_id = 0x02,
180                 .dev_size = 4*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(1024, 4*KB)
188                 }
189         },
190         {
191                 .mfr = CFI_MFR_SST,
192                 .id = 0x234b,                           /* SST39VF1601 */
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 = 0x234a,                           /* SST39VF1602 */
207                 .pri_id = 0x02,
208                 .dev_size = 2*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(512, 4*KB)
216                 }
217         },
218         {
219                 .mfr = CFI_MFR_SST,
220                 .id = 0x235b,                           /* SST39VF3201 */
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 = 0x235a,                           /* SST39VF3202 */
235                 .pri_id = 0x02,
236                 .dev_size = 4*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(1024, 4*KB)
244                 }
245         },
246         {
247         .mfr = CFI_MFR_SST,
248             .id = 0x236d,               /* SST39VF6401B */
249             .pri_id = 0x02,
250             .dev_size = 8*MB,
251             .interface_desc = 0x2,      /* x8 or x16 device with nBYTE */
252             .max_buf_write_size = 0x0,
253             .status_poll_mask = CFI_STATUS_POLL_MASK_DQ6_DQ7,
254             .num_erase_regions = 1,
255             .erase_region_info =
256             {
257                 ERASE_REGION(2048, 4*KB)
258             }
259         },
260         {
261                 .mfr = CFI_MFR_AMD,
262                 .id = 0x22ab,                           /* AM29F400BB */
263                 .pri_id = 0x02,
264                 .dev_size = 512*KB,
265                 .interface_desc = 0x2,          /* x8 or x16 device with nBYTE */
266                 .max_buf_write_size = 0x0,
267                 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
268                 .num_erase_regions = 4,
269                 .erase_region_info =
270                 {
271                         ERASE_REGION(1, 16*KB),
272                         ERASE_REGION(2,  8*KB),
273                         ERASE_REGION(1, 32*KB),
274                         ERASE_REGION(7, 64*KB)
275                 }
276         },
277         {
278                 .mfr = CFI_MFR_AMD,
279                 .id = 0x2223,                           /* AM29F400BT */
280                 .pri_id = 0x02,
281                 .dev_size = 512*KB,
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                 {
288                         ERASE_REGION(7, 64*KB),
289                         ERASE_REGION(1, 32*KB),
290                         ERASE_REGION(2,  8*KB),
291                         ERASE_REGION(1, 16*KB)
292                 }
293         },
294         {
295                 .mfr = CFI_MFR_FUJITSU,
296                 .id = 0x226b,                           /* AM29SL800DB */
297                 .pri_id = 0x02,
298                 .dev_size = 1*MB,
299                 .interface_desc = 0x2,          /* x8 or x16 device with nBYTE */
300                 .max_buf_write_size = 0x0,
301                 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
302                 .num_erase_regions = 4,
303                 .erase_region_info =
304                 {
305                         ERASE_REGION(1, 16*KB),
306                         ERASE_REGION(2,  8*KB),
307                         ERASE_REGION(1, 32*KB),
308                         ERASE_REGION(15, 64*KB)
309                 }
310         },
311    {
312                 .mfr = CFI_MFR_FUJITSU,
313                 .id = 0x22ea,                           /* MBM29SL800TE */
314                 .pri_id = 0x02,
315                 .dev_size = 1*MB,
316                 .interface_desc = 0x2,          /* x8 or x16 device with nBYTE */
317                 .max_buf_write_size = 0x0,
318                 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
319                 .num_erase_regions = 4,
320                 .erase_region_info =
321                 {
322                         ERASE_REGION(15, 64*KB),
323                         ERASE_REGION(1,  32*KB),
324                         ERASE_REGION(2,  8*KB),
325                         ERASE_REGION(1,  16*KB)
326                 }
327         },
328         {
329                 .mfr = CFI_MFR_FUJITSU,
330                 .id = 0xba,                             /* 29LV400BC */
331                 .pri_id = 0x02,
332                 .dev_size = 512*KB,
333                 .interface_desc = 0x1,          /* x8 or x16 device w/ nBYTE */
334                 .max_buf_write_size = 0x00,
335                 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
336                 .num_erase_regions = 4,
337                 .erase_region_info =
338                 {
339                         ERASE_REGION(1, 16*KB),
340                         ERASE_REGION(2,  8*KB),
341                         ERASE_REGION(1, 32*KB),
342                         ERASE_REGION(7, 64*KB)
343                 }
344         },
345         {
346                 .mfr = CFI_MFR_AMIC,
347                 .id = 0xb31a,                           /* A29L800A */
348                 .pri_id = 0x02,
349                 .dev_size = 1*MB,
350                 .interface_desc = 0x2,
351                 .max_buf_write_size = 0x0,
352                 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
353                 .num_erase_regions = 4,
354                 .erase_region_info =
355                 {
356                         ERASE_REGION(1, 16*KB),
357                         ERASE_REGION(2,  8*KB),
358                         ERASE_REGION(1, 32*KB),
359                         ERASE_REGION(15, 64*KB)
360                 }
361         },
362         {
363                 .mfr = CFI_MFR_MX,
364                 .id = 0x225b,                           /* MX29LV800B */
365                 .pri_id = 0x02,
366                 .dev_size = 1*MB,
367                 .interface_desc = 0x2,          /* x8 or x16 device with nBYTE */
368                 .max_buf_write_size = 0x0,
369                 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
370                 .num_erase_regions = 4,
371                 .erase_region_info =
372                 {
373                         ERASE_REGION(1, 16*KB),
374                         ERASE_REGION(2, 8*KB),
375                         ERASE_REGION(1, 32*KB),
376                         ERASE_REGION(15, 64*KB)
377                 }
378         },
379
380         {
381                 .mfr = CFI_MFR_MX,
382                 .id = 0x2249,                           /* MX29LV160AB: 2MB */
383                 .pri_id = 0x02,
384                 .dev_size = 2*MB,
385                 .interface_desc = 0x2,          /* x8 or x16 device with nBYTE */
386                 .max_buf_write_size = 0x0,
387                 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
388                 .num_erase_regions = 4,
389                 .erase_region_info =
390                 {
391                         ERASE_REGION(1, 16*KB),
392                         ERASE_REGION(2, 8*KB),
393                         ERASE_REGION(1, 32*KB),
394                         ERASE_REGION(31, 64*KB)
395                 }
396         },
397         {
398                 .mfr = CFI_MFR_MX,
399                 .id = 0x22C4,                           /* MX29LV160AT: 2MB */
400                 .pri_id = 0x02,
401                 .dev_size = 2*MB,
402                 .interface_desc = 0x2,          /* x8 or x16 device with nBYTE */
403                 .max_buf_write_size = 0x0,
404                 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
405                 .num_erase_regions = 4,
406                 .erase_region_info =
407                 {
408                         ERASE_REGION(31, 64*KB),
409                         ERASE_REGION(1, 32*KB),
410                         ERASE_REGION(2, 8*KB),
411                         ERASE_REGION(1, 16*KB)
412                 }
413         },
414         {
415                 .mfr = CFI_MFR_ATMEL,
416                 .id = 0x00c0,                           /* Atmel 49BV1614 */
417                 .pri_id = 0x02,
418                 .dev_size = 2*MB,
419                 .interface_desc = 0x2,          /* x8 or x16 device with nBYTE */
420                 .max_buf_write_size = 0x0,
421                 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
422                 .num_erase_regions = 3,
423                 .erase_region_info =
424                 {
425                         ERASE_REGION(8,  8*KB),
426                         ERASE_REGION(2, 32*KB),
427                         ERASE_REGION(30, 64*KB)
428                 }
429         },
430         {
431                 .mfr = CFI_MFR_ATMEL,
432                 .id = 0xC2,                                     /* Atmel 49BV1614T */
433                 .pri_id = 0x02,
434                 .dev_size = 2*MB,
435                 .interface_desc = 0x2,          /* x8 or x16 device with nBYTE */
436                 .max_buf_write_size = 0x0,
437                 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
438                 .num_erase_regions = 3,
439                 .erase_region_info =
440                 {
441                         ERASE_REGION(30, 64*KB),
442                         ERASE_REGION(2, 32*KB),
443                         ERASE_REGION(8,  8*KB)
444                 }
445         },
446         {
447                 .mfr = CFI_MFR_AMD,
448                 .id = 0x225b,                           /* S29AL008D */
449                 .pri_id = 0x02,
450                 .dev_size = 1*MB,
451                 .interface_desc = 0x2,          /* x8 or x16 device with nBYTE */
452                 .max_buf_write_size = 0x0,
453                 .status_poll_mask = CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7,
454                 .num_erase_regions = 4,
455                 .erase_region_info =
456                 {
457                         ERASE_REGION(1, 16*KB),
458                         ERASE_REGION(2, 8*KB),
459                         ERASE_REGION(1, 32*KB),
460                         ERASE_REGION(15, 64*KB)
461                 }
462         },
463         {
464                 .mfr = 0,
465                 .id = 0,
466         }
467 };
468
469 void cfi_fixup_non_cfi(struct flash_bank *bank)
470 {
471         unsigned int mask;
472         struct cfi_flash_bank *cfi_info = bank->driver_priv;
473         struct non_cfi *non_cfi = non_cfi_flashes;
474
475         if(cfi_info->x16_as_x8)
476                 mask = 0xFF;
477         else
478                 mask = 0xFFFF;
479
480         for (non_cfi = non_cfi_flashes; non_cfi->mfr; non_cfi++)
481         {
482                 if ((cfi_info->manufacturer == non_cfi->mfr)
483                         && (cfi_info->device_id == (non_cfi->id & mask)))
484                 {
485                         break;
486                 }
487         }
488
489         /* only fixup jedec flashs found in table */
490         if (!non_cfi->mfr)
491                 return;
492
493         cfi_info->not_cfi = 1;
494
495         /* fill in defaults for non-critical data */
496         cfi_info->vcc_min = 0x0;
497         cfi_info->vcc_max = 0x0;
498         cfi_info->vpp_min = 0x0;
499         cfi_info->vpp_max = 0x0;
500         /* these are used for timeouts - use vales that should be long enough
501            for normal operation. */
502         cfi_info->word_write_timeout_typ = 0x0a;
503         cfi_info->buf_write_timeout_typ = 0x0d;
504         cfi_info->block_erase_timeout_typ = 0x0d;
505         cfi_info->chip_erase_timeout_typ = 0x10;
506         cfi_info->word_write_timeout_max = 0x0;
507         cfi_info->buf_write_timeout_max = 0x0;
508         cfi_info->block_erase_timeout_max = 0x0;
509         cfi_info->chip_erase_timeout_max = 0x0;
510
511         cfi_info->qry[0] = 'Q';
512         cfi_info->qry[1] = 'R';
513         cfi_info->qry[2] = 'Y';
514
515         cfi_info->pri_id = non_cfi->pri_id;
516         cfi_info->pri_addr = 0x0;
517         cfi_info->alt_id = 0x0;
518         cfi_info->alt_addr = 0x0;
519         cfi_info->alt_ext = NULL;
520
521         cfi_info->interface_desc = non_cfi->interface_desc;
522         cfi_info->max_buf_write_size = non_cfi->max_buf_write_size;
523         cfi_info->status_poll_mask = non_cfi->status_poll_mask;
524         cfi_info->num_erase_regions = non_cfi->num_erase_regions;
525         size_t erase_region_info_size = sizeof(*cfi_info->erase_region_info) *
526                         cfi_info->num_erase_regions;
527         cfi_info->erase_region_info = malloc(erase_region_info_size);
528         memcpy(cfi_info->erase_region_info,
529                         non_cfi->erase_region_info, erase_region_info_size);
530         cfi_info->dev_size = non_cfi->dev_size;
531
532         if (cfi_info->pri_id == 0x2)
533         {
534                 struct cfi_spansion_pri_ext *pri_ext = malloc(sizeof(struct cfi_spansion_pri_ext));
535
536                 pri_ext->pri[0] = 'P';
537                 pri_ext->pri[1] = 'R';
538                 pri_ext->pri[2] = 'I';
539
540                 pri_ext->major_version = '1';
541                 pri_ext->minor_version = '0';
542
543                 pri_ext->SiliconRevision = 0x0;
544                 pri_ext->EraseSuspend = 0x0;
545                 pri_ext->EraseSuspend = 0x0;
546                 pri_ext->BlkProt = 0x0;
547                 pri_ext->TmpBlkUnprotect = 0x0;
548                 pri_ext->BlkProtUnprot = 0x0;
549                 pri_ext->SimultaneousOps = 0x0;
550                 pri_ext->BurstMode = 0x0;
551                 pri_ext->PageMode = 0x0;
552                 pri_ext->VppMin = 0x0;
553                 pri_ext->VppMax = 0x0;
554                 pri_ext->TopBottom = 0x0;
555
556                 pri_ext->_unlock1 = 0x5555;
557                 pri_ext->_unlock2 = 0x2AAA;
558                 pri_ext->_reversed_geometry = 0;
559
560                 cfi_info->pri_ext = pri_ext;
561         } else if ((cfi_info->pri_id == 0x1) || (cfi_info->pri_id == 0x3))
562         {
563                 LOG_ERROR("BUG: non-CFI flashes using the Intel commandset are not yet supported");
564                 exit(-1);
565         }
566 }