mtd: spi-nor-core: Replace MTD_SPI_NOR_USE_4K_SECTORS with SPI_FLASH_USE_4K_SECTORS
[oweals/u-boot.git] / drivers / mtd / jedec_flash.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2007
4  * Michael Schwingen, <michael@schwingen.org>
5  *
6  * based in great part on jedec_probe.c from linux kernel:
7  * (C) 2000 Red Hat. GPL'd.
8  * Occasionally maintained by Thayne Harbaugh tharbaugh at lnxi dot com
9  */
10
11 /* The DEBUG define must be before common to enable debugging */
12 /*#define DEBUG*/
13
14 #include <common.h>
15 #include <asm/processor.h>
16 #include <asm/io.h>
17 #include <asm/byteorder.h>
18
19 #define P_ID_AMD_STD CFI_CMDSET_AMD_LEGACY
20
21 /* AMD */
22 #define AM29DL800BB     0x22CB
23 #define AM29DL800BT     0x224A
24
25 #define AM29F400BB      0x22AB
26 #define AM29F800BB      0x2258
27 #define AM29F800BT      0x22D6
28 #define AM29LV400BB     0x22BA
29 #define AM29LV400BT     0x22B9
30 #define AM29LV800BB     0x225B
31 #define AM29LV800BT     0x22DA
32 #define AM29LV160DT     0x22C4
33 #define AM29LV160DB     0x2249
34 #define AM29F017D       0x003D
35 #define AM29F016D       0x00AD
36 #define AM29F080        0x00D5
37 #define AM29F040        0x00A4
38 #define AM29LV040B      0x004F
39 #define AM29F032B       0x0041
40 #define AM29F002T       0x00B0
41
42 /* SST */
43 #define SST39LF800      0x2781
44 #define SST39LF160      0x2782
45 #define SST39VF1601     0x234b
46 #define SST39LF512      0x00D4
47 #define SST39LF010      0x00D5
48 #define SST39LF020      0x00D6
49 #define SST39LF040      0x00D7
50 #define SST39SF010A     0x00B5
51 #define SST39SF020A     0x00B6
52
53 /* STM */
54 #define STM29F400BB     0x00D6
55
56 /* MXIC */
57 #define MX29LV040       0x004F
58
59 /* WINBOND */
60 #define W39L040A        0x00D6
61
62 /* AMIC */
63 #define A29L040         0x0092
64
65 /* EON */
66 #define EN29LV040A      0x004F
67
68 /*
69  * Unlock address sets for AMD command sets.
70  * Intel command sets use the MTD_UADDR_UNNECESSARY.
71  * Each identifier, except MTD_UADDR_UNNECESSARY, and
72  * MTD_UADDR_NO_SUPPORT must be defined below in unlock_addrs[].
73  * MTD_UADDR_NOT_SUPPORTED must be 0 so that structure
74  * initialization need not require initializing all of the
75  * unlock addresses for all bit widths.
76  */
77 enum uaddr {
78         MTD_UADDR_NOT_SUPPORTED = 0,    /* data width not supported */
79         MTD_UADDR_0x0555_0x02AA,
80         MTD_UADDR_0x0555_0x0AAA,
81         MTD_UADDR_0x5555_0x2AAA,
82         MTD_UADDR_0x0AAA_0x0555,
83         MTD_UADDR_DONT_CARE,            /* Requires an arbitrary address */
84         MTD_UADDR_UNNECESSARY,          /* Does not require any address */
85 };
86
87
88 struct unlock_addr {
89         u32 addr1;
90         u32 addr2;
91 };
92
93
94 /*
95  * I don't like the fact that the first entry in unlock_addrs[]
96  * exists, but is for MTD_UADDR_NOT_SUPPORTED - and, therefore,
97  * should not be used.  The  problem is that structures with
98  * initializers have extra fields initialized to 0.  It is _very_
99  * desireable to have the unlock address entries for unsupported
100  * data widths automatically initialized - that means that
101  * MTD_UADDR_NOT_SUPPORTED must be 0 and the first entry here
102  * must go unused.
103  */
104 static const struct unlock_addr  unlock_addrs[] = {
105         [MTD_UADDR_NOT_SUPPORTED] = {
106                 .addr1 = 0xffff,
107                 .addr2 = 0xffff
108         },
109
110         [MTD_UADDR_0x0555_0x02AA] = {
111                 .addr1 = 0x0555,
112                 .addr2 = 0x02aa
113         },
114
115         [MTD_UADDR_0x0555_0x0AAA] = {
116                 .addr1 = 0x0555,
117                 .addr2 = 0x0aaa
118         },
119
120         [MTD_UADDR_0x5555_0x2AAA] = {
121                 .addr1 = 0x5555,
122                 .addr2 = 0x2aaa
123         },
124
125         [MTD_UADDR_0x0AAA_0x0555] = {
126                 .addr1 = 0x0AAA,
127                 .addr2 = 0x0555
128         },
129
130         [MTD_UADDR_DONT_CARE] = {
131                 .addr1 = 0x0000,      /* Doesn't matter which address */
132                 .addr2 = 0x0000       /* is used - must be last entry */
133         },
134
135         [MTD_UADDR_UNNECESSARY] = {
136                 .addr1 = 0x0000,
137                 .addr2 = 0x0000
138         }
139 };
140
141
142 struct amd_flash_info {
143         const __u16 mfr_id;
144         const __u16 dev_id;
145         const char *name;
146         const int DevSize;
147         const int NumEraseRegions;
148         const int CmdSet;
149         const __u8 uaddr[4];            /* unlock addrs for 8, 16, 32, 64 */
150         const ulong regions[6];
151 };
152
153 #define ERASEINFO(size,blocks) (size<<8)|(blocks-1)
154
155 #define SIZE_64KiB  16
156 #define SIZE_128KiB 17
157 #define SIZE_256KiB 18
158 #define SIZE_512KiB 19
159 #define SIZE_1MiB   20
160 #define SIZE_2MiB   21
161 #define SIZE_4MiB   22
162 #define SIZE_8MiB   23
163
164 static const struct amd_flash_info jedec_table[] = {
165 #ifdef CONFIG_SYS_FLASH_LEGACY_256Kx8
166         {
167                 .mfr_id         = (u16)SST_MANUFACT,
168                 .dev_id         = SST39LF020,
169                 .name           = "SST 39LF020",
170                 .uaddr          = {
171                         [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
172                 },
173                 .DevSize        = SIZE_256KiB,
174                 .CmdSet         = P_ID_AMD_STD,
175                 .NumEraseRegions= 1,
176                 .regions        = {
177                         ERASEINFO(0x01000,64),
178                 }
179         },
180 #endif
181 #ifdef CONFIG_SYS_FLASH_LEGACY_512Kx8
182         {
183                 .mfr_id         = (u16)AMD_MANUFACT,
184                 .dev_id         = AM29LV040B,
185                 .name           = "AMD AM29LV040B",
186                 .uaddr          = {
187                         [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
188                 },
189                 .DevSize        = SIZE_512KiB,
190                 .CmdSet         = P_ID_AMD_STD,
191                 .NumEraseRegions= 1,
192                 .regions        = {
193                         ERASEINFO(0x10000,8),
194                 }
195         },
196         {
197                 .mfr_id         = (u16)SST_MANUFACT,
198                 .dev_id         = SST39LF040,
199                 .name           = "SST 39LF040",
200                 .uaddr          = {
201                         [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
202                 },
203                 .DevSize        = SIZE_512KiB,
204                 .CmdSet         = P_ID_AMD_STD,
205                 .NumEraseRegions= 1,
206                 .regions        = {
207                         ERASEINFO(0x01000,128),
208                 }
209         },
210         {
211                 .mfr_id         = (u16)STM_MANUFACT,
212                 .dev_id         = STM_ID_M29W040B,
213                 .name           = "ST Micro M29W040B",
214                 .uaddr          = {
215                         [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
216                 },
217                 .DevSize        = SIZE_512KiB,
218                 .CmdSet         = P_ID_AMD_STD,
219                 .NumEraseRegions= 1,
220                 .regions        = {
221                         ERASEINFO(0x10000,8),
222                 }
223         },
224         {
225                 .mfr_id         = (u16)MX_MANUFACT,
226                 .dev_id         = MX29LV040,
227                 .name           = "MXIC MX29LV040",
228                 .uaddr          = {
229                         [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
230                 },
231                 .DevSize        = SIZE_512KiB,
232                 .CmdSet         = P_ID_AMD_STD,
233                 .NumEraseRegions= 1,
234                 .regions        = {
235                         ERASEINFO(0x10000, 8),
236                 }
237         },
238         {
239                 .mfr_id         = (u16)WINB_MANUFACT,
240                 .dev_id         = W39L040A,
241                 .name           = "WINBOND W39L040A",
242                 .uaddr          = {
243                         [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
244                 },
245                 .DevSize        = SIZE_512KiB,
246                 .CmdSet         = P_ID_AMD_STD,
247                 .NumEraseRegions= 1,
248                 .regions        = {
249                         ERASEINFO(0x10000, 8),
250                 }
251         },
252         {
253                 .mfr_id         = (u16)AMIC_MANUFACT,
254                 .dev_id         = A29L040,
255                 .name           = "AMIC A29L040",
256                 .uaddr          = {
257                         [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
258                 },
259                 .DevSize        = SIZE_512KiB,
260                 .CmdSet         = P_ID_AMD_STD,
261                 .NumEraseRegions= 1,
262                 .regions        = {
263                         ERASEINFO(0x10000, 8),
264                 }
265         },
266         {
267                 .mfr_id         = (u16)EON_MANUFACT,
268                 .dev_id         = EN29LV040A,
269                 .name           = "EON EN29LV040A",
270                 .uaddr          = {
271                         [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
272                 },
273                 .DevSize        = SIZE_512KiB,
274                 .CmdSet         = P_ID_AMD_STD,
275                 .NumEraseRegions= 1,
276                 .regions        = {
277                         ERASEINFO(0x10000, 8),
278                 }
279         },
280 #endif
281 #ifdef CONFIG_SYS_FLASH_LEGACY_512Kx16
282         {
283                 .mfr_id         = (u16)AMD_MANUFACT,
284                 .dev_id         = AM29F400BB,
285                 .name           = "AMD AM29F400BB",
286                 .uaddr          = {
287                         [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
288                 },
289                 .DevSize        = SIZE_512KiB,
290                 .CmdSet         = CFI_CMDSET_AMD_LEGACY,
291                 .NumEraseRegions= 4,
292                 .regions        = {
293                         ERASEINFO(0x04000, 1),
294                         ERASEINFO(0x02000, 2),
295                         ERASEINFO(0x08000, 1),
296                         ERASEINFO(0x10000, 7),
297                 }
298         },
299         {
300                 .mfr_id         = (u16)AMD_MANUFACT,
301                 .dev_id         = AM29LV400BB,
302                 .name           = "AMD AM29LV400BB",
303                 .uaddr          = {
304                         [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
305                 },
306                 .DevSize        = SIZE_512KiB,
307                 .CmdSet         = CFI_CMDSET_AMD_LEGACY,
308                 .NumEraseRegions= 4,
309                 .regions        = {
310                         ERASEINFO(0x04000,1),
311                         ERASEINFO(0x02000,2),
312                         ERASEINFO(0x08000,1),
313                         ERASEINFO(0x10000,7),
314                 }
315         },
316         {
317                 .mfr_id         = (u16)AMD_MANUFACT,
318                 .dev_id         = AM29LV800BB,
319                 .name           = "AMD AM29LV800BB",
320                 .uaddr          = {
321                         [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
322                 },
323                 .DevSize        = SIZE_1MiB,
324                 .CmdSet         = CFI_CMDSET_AMD_LEGACY,
325                 .NumEraseRegions= 4,
326                 .regions        = {
327                         ERASEINFO(0x04000, 1),
328                         ERASEINFO(0x02000, 2),
329                         ERASEINFO(0x08000, 1),
330                         ERASEINFO(0x10000, 15),
331                 }
332         },
333         {
334                 .mfr_id         = (u16)AMD_MANUFACT,
335                 .dev_id         = AM29LV800BT,
336                 .name           = "AMD AM29LV800BT",
337                 .uaddr          = {
338                         [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
339                 },
340                 .DevSize        = SIZE_1MiB,
341                 .CmdSet         = CFI_CMDSET_AMD_LEGACY,
342                 .NumEraseRegions= 4,
343                 .regions        = {
344                         ERASEINFO(0x10000, 15),
345                         ERASEINFO(0x08000, 1),
346                         ERASEINFO(0x02000, 2),
347                         ERASEINFO(0x04000, 1),
348                 }
349         },
350         {
351                 .mfr_id         = (u16)MX_MANUFACT,
352                 .dev_id         = AM29LV800BT,
353                 .name           = "MXIC MX29LV800BT",
354                 .uaddr          = {
355                         [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
356                 },
357                 .DevSize        = SIZE_1MiB,
358                 .CmdSet         = CFI_CMDSET_AMD_LEGACY,
359                 .NumEraseRegions= 4,
360                 .regions        = {
361                         ERASEINFO(0x10000, 15),
362                         ERASEINFO(0x08000, 1),
363                         ERASEINFO(0x02000, 2),
364                         ERASEINFO(0x04000, 1),
365                 }
366         },
367         {
368                 .mfr_id         = (u16)EON_ALT_MANU,
369                 .dev_id         = AM29LV800BT,
370                 .name           = "EON EN29LV800BT",
371                 .uaddr          = {
372                         [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
373                 },
374                 .DevSize        = SIZE_1MiB,
375                 .CmdSet         = CFI_CMDSET_AMD_LEGACY,
376                 .NumEraseRegions= 4,
377                 .regions        = {
378                         ERASEINFO(0x10000, 15),
379                         ERASEINFO(0x08000, 1),
380                         ERASEINFO(0x02000, 2),
381                         ERASEINFO(0x04000, 1),
382                 }
383         },
384         {
385                 .mfr_id         = (u16)STM_MANUFACT,
386                 .dev_id         = STM29F400BB,
387                 .name           = "ST Micro M29F400BB",
388                 .uaddr          = {
389                         [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
390                 },
391                 .DevSize                = SIZE_512KiB,
392                 .CmdSet                 = CFI_CMDSET_AMD_LEGACY,
393                 .NumEraseRegions        = 4,
394                 .regions                = {
395                         ERASEINFO(0x04000, 1),
396                         ERASEINFO(0x02000, 2),
397                         ERASEINFO(0x08000, 1),
398                         ERASEINFO(0x10000, 7),
399                 }
400         },
401 #endif
402 };
403
404 static inline void fill_info(flash_info_t *info, const struct amd_flash_info *jedec_entry, ulong base)
405 {
406         int i,j;
407         int sect_cnt;
408         int size_ratio;
409         int total_size;
410         enum uaddr uaddr_idx;
411
412         size_ratio = info->portwidth / info->chipwidth;
413
414         debug("Found JEDEC Flash: %s\n", jedec_entry->name);
415         info->vendor = jedec_entry->CmdSet;
416         /* Todo: do we need device-specific timeouts? */
417         info->erase_blk_tout = 30000;
418         info->buffer_write_tout = 1000;
419         info->write_tout = 100;
420         info->name = jedec_entry->name;
421
422         /* copy unlock addresses from device table to CFI info struct. This
423            is just here because the addresses are in the table anyway - if
424            the flash is not detected due to wrong unlock addresses,
425            flash_detect_legacy would have to try all of them before we even
426            get here. */
427         switch(info->chipwidth) {
428         case FLASH_CFI_8BIT:
429                 uaddr_idx = jedec_entry->uaddr[0];
430                 break;
431         case FLASH_CFI_16BIT:
432                 uaddr_idx = jedec_entry->uaddr[1];
433                 break;
434         case FLASH_CFI_32BIT:
435                 uaddr_idx = jedec_entry->uaddr[2];
436                 break;
437         default:
438                 uaddr_idx = MTD_UADDR_NOT_SUPPORTED;
439                 break;
440         }
441
442         debug("unlock address index %d\n", uaddr_idx);
443         info->addr_unlock1 = unlock_addrs[uaddr_idx].addr1;
444         info->addr_unlock2 = unlock_addrs[uaddr_idx].addr2;
445         debug("unlock addresses are 0x%lx/0x%lx\n",
446                 info->addr_unlock1, info->addr_unlock2);
447
448         sect_cnt = 0;
449         total_size = 0;
450         for (i = 0; i < jedec_entry->NumEraseRegions; i++) {
451                 ulong erase_region_size = jedec_entry->regions[i] >> 8;
452                 ulong erase_region_count = (jedec_entry->regions[i] & 0xff) + 1;
453
454                 total_size += erase_region_size * erase_region_count;
455                 debug("erase_region_count = %ld erase_region_size = %ld\n",
456                        erase_region_count, erase_region_size);
457                 for (j = 0; j < erase_region_count; j++) {
458                         if (sect_cnt >= CONFIG_SYS_MAX_FLASH_SECT) {
459                                 printf("ERROR: too many flash sectors\n");
460                                 break;
461                         }
462                         info->start[sect_cnt] = base;
463                         base += (erase_region_size * size_ratio);
464                         sect_cnt++;
465                 }
466         }
467         info->sector_count = sect_cnt;
468         info->size = total_size * size_ratio;
469 }
470
471 /*-----------------------------------------------------------------------
472  * match jedec ids against table. If a match is found, fill flash_info entry
473  */
474 int jedec_flash_match(flash_info_t *info, ulong base)
475 {
476         int ret = 0;
477         int i;
478         ulong mask = 0xFFFF;
479         if (info->chipwidth == 1)
480                 mask = 0xFF;
481
482         for (i = 0; i < ARRAY_SIZE(jedec_table); i++) {
483                 if ((jedec_table[i].mfr_id & mask) == (info->manufacturer_id & mask) &&
484                     (jedec_table[i].dev_id & mask) == (info->device_id & mask)) {
485                         fill_info(info, &jedec_table[i], base);
486                         ret = 1;
487                         break;
488                 }
489         }
490         return ret;
491 }