openocd: fix SPDX tag format for files .c
[fw/openocd] / src / flash / nor / numicro.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4  *   Copyright (C) 2011 by James K. Larson                                 *
5  *   jlarson@pacifier.com                                                  *
6  *                                                                         *
7  *   Copyright (C) 2013 Cosmin Gorgovan                                    *
8  *   cosmin [at] linux-geek [dot] org                                      *
9  *                                                                         *
10  *   Copyright (C) 2014 Pawel Si                                           *
11  *   stawel+openocd@gmail.com                                              *
12  *                                                                         *
13  *   Copyright (C) 2015 Nemui Trinomius                                    *
14  *   nemuisan_kawausogasuki@live.jp                                        *
15  ***************************************************************************/
16
17 #ifdef HAVE_CONFIG_H
18 #include <config.h>
19 #endif
20
21 #include "imp.h"
22 #include <helper/binarybuffer.h>
23 #include <target/algorithm.h>
24 #include <target/armv7m.h>
25 #include <target/cortex_m.h>
26
27 /* Nuvoton NuMicro register locations */
28 #define NUMICRO_SYS_BASE        0x50000000
29 #define NUMICRO_SYS_WRPROT      0x50000100
30 #define NUMICRO_SYS_IPRSTC1     0x50000008
31
32 #define NUMICRO_SYSCLK_BASE     0x50000200
33 #define NUMICRO_SYSCLK_PWRCON   0x50000200
34 #define NUMICRO_SYSCLK_CLKSEL0  0x50000210
35 #define NUMICRO_SYSCLK_CLKDIV   0x50000218
36 #define NUMICRO_SYSCLK_AHBCLK   0x50000204
37
38 #define NUMICRO_FLASH_BASE      0x5000C000
39 #define NUMICRO_FLASH_ISPCON    0x5000C000
40 #define NUMICRO_FLASH_ISPADR    0x5000C004
41 #define NUMICRO_FLASH_ISPDAT    0x5000C008
42 #define NUMICRO_FLASH_ISPCMD    0x5000C00C
43 #define NUMICRO_FLASH_ISPTRG    0x5000C010
44 #define NUMICRO_FLASH_CHEAT       0x5000C01C    /* Undocumented isp register(may be cheat register) */
45
46 #define NUMICRO_SCS_BASE        0xE000E000
47 #define NUMICRO_SCS_AIRCR       0xE000ED0C
48 #define NUMICRO_SCS_DHCSR       0xE000EDF0
49 #define NUMICRO_SCS_DEMCR       0xE000EDFC
50
51 #define NUMICRO_APROM_BASE      0x00000000
52 #define NUMICRO_DATA_BASE       0x0001F000
53 #define NUMICRO_LDROM_BASE      0x00100000
54 #define NUMICRO_CONFIG_BASE     0x00300000
55
56 #define NUMICRO_CONFIG0         0x5000C000
57 #define NUMICRO_CONFIG1         0x5000C004
58
59 /* Command register bits */
60 #define PWRCON_OSC22M         (1 << 2)
61 #define PWRCON_XTL12M         (1 << 0)
62
63 #define IPRSTC1_CPU_RST       (1 << 1)
64 #define IPRSTC1_CHIP_RST      (1 << 0)
65
66 #define AHBCLK_ISP_EN         (1 << 2)
67 #define AHBCLK_SRAM_EN        (1 << 4)
68 #define AHBCLK_TICK_EN        (1 << 5)
69
70 #define ISPCON_ISPEN          (1 << 0)
71 #define ISPCON_BS_AP          (0 << 1)
72 #define ISPCON_BS_LP          (1 << 1)
73 #define ISPCON_BS_MASK        (1 << 1)
74 #define ISPCON_APUEN          (1 << 3)
75 #define ISPCON_CFGUEN         (1 << 4)
76 #define ISPCON_LDUEN          (1 << 5)
77 #define ISPCON_ISPFF          (1 << 6)
78
79 #define CONFIG0_LOCK_MASK         (1 << 1)
80
81 /* isp commands */
82 #define ISPCMD_READ           0x00
83 #define ISPCMD_WRITE          0x21
84 #define ISPCMD_ERASE          0x22
85 #define ISPCMD_CHIPERASE      0x26   /* Undocumented isp "Chip-Erase" command */
86 #define ISPCMD_READ_CID       0x0B
87 #define ISPCMD_READ_DID       0x0C
88 #define ISPCMD_READ_UID       0x04
89 #define ISPCMD_VECMAP         0x2E
90 #define ISPTRG_ISPGO          (1 << 0)
91
92 /* access unlock keys */
93 #define REG_KEY1              0x59
94 #define REG_KEY2              0x16
95 #define REG_KEY3              0x88
96 #define REG_LOCK              0x00
97
98 /* flash pagesizes */
99 #define NUMICRO_PAGESIZE        512
100 /* flash MAX banks */
101 #define NUMICRO_MAX_FLASH_BANKS 4
102
103 /* flash bank structs */
104 struct numicro_flash_bank_type {
105         uint32_t base;
106         uint32_t size;
107 };
108
109 /* part structs */
110 struct numicro_cpu_type {
111         char *partname;
112         uint32_t partid;
113         unsigned int n_banks;
114         struct numicro_flash_bank_type bank[NUMICRO_MAX_FLASH_BANKS];
115 };
116
117 /* TODO : Support variable DataFlash region for 128kB Flash model */
118 #define NUMICRO_BANKS_NUC100(aprom_size) \
119         .n_banks = 4, \
120         { {NUMICRO_APROM_BASE, (aprom_size)}, {NUMICRO_DATA_BASE, 4*1024}, {NUMICRO_LDROM_BASE, 4*1024}, \
121         {NUMICRO_CONFIG_BASE, 1024} }
122
123 #define NUMICRO_BANKS_M051(aprom_size) \
124         .n_banks = 4, \
125         { {NUMICRO_APROM_BASE, (aprom_size)}, {NUMICRO_DATA_BASE, 4*1024}, {NUMICRO_LDROM_BASE, 4*1024}, \
126         {NUMICRO_CONFIG_BASE, 1024} }
127
128 #define NUMICRO_BANKS_MINI51(aprom_size) \
129         .n_banks = 3, \
130         { {NUMICRO_APROM_BASE, (aprom_size)}, {NUMICRO_LDROM_BASE, 2*1024}, {NUMICRO_CONFIG_BASE, 512} }
131
132 #define NUMICRO_BANKS_NANO(aprom_size) \
133         .n_banks = 4, \
134         { {NUMICRO_APROM_BASE, (aprom_size)}, {NUMICRO_DATA_BASE, 4*1024}, {NUMICRO_LDROM_BASE, 4*1024}, \
135         {NUMICRO_CONFIG_BASE, 1024} }
136
137 #define NUMICRO_BANKS_NUC400(aprom_size) \
138         .n_banks = 4, \
139         { {NUMICRO_APROM_BASE, (aprom_size)}, {NUMICRO_DATA_BASE, 4*1024}, {NUMICRO_LDROM_BASE, 16*1024}, \
140         {NUMICRO_CONFIG_BASE, 1024} }
141
142
143 static const struct numicro_cpu_type numicro_parts[] = {
144         /*PART NO*/     /*PART ID*/ /*Banks*/
145         /* NUC100 Version B */
146         {"NUC100LD2BN", 0x10010004, NUMICRO_BANKS_NUC100(64*1024)},
147         {"NUC100LD1BN", 0x10010005, NUMICRO_BANKS_NUC100(64*1024)},
148         {"NUC100LD0BN", 0x10010027, NUMICRO_BANKS_NUC100(64*1024)},
149         {"NUC100LC2BN", 0x10010007, NUMICRO_BANKS_NUC100(32*1024)},
150         {"NUC100LC1BN", 0x10010008, NUMICRO_BANKS_NUC100(32*1024)},
151         {"NUC100LC0BN", 0x10010028, NUMICRO_BANKS_NUC100(32*1024)},
152         {"NUC100LB2BN", 0x10010029, NUMICRO_BANKS_NUC100(16*1024)},
153         {"NUC100LB1BN", 0x10010030, NUMICRO_BANKS_NUC100(16*1024)},
154         {"NUC100LB0BN", 0x10010031, NUMICRO_BANKS_NUC100(16*1024)},
155         {"NUC100LA2BN", 0x10010032, NUMICRO_BANKS_NUC100(8*1024)},
156         {"NUC100LA1BN", 0x10010033, NUMICRO_BANKS_NUC100(8*1024)},
157         {"NUC100LA0BN", 0x10010034, NUMICRO_BANKS_NUC100(8*1024)},
158
159         {"NUC100RD2BN", 0x10010013, NUMICRO_BANKS_NUC100(64*1024)},
160         {"NUC100RD1BN", 0x10010014, NUMICRO_BANKS_NUC100(64*1024)},
161         {"NUC100RD0BN", 0x10010035, NUMICRO_BANKS_NUC100(64*1024)},
162         {"NUC100RC2BN", 0x10010016, NUMICRO_BANKS_NUC100(32*1024)},
163         {"NUC100RC1BN", 0x10010017, NUMICRO_BANKS_NUC100(32*1024)},
164         {"NUC100RC0BN", 0x10010036, NUMICRO_BANKS_NUC100(32*1024)},
165         {"NUC100RB2BN", 0x10010037, NUMICRO_BANKS_NUC100(16*1024)},
166         {"NUC100RB1BN", 0x10010038, NUMICRO_BANKS_NUC100(16*1024)},
167         {"NUC100RB0BN", 0x10010039, NUMICRO_BANKS_NUC100(16*1024)},
168         {"NUC100RA2BN", 0x10010040, NUMICRO_BANKS_NUC100(8*1024)},
169         {"NUC100RA1BN", 0x10010041, NUMICRO_BANKS_NUC100(8*1024)},
170         {"NUC100RA0BN", 0x10010042, NUMICRO_BANKS_NUC100(8*1024)},
171
172     /* NUC100 Version C */
173         {"NUC100LE3CN", 0x20010000, NUMICRO_BANKS_NUC100(128*1024)},
174         {"NUC100LE2CN", 0x20010001, NUMICRO_BANKS_NUC100(128*1024)},
175         {"NUC100LE1CN", 0x20010002, NUMICRO_BANKS_NUC100(128*1024)},
176         {"NUC100LD3CN", 0x20010003, NUMICRO_BANKS_NUC100(64*1024)},
177         {"NUC100LD2CN", 0x20010004, NUMICRO_BANKS_NUC100(64*1024)},
178         {"NUC100LD1CN", 0x20010005, NUMICRO_BANKS_NUC100(64*1024)},
179         {"NUC100LC3CN", 0x20010006, NUMICRO_BANKS_NUC100(32*1024)},
180         {"NUC100LC2CN", 0x20010007, NUMICRO_BANKS_NUC100(32*1024)},
181         {"NUC100LC1CN", 0x20010008, NUMICRO_BANKS_NUC100(32*1024)},
182         {"NUC100RE3CN", 0x20010009, NUMICRO_BANKS_NUC100(128*1024)},
183         {"NUC100RE2CN", 0x20010010, NUMICRO_BANKS_NUC100(128*1024)},
184         {"NUC100RE1CN", 0x20010011, NUMICRO_BANKS_NUC100(128*1024)},
185         {"NUC100RD3CN", 0x20010012, NUMICRO_BANKS_NUC100(64*1024)},
186         {"NUC100RD2CN", 0x20010013, NUMICRO_BANKS_NUC100(64*1024)},
187         {"NUC100RD1CN", 0x20010014, NUMICRO_BANKS_NUC100(64*1024)},
188         {"NUC100RC3CN", 0x20010015, NUMICRO_BANKS_NUC100(32*1024)},
189         {"NUC100RC2CN", 0x20010016, NUMICRO_BANKS_NUC100(32*1024)},
190         {"NUC100RC1CN", 0x20010017, NUMICRO_BANKS_NUC100(32*1024)},
191         {"NUC100VE3CN", 0x20010018, NUMICRO_BANKS_NUC100(128*1024)},
192         {"NUC100VE2CN", 0x20010019, NUMICRO_BANKS_NUC100(128*1024)},
193         {"NUC100VE1CN", 0x20010020, NUMICRO_BANKS_NUC100(128*1024)},
194         {"NUC100VD3CN", 0x20010021, NUMICRO_BANKS_NUC100(64*1024)},
195         {"NUC100VD2CN", 0x20010022, NUMICRO_BANKS_NUC100(64*1024)},
196         {"NUC100VD1CN", 0x20010023, NUMICRO_BANKS_NUC100(64*1024)},
197         {"NUC100VC3CN", 0x20010024, NUMICRO_BANKS_NUC100(32*1024)},
198         {"NUC100VC2CN", 0x20010025, NUMICRO_BANKS_NUC100(32*1024)},
199         {"NUC100VC1CN", 0x20010026, NUMICRO_BANKS_NUC100(32*1024)},
200
201     /* NUC100 Version B */
202         {"NUC101YD2BN", 0x10010143, NUMICRO_BANKS_NUC100(64*1024)},
203         {"NUC101YD1BN", 0x10010144, NUMICRO_BANKS_NUC100(64*1024)},
204         {"NUC101YD0BN", 0x10010145, NUMICRO_BANKS_NUC100(64*1024)},
205         {"NUC101YC2BN", 0x10010146, NUMICRO_BANKS_NUC100(32*1024)},
206         {"NUC101YC1BN", 0x10010147, NUMICRO_BANKS_NUC100(32*1024)},
207         {"NUC101YC0BN", 0x10010148, NUMICRO_BANKS_NUC100(32*1024)},
208         {"NUC101YB2BN", 0x10010149, NUMICRO_BANKS_NUC100(16*1024)},
209         {"NUC101YB1BN", 0x10010150, NUMICRO_BANKS_NUC100(16*1024)},
210         {"NUC101YB0BN", 0x10010151, NUMICRO_BANKS_NUC100(16*1024)},
211         {"NUC101YA2BN", 0x10010152, NUMICRO_BANKS_NUC100(8*1024)},
212         {"NUC101YA1BN", 0x10010153, NUMICRO_BANKS_NUC100(8*1024)},
213         {"NUC101YA0BN", 0x10010154, NUMICRO_BANKS_NUC100(8*1024)},
214
215         {"NUC101LD2BN", 0x10010104, NUMICRO_BANKS_NUC100(64*1024)},
216         {"NUC101LD1BN", 0x10010105, NUMICRO_BANKS_NUC100(64*1024)},
217         {"NUC101LD0BN", 0x10010127, NUMICRO_BANKS_NUC100(64*1024)},
218         {"NUC101LC2BN", 0x10010107, NUMICRO_BANKS_NUC100(32*1024)},
219         {"NUC101LC1BN", 0x10010108, NUMICRO_BANKS_NUC100(32*1024)},
220         {"NUC101LC0BN", 0x10010128, NUMICRO_BANKS_NUC100(32*1024)},
221         {"NUC101LB2BN", 0x10010129, NUMICRO_BANKS_NUC100(16*1024)},
222         {"NUC101LB1BN", 0x10010130, NUMICRO_BANKS_NUC100(16*1024)},
223         {"NUC101LB0BN", 0x10010131, NUMICRO_BANKS_NUC100(16*1024)},
224         {"NUC101LA2BN", 0x10010132, NUMICRO_BANKS_NUC100(8*1024)},
225         {"NUC101LA1BN", 0x10010133, NUMICRO_BANKS_NUC100(8*1024)},
226         {"NUC101LA0BN", 0x10010134, NUMICRO_BANKS_NUC100(8*1024)},
227
228         {"NUC101RD2BN", 0x10010113, NUMICRO_BANKS_NUC100(64*1024)},
229         {"NUC101RD1BN", 0x10010114, NUMICRO_BANKS_NUC100(64*1024)},
230         {"NUC101RD0BN", 0x10010135, NUMICRO_BANKS_NUC100(64*1024)},
231         {"NUC101RC2BN", 0x10010116, NUMICRO_BANKS_NUC100(32*1024)},
232         {"NUC101RC1BN", 0x10010117, NUMICRO_BANKS_NUC100(32*1024)},
233         {"NUC101RC0BN", 0x10010136, NUMICRO_BANKS_NUC100(32*1024)},
234         {"NUC101RB2BN", 0x10010137, NUMICRO_BANKS_NUC100(16*1024)},
235         {"NUC101RB1BN", 0x10010138, NUMICRO_BANKS_NUC100(16*1024)},
236         {"NUC101RB0BN", 0x10010139, NUMICRO_BANKS_NUC100(16*1024)},
237         {"NUC101RA2BN", 0x10010140, NUMICRO_BANKS_NUC100(8*1024)},
238         {"NUC101RA1BN", 0x10010141, NUMICRO_BANKS_NUC100(8*1024)},
239         {"NUC101RA0BN", 0x10010142, NUMICRO_BANKS_NUC100(8*1024)},
240
241     /* NUC101 Version C */
242         {"NUC101LE3CN", 0x20010100, NUMICRO_BANKS_NUC100(128*1024)},
243         {"NUC101LE2CN", 0x20010101, NUMICRO_BANKS_NUC100(128*1024)},
244         {"NUC101LE1CN", 0x20010102, NUMICRO_BANKS_NUC100(128*1024)},
245         {"NUC101LD3CN", 0x20010103, NUMICRO_BANKS_NUC100(64*1024)},
246         {"NUC101LD2CN", 0x20010104, NUMICRO_BANKS_NUC100(64*1024)},
247         {"NUC101LD1CN", 0x20010105, NUMICRO_BANKS_NUC100(64*1024)},
248         {"NUC101LC3CN", 0x20010106, NUMICRO_BANKS_NUC100(32*1024)},
249         {"NUC101LC2CN", 0x20010107, NUMICRO_BANKS_NUC100(32*1024)},
250         {"NUC101LC1CN", 0x20010108, NUMICRO_BANKS_NUC100(32*1024)},
251         {"NUC101RE3CN", 0x20010109, NUMICRO_BANKS_NUC100(128*1024)},
252         {"NUC101RE2CN", 0x20010110, NUMICRO_BANKS_NUC100(128*1024)},
253         {"NUC101RE1CN", 0x20010111, NUMICRO_BANKS_NUC100(128*1024)},
254
255         {"NUC101RD3CN", 0x20010112, NUMICRO_BANKS_NUC100(64*1024)},
256         {"NUC101RD2CN", 0x20010113, NUMICRO_BANKS_NUC100(64*1024)},
257         {"NUC101RD1CN", 0x20010114, NUMICRO_BANKS_NUC100(64*1024)},
258         {"NUC101RC3CN", 0x20010115, NUMICRO_BANKS_NUC100(32*1024)},
259         {"NUC101RC2CN", 0x20010116, NUMICRO_BANKS_NUC100(32*1024)},
260         {"NUC101RC1CN", 0x20010117, NUMICRO_BANKS_NUC100(32*1024)},
261         {"NUC101VE3CN", 0x20010118, NUMICRO_BANKS_NUC100(128*1024)},
262         {"NUC101VE2CN", 0x20010119, NUMICRO_BANKS_NUC100(128*1024)},
263         {"NUC101VE1CN", 0x20010120, NUMICRO_BANKS_NUC100(128*1024)},
264         {"NUC101VD3CN", 0x20010121, NUMICRO_BANKS_NUC100(64*1024)},
265         {"NUC101VD2CN", 0x20010122, NUMICRO_BANKS_NUC100(64*1024)},
266         {"NUC101VD1CN", 0x20010123, NUMICRO_BANKS_NUC100(64*1024)},
267         {"NUC101VC3CN", 0x20010124, NUMICRO_BANKS_NUC100(32*1024)},
268         {"NUC101VC2CN", 0x20010125, NUMICRO_BANKS_NUC100(32*1024)},
269         {"NUC101VC1CN", 0x20010126, NUMICRO_BANKS_NUC100(32*1024)},
270
271     /* NUC102 Version A */
272         {"NUC102ZD2AN", 0x00010231, NUMICRO_BANKS_NUC100(64*1024)},
273         {"NUC102ZC1AN", 0x00010235, NUMICRO_BANKS_NUC100(32*1024)},
274         {"NUC102LD2AN", 0x00010204, NUMICRO_BANKS_NUC100(64*1024)},
275         {"NUC102LC1AN", 0x00010208, NUMICRO_BANKS_NUC100(32*1024)},
276
277         {"NUC102RB3AN", 0x00010248, NUMICRO_BANKS_NUC100(16*1024)},
278         {"NUC102RB2AN", 0x00010249, NUMICRO_BANKS_NUC100(16*1024)},
279         {"NUC102RB1AN", 0x00010250, NUMICRO_BANKS_NUC100(16*1024)},
280         {"NUC102RA3AN", 0x00010251, NUMICRO_BANKS_NUC100(8*1024)},
281         {"NUC102RA2AN", 0x00010252, NUMICRO_BANKS_NUC100(8*1024)},
282         {"NUC102RA1AN", 0x00010253, NUMICRO_BANKS_NUC100(8*1024)},
283         {"NUC102VB3AN", 0x00010254, NUMICRO_BANKS_NUC100(16*1024)},
284         {"NUC102VB2AN", 0x00010255, NUMICRO_BANKS_NUC100(16*1024)},
285         {"NUC102VB1AN", 0x00010256, NUMICRO_BANKS_NUC100(16*1024)},
286         {"NUC102VA3AN", 0x00010257, NUMICRO_BANKS_NUC100(8*1024)},
287         {"NUC102VA2AN", 0x00010258, NUMICRO_BANKS_NUC100(8*1024)},
288         {"NUC102VA1AN", 0x00010259, NUMICRO_BANKS_NUC100(8*1024)},
289         {"NUC102LA0AN", 0x00010260, NUMICRO_BANKS_NUC100(8*1024)},
290         {"NUC102LB0AN", 0x00010261, NUMICRO_BANKS_NUC100(16*1024)},
291         {"NUC102LC0AN", 0x00010262, NUMICRO_BANKS_NUC100(32*1024)},
292         {"NUC102LD0AN", 0x00010263, NUMICRO_BANKS_NUC100(64*1024)},
293         {"NUC102RA0AN", 0x00010264, NUMICRO_BANKS_NUC100(8*1024)},
294         {"NUC102RB0AN", 0x00010265, NUMICRO_BANKS_NUC100(16*1024)},
295         {"NUC102RC0AN", 0x00010266, NUMICRO_BANKS_NUC100(32*1024)},
296         {"NUC102RD0AN", 0x00010267, NUMICRO_BANKS_NUC100(64*1024)},
297         {"NUC102VA0AN", 0x00010268, NUMICRO_BANKS_NUC100(8*1024)},
298         {"NUC102VB0AN", 0x00010269, NUMICRO_BANKS_NUC100(16*1024)},
299         {"NUC102VC0AN", 0x00010270, NUMICRO_BANKS_NUC100(32*1024)},
300         {"NUC102VD0AN", 0x00010271, NUMICRO_BANKS_NUC100(64*1024)},
301         {"NUC102ZA0AN", 0x00010272, NUMICRO_BANKS_NUC100(8*1024)},
302         {"NUC102ZB0AN", 0x00010273, NUMICRO_BANKS_NUC100(16*1024)},
303         {"NUC102ZC0AN", 0x00010274, NUMICRO_BANKS_NUC100(32*1024)},
304         {"NUC102ZD0AN", 0x00010275, NUMICRO_BANKS_NUC100(64*1024)},
305
306     /* NUC102 Version A */
307         {"NUC122LD2AN", 0x00012204, NUMICRO_BANKS_NUC100(64*1024)},
308         {"NUC122LD1AN", 0x00012205, NUMICRO_BANKS_NUC100(64*1024)},
309         {"NUC122LC2AN", 0x00012207, NUMICRO_BANKS_NUC100(32*1024)},
310         {"NUC122LC1AN", 0x00012208, NUMICRO_BANKS_NUC100(32*1024)},
311         {"NUC122RD2AN", 0x00012213, NUMICRO_BANKS_NUC100(64*1024)},
312         {"NUC122RD1AN", 0x00012214, NUMICRO_BANKS_NUC100(64*1024)},
313         {"NUC122RC2AN", 0x00012216, NUMICRO_BANKS_NUC100(32*1024)},
314         {"NUC122RC1AN", 0x00012217, NUMICRO_BANKS_NUC100(32*1024)},
315         {"NUC122SD2AN", 0x00012222, NUMICRO_BANKS_NUC100(64*1024)},
316         {"NUC122SD1AN", 0x00012223, NUMICRO_BANKS_NUC100(64*1024)},
317         {"NUC122SC2AN", 0x00012225, NUMICRO_BANKS_NUC100(32*1024)},
318         {"NUC122SC1AN", 0x00012226, NUMICRO_BANKS_NUC100(32*1024)},
319         {"NUC122ZD2AN", 0x00012231, NUMICRO_BANKS_NUC100(64*1024)},
320         {"NUC122ZD1AN", 0x00012232, NUMICRO_BANKS_NUC100(64*1024)},
321         {"NUC122ZC2AN", 0x00012234, NUMICRO_BANKS_NUC100(32*1024)},
322         {"NUC122ZC1AN", 0x00012235, NUMICRO_BANKS_NUC100(32*1024)},
323         {"NUC122ZB2AN", 0x00012237, NUMICRO_BANKS_NUC100(16*1024)},
324         {"NUC122ZB1AN", 0x00012238, NUMICRO_BANKS_NUC100(16*1024)},
325         {"NUC122ZA2AN", 0x00012240, NUMICRO_BANKS_NUC100(8*1024)},
326         {"NUC122ZA1AN", 0x00012241, NUMICRO_BANKS_NUC100(8*1024)},
327         {"NUC122LB2AN", 0x00012243, NUMICRO_BANKS_NUC100(16*1024)},
328         {"NUC122LB1AN", 0x00012244, NUMICRO_BANKS_NUC100(16*1024)},
329         {"NUC122LA2AN", 0x00012246, NUMICRO_BANKS_NUC100(8*1024)},
330         {"NUC122LA1AN", 0x00012247, NUMICRO_BANKS_NUC100(8*1024)},
331         {"NUC122RB2AN", 0x00012249, NUMICRO_BANKS_NUC100(16*1024)},
332         {"NUC122RB1AN", 0x00012250, NUMICRO_BANKS_NUC100(16*1024)},
333         {"NUC122RA2AN", 0x00012252, NUMICRO_BANKS_NUC100(8*1024)},
334         {"NUC122RA1AN", 0x00012253, NUMICRO_BANKS_NUC100(8*1024)},
335         {"NUC122SB2AN", 0x00012255, NUMICRO_BANKS_NUC100(16*1024)},
336         {"NUC122SB1AN", 0x00012256, NUMICRO_BANKS_NUC100(16*1024)},
337         {"NUC122SA2AN", 0x00012258, NUMICRO_BANKS_NUC100(8*1024)},
338         {"NUC122SA1AN", 0x00012259, NUMICRO_BANKS_NUC100(8*1024)},
339         {"NUC122LA0AN", 0x00012260, NUMICRO_BANKS_NUC100(8*1024)},
340         {"NUC122LB0AN", 0x00012261, NUMICRO_BANKS_NUC100(16*1024)},
341         {"NUC122LC0AN", 0x00012262, NUMICRO_BANKS_NUC100(32*1024)},
342         {"NUC122LD0AN", 0x00012263, NUMICRO_BANKS_NUC100(64*1024)},
343         {"NUC122RA0AN", 0x00012264, NUMICRO_BANKS_NUC100(8*1024)},
344         {"NUC122RB0AN", 0x00012265, NUMICRO_BANKS_NUC100(16*1024)},
345         {"NUC122RC0AN", 0x00012266, NUMICRO_BANKS_NUC100(32*1024)},
346         {"NUC122RD0AN", 0x00012267, NUMICRO_BANKS_NUC100(64*1024)},
347         {"NUC122SA0AN", 0x00012268, NUMICRO_BANKS_NUC100(8*1024)},
348         {"NUC122SB0AN", 0x00012269, NUMICRO_BANKS_NUC100(16*1024)},
349         {"NUC122SC0AN", 0x00012270, NUMICRO_BANKS_NUC100(32*1024)},
350         {"NUC122SD0AN", 0x00012271, NUMICRO_BANKS_NUC100(64*1024)},
351         {"NUC122ZA0AN", 0x00012272, NUMICRO_BANKS_NUC100(8*1024)},
352         {"NUC122ZB0AN", 0x00012273, NUMICRO_BANKS_NUC100(16*1024)},
353         {"NUC122ZC0AN", 0x00012274, NUMICRO_BANKS_NUC100(32*1024)},
354         {"NUC122ZD0AN", 0x00012275, NUMICRO_BANKS_NUC100(64*1024)},
355         {"NUC122YD2AN", 0x00012277, NUMICRO_BANKS_NUC100(64*1024)},
356         {"NUC122YD1AN", 0x00012278, NUMICRO_BANKS_NUC100(64*1024)},
357         {"NUC122YD0AN", 0x00012279, NUMICRO_BANKS_NUC100(64*1024)},
358         {"NUC122YC2AN", 0x00012281, NUMICRO_BANKS_NUC100(32*1024)},
359         {"NUC122YC1AN", 0x00012282, NUMICRO_BANKS_NUC100(32*1024)},
360         {"NUC122YC0AN", 0x00012283, NUMICRO_BANKS_NUC100(32*1024)},
361         {"NUC122YB2AN", 0x00012285, NUMICRO_BANKS_NUC100(16*1024)},
362         {"NUC122YB1AN", 0x00012286, NUMICRO_BANKS_NUC100(16*1024)},
363         {"NUC122YB0AN", 0x00012287, NUMICRO_BANKS_NUC100(16*1024)},
364         {"NUC122YA2AN", 0x00012289, NUMICRO_BANKS_NUC100(8*1024)},
365         {"NUC122YA1AN", 0x00012290, NUMICRO_BANKS_NUC100(8*1024)},
366         {"NUC122YA0AN", 0x00012291, NUMICRO_BANKS_NUC100(8*1024)},
367
368     /* NUC120 Version C */
369         {"NUC120LD2BN", 0x10012004, NUMICRO_BANKS_NUC100(64*1024)},
370         {"NUC120LD1BN", 0x10012005, NUMICRO_BANKS_NUC100(64*1024)},
371         {"NUC120LD0BN", 0x10012027, NUMICRO_BANKS_NUC100(64*1024)},
372         {"NUC120LC2BN", 0x10012007, NUMICRO_BANKS_NUC100(32*1024)},
373         {"NUC120LC1BN", 0x10012008, NUMICRO_BANKS_NUC100(32*1024)},
374         {"NUC120LC0BN", 0x10012028, NUMICRO_BANKS_NUC100(32*1024)},
375         {"NUC120LB2BN", 0x10012029, NUMICRO_BANKS_NUC100(16*1024)},
376         {"NUC120LB1BN", 0x10012030, NUMICRO_BANKS_NUC100(16*1024)},
377         {"NUC120LB0BN", 0x10012031, NUMICRO_BANKS_NUC100(16*1024)},
378         {"NUC120LA2BN", 0x10012032, NUMICRO_BANKS_NUC100(8*1024)},
379         {"NUC120LA1BN", 0x10012033, NUMICRO_BANKS_NUC100(8*1024)},
380         {"NUC120LA0BN", 0x10012034, NUMICRO_BANKS_NUC100(8*1024)},
381
382         {"NUC120RD2BN", 0x10012013, NUMICRO_BANKS_NUC100(64*1024)},
383         {"NUC120RD1BN", 0x10012014, NUMICRO_BANKS_NUC100(64*1024)},
384         {"NUC120RD0BN", 0x10012035, NUMICRO_BANKS_NUC100(64*1024)},
385         {"NUC120RC2BN", 0x10012016, NUMICRO_BANKS_NUC100(32*1024)},
386         {"NUC120RC1BN", 0x10012017, NUMICRO_BANKS_NUC100(32*1024)},
387         {"NUC120RC0BN", 0x10012036, NUMICRO_BANKS_NUC100(32*1024)},
388         {"NUC120RB2BN", 0x10012037, NUMICRO_BANKS_NUC100(16*1024)},
389         {"NUC120RB1BN", 0x10012038, NUMICRO_BANKS_NUC100(16*1024)},
390         {"NUC120RB0BN", 0x10012039, NUMICRO_BANKS_NUC100(16*1024)},
391         {"NUC120RA2BN", 0x10012040, NUMICRO_BANKS_NUC100(8*1024)},
392         {"NUC120RA1BN", 0x10012041, NUMICRO_BANKS_NUC100(8*1024)},
393         {"NUC120RA0BN", 0x10012042, NUMICRO_BANKS_NUC100(8*1024)},
394
395     /* NUC120 Version C */
396         {"NUC120LE3CN", 0x20012000, NUMICRO_BANKS_NUC100(128*1024)},
397         {"NUC120LE2CN", 0x20012001, NUMICRO_BANKS_NUC100(128*1024)},
398         {"NUC120LE1CN", 0x20012002, NUMICRO_BANKS_NUC100(128*1024)},
399         {"NUC120LD3CN", 0x20012003, NUMICRO_BANKS_NUC100(64*1024)},
400         {"NUC120LD2CN", 0x20012004, NUMICRO_BANKS_NUC100(64*1024)},
401         {"NUC120LD1CN", 0x20012005, NUMICRO_BANKS_NUC100(64*1024)},
402         {"NUC120LC3CN", 0x20012006, NUMICRO_BANKS_NUC100(32*1024)},
403         {"NUC120LC2CN", 0x20012007, NUMICRO_BANKS_NUC100(32*1024)},
404         {"NUC120LC1CN", 0x20012008, NUMICRO_BANKS_NUC100(32*1024)},
405         {"NUC120RE3CN", 0x20012009, NUMICRO_BANKS_NUC100(128*1024)},
406         {"NUC120RE2CN", 0x20012010, NUMICRO_BANKS_NUC100(128*1024)},
407         {"NUC120RE1CN", 0x20012011, NUMICRO_BANKS_NUC100(128*1024)},
408
409         {"NUC120RD3CN", 0x20012012, NUMICRO_BANKS_NUC100(64*1024)},
410         {"NUC120RD2CN", 0x20012013, NUMICRO_BANKS_NUC100(64*1024)},
411         {"NUC120RD1CN", 0x20012014, NUMICRO_BANKS_NUC100(64*1024)},
412         {"NUC120RC3CN", 0x20012015, NUMICRO_BANKS_NUC100(32*1024)},
413         {"NUC120RC2CN", 0x20012016, NUMICRO_BANKS_NUC100(32*1024)},
414         {"NUC120RC1CN", 0x20012017, NUMICRO_BANKS_NUC100(32*1024)},
415         {"NUC120VE3CN", 0x20012018, NUMICRO_BANKS_NUC100(128*1024)},
416         {"NUC120VE2CN", 0x20012019, NUMICRO_BANKS_NUC100(128*1024)},
417         {"NUC120VE1CN", 0x20012020, NUMICRO_BANKS_NUC100(128*1024)},
418         {"NUC120VD3CN", 0x20012021, NUMICRO_BANKS_NUC100(64*1024)},
419         {"NUC120VD2CN", 0x20012022, NUMICRO_BANKS_NUC100(64*1024)},
420         {"NUC120VD1CN", 0x20012023, NUMICRO_BANKS_NUC100(64*1024)},
421         {"NUC120VC3CN", 0x20012024, NUMICRO_BANKS_NUC100(32*1024)},
422         {"NUC120VC2CN", 0x20012025, NUMICRO_BANKS_NUC100(32*1024)},
423         {"NUC120VC1CN", 0x20012026, NUMICRO_BANKS_NUC100(32*1024)},
424
425     /* NUC120 Version B */
426         {"NUC130LD2BN", 0x10013004, NUMICRO_BANKS_NUC100(64*1024)},
427         {"NUC130LD1BN", 0x10013005, NUMICRO_BANKS_NUC100(64*1024)},
428         {"NUC130LD0BN", 0x10013027, NUMICRO_BANKS_NUC100(64*1024)},
429         {"NUC130LC2BN", 0x10013007, NUMICRO_BANKS_NUC100(32*1024)},
430         {"NUC130LC1BN", 0x10013008, NUMICRO_BANKS_NUC100(32*1024)},
431         {"NUC130LC0BN", 0x10013028, NUMICRO_BANKS_NUC100(32*1024)},
432         {"NUC130LB2BN", 0x10013029, NUMICRO_BANKS_NUC100(16*1024)},
433         {"NUC130LB1BN", 0x10013030, NUMICRO_BANKS_NUC100(16*1024)},
434         {"NUC130LB0BN", 0x10013031, NUMICRO_BANKS_NUC100(16*1024)},
435         {"NUC130LA2BN", 0x10013032, NUMICRO_BANKS_NUC100(8*1024)},
436         {"NUC130LA1BN", 0x10013033, NUMICRO_BANKS_NUC100(8*1024)},
437         {"NUC130LA0BN", 0x10013034, NUMICRO_BANKS_NUC100(8*1024)},
438
439         {"NUC130RD2BN", 0x10013013, NUMICRO_BANKS_NUC100(64*1024)},
440         {"NUC130RD1BN", 0x10013014, NUMICRO_BANKS_NUC100(64*1024)},
441         {"NUC130RD0BN", 0x10013035, NUMICRO_BANKS_NUC100(64*1024)},
442         {"NUC130RC2BN", 0x10013016, NUMICRO_BANKS_NUC100(32*1024)},
443         {"NUC130RC1BN", 0x10013017, NUMICRO_BANKS_NUC100(32*1024)},
444         {"NUC130RC0BN", 0x10013036, NUMICRO_BANKS_NUC100(32*1024)},
445         {"NUC130RB2BN", 0x10013037, NUMICRO_BANKS_NUC100(16*1024)},
446         {"NUC130RB1BN", 0x10013038, NUMICRO_BANKS_NUC100(16*1024)},
447         {"NUC130RB0BN", 0x10013039, NUMICRO_BANKS_NUC100(16*1024)},
448         {"NUC130RA2BN", 0x10013040, NUMICRO_BANKS_NUC100(8*1024)},
449         {"NUC130RA1BN", 0x10013041, NUMICRO_BANKS_NUC100(8*1024)},
450         {"NUC130RA0BN", 0x10013042, NUMICRO_BANKS_NUC100(8*1024)},
451
452     /* NUC130 Version C */
453         {"NUC130LE3CN", 0x20013000, NUMICRO_BANKS_NUC100(128*1024)},
454         {"NUC130LE2CN", 0x20013001, NUMICRO_BANKS_NUC100(128*1024)},
455         {"NUC130LE1CN", 0x20013002, NUMICRO_BANKS_NUC100(128*1024)},
456         {"NUC130LD3CN", 0x20013003, NUMICRO_BANKS_NUC100(64*1024)},
457         {"NUC130LD2CN", 0x20013004, NUMICRO_BANKS_NUC100(64*1024)},
458         {"NUC130LD1CN", 0x20013005, NUMICRO_BANKS_NUC100(64*1024)},
459         {"NUC130LC3CN", 0x20013006, NUMICRO_BANKS_NUC100(32*1024)},
460         {"NUC130LC2CN", 0x20013007, NUMICRO_BANKS_NUC100(32*1024)},
461         {"NUC130LC1CN", 0x20013008, NUMICRO_BANKS_NUC100(32*1024)},
462         {"NUC130RE3CN", 0x20013009, NUMICRO_BANKS_NUC100(128*1024)},
463         {"NUC130RE2CN", 0x20013010, NUMICRO_BANKS_NUC100(128*1024)},
464         {"NUC130RE1CN", 0x20013011, NUMICRO_BANKS_NUC100(128*1024)},
465
466         {"NUC130RD3CN", 0x20013012, NUMICRO_BANKS_NUC100(64*1024)},
467         {"NUC130RD2CN", 0x20013013, NUMICRO_BANKS_NUC100(64*1024)},
468         {"NUC130RD1CN", 0x20013014, NUMICRO_BANKS_NUC100(64*1024)},
469         {"NUC130RC3CN", 0x20013015, NUMICRO_BANKS_NUC100(32*1024)},
470         {"NUC130RC2CN", 0x20013016, NUMICRO_BANKS_NUC100(32*1024)},
471         {"NUC130RC1CN", 0x20013017, NUMICRO_BANKS_NUC100(32*1024)},
472         {"NUC130VE3CN", 0x20013018, NUMICRO_BANKS_NUC100(128*1024)},
473         {"NUC130VE2CN", 0x20013019, NUMICRO_BANKS_NUC100(128*1024)},
474         {"NUC130VE1CN", 0x20013020, NUMICRO_BANKS_NUC100(128*1024)},
475         {"NUC130VD3CN", 0x20013021, NUMICRO_BANKS_NUC100(64*1024)},
476         {"NUC130VD2CN", 0x20013022, NUMICRO_BANKS_NUC100(64*1024)},
477         {"NUC130VD1CN", 0x20013023, NUMICRO_BANKS_NUC100(64*1024)},
478         {"NUC130VC3CN", 0x20013024, NUMICRO_BANKS_NUC100(32*1024)},
479         {"NUC130VC2CN", 0x20013025, NUMICRO_BANKS_NUC100(32*1024)},
480         {"NUC130VC1CN", 0x20013026, NUMICRO_BANKS_NUC100(32*1024)},
481
482     /* NUC140 Version B */
483         {"NUC140LD2BN", 0x10014004, NUMICRO_BANKS_NUC100(64*1024)},
484         {"NUC140LD1BN", 0x10014005, NUMICRO_BANKS_NUC100(64*1024)},
485         {"NUC140LD0BN", 0x10014027, NUMICRO_BANKS_NUC100(64*1024)},
486         {"NUC140LC2BN", 0x10014007, NUMICRO_BANKS_NUC100(32*1024)},
487         {"NUC140LC1BN", 0x10014008, NUMICRO_BANKS_NUC100(32*1024)},
488         {"NUC140LC0BN", 0x10014028, NUMICRO_BANKS_NUC100(32*1024)},
489         {"NUC140LB2BN", 0x10014029, NUMICRO_BANKS_NUC100(16*1024)},
490         {"NUC140LB1BN", 0x10014030, NUMICRO_BANKS_NUC100(16*1024)},
491         {"NUC140LB0BN", 0x10014031, NUMICRO_BANKS_NUC100(16*1024)},
492         {"NUC140LA2BN", 0x10014032, NUMICRO_BANKS_NUC100(8*1024)},
493         {"NUC140LA1BN", 0x10014033, NUMICRO_BANKS_NUC100(8*1024)},
494         {"NUC140LA0BN", 0x10014034, NUMICRO_BANKS_NUC100(8*1024)},
495
496         {"NUC140RD2BN", 0x10014013, NUMICRO_BANKS_NUC100(64*1024)},
497         {"NUC140RD1BN", 0x10014014, NUMICRO_BANKS_NUC100(64*1024)},
498         {"NUC140RD0BN", 0x10014035, NUMICRO_BANKS_NUC100(64*1024)},
499         {"NUC140RC2BN", 0x10014016, NUMICRO_BANKS_NUC100(32*1024)},
500         {"NUC140RC1BN", 0x10014017, NUMICRO_BANKS_NUC100(32*1024)},
501         {"NUC140RC0BN", 0x10014036, NUMICRO_BANKS_NUC100(32*1024)},
502         {"NUC140RB2BN", 0x10014037, NUMICRO_BANKS_NUC100(16*1024)},
503         {"NUC140RB1BN", 0x10014038, NUMICRO_BANKS_NUC100(16*1024)},
504         {"NUC140RB0BN", 0x10014039, NUMICRO_BANKS_NUC100(16*1024)},
505         {"NUC140RA2BN", 0x10014040, NUMICRO_BANKS_NUC100(8*1024)},
506         {"NUC140RA1BN", 0x10014041, NUMICRO_BANKS_NUC100(8*1024)},
507         {"NUC140RA0BN", 0x10014042, NUMICRO_BANKS_NUC100(8*1024)},
508
509     /* NUC140 Version C */
510         {"NUC140LE3CN", 0x20014000, NUMICRO_BANKS_NUC100(128*1024)},
511         {"NUC140LE2CN", 0x20014001, NUMICRO_BANKS_NUC100(128*1024)},
512         {"NUC140LE1CN", 0x20014002, NUMICRO_BANKS_NUC100(128*1024)},
513         {"NUC140LD3CN", 0x20014003, NUMICRO_BANKS_NUC100(64*1024)},
514         {"NUC140LD2CN", 0x20014004, NUMICRO_BANKS_NUC100(64*1024)},
515         {"NUC140LD1CN", 0x20014005, NUMICRO_BANKS_NUC100(64*1024)},
516         {"NUC140LC3CN", 0x20014006, NUMICRO_BANKS_NUC100(32*1024)},
517         {"NUC140LC2CN", 0x20014007, NUMICRO_BANKS_NUC100(32*1024)},
518         {"NUC140LC1CN", 0x20014008, NUMICRO_BANKS_NUC100(32*1024)},
519         {"NUC140RE3CN", 0x20014009, NUMICRO_BANKS_NUC100(128*1024)},
520         {"NUC140RE2CN", 0x20014010, NUMICRO_BANKS_NUC100(128*1024)},
521         {"NUC140RE1CN", 0x20014011, NUMICRO_BANKS_NUC100(128*1024)},
522
523         {"NUC140RD3CN", 0x20014012, NUMICRO_BANKS_NUC100(64*1024)},
524         {"NUC140RD2CN", 0x20014013, NUMICRO_BANKS_NUC100(64*1024)},
525         {"NUC140RD1CN", 0x20014014, NUMICRO_BANKS_NUC100(64*1024)},
526         {"NUC140RC3CN", 0x20014015, NUMICRO_BANKS_NUC100(32*1024)},
527         {"NUC140RC2CN", 0x20014016, NUMICRO_BANKS_NUC100(32*1024)},
528         {"NUC140RC1CN", 0x20014017, NUMICRO_BANKS_NUC100(32*1024)},
529         {"NUC140VE3CN", 0x20014018, NUMICRO_BANKS_NUC100(128*1024)},
530         {"NUC140VE2CN", 0x20014019, NUMICRO_BANKS_NUC100(128*1024)},
531         {"NUC140VE1CN", 0x20014020, NUMICRO_BANKS_NUC100(128*1024)},
532         {"NUC140VD3CN", 0x20014021, NUMICRO_BANKS_NUC100(64*1024)},
533         {"NUC140VD2CN", 0x20014022, NUMICRO_BANKS_NUC100(64*1024)},
534         {"NUC140VD1CN", 0x20014023, NUMICRO_BANKS_NUC100(64*1024)},
535         {"NUC140VC3CN", 0x20014024, NUMICRO_BANKS_NUC100(32*1024)},
536         {"NUC140VC2CN", 0x20014025, NUMICRO_BANKS_NUC100(32*1024)},
537         {"NUC140VC1CN", 0x20014026, NUMICRO_BANKS_NUC100(32*1024)},
538
539     /* NUC100 Version A */
540         {"NUC100LE3AN", 0x00010000, NUMICRO_BANKS_NUC100(128*1024)},
541         {"NUC100LE2AN", 0x00010001, NUMICRO_BANKS_NUC100(128*1024)},
542         {"NUC100LE1AN", 0x00010002, NUMICRO_BANKS_NUC100(128*1024)},
543         {"NUC100LD3AN", 0x00010003, NUMICRO_BANKS_NUC100(64*1024)},
544         {"NUC100LD2AN", 0x00010004, NUMICRO_BANKS_NUC100(64*1024)},
545         {"NUC100LD1AN", 0x00010005, NUMICRO_BANKS_NUC100(64*1024)},
546         {"NUC100LC3AN", 0x00010006, NUMICRO_BANKS_NUC100(32*1024)},
547         {"NUC100LC2AN", 0x00010007, NUMICRO_BANKS_NUC100(32*1024)},
548         {"NUC100LC1AN", 0x00010008, NUMICRO_BANKS_NUC100(32*1024)},
549         {"NUC100RE3AN", 0x00010009, NUMICRO_BANKS_NUC100(128*1024)},
550         {"NUC100RE2AN", 0x00010010, NUMICRO_BANKS_NUC100(128*1024)},
551         {"NUC100RE1AN", 0x00010011, NUMICRO_BANKS_NUC100(128*1024)},
552         {"NUC100RD3AN", 0x00010012, NUMICRO_BANKS_NUC100(64*1024)},
553         {"NUC100RD2AN", 0x00010013, NUMICRO_BANKS_NUC100(64*1024)},
554         {"NUC100RD1AN", 0x00010014, NUMICRO_BANKS_NUC100(64*1024)},
555         {"NUC100RC3AN", 0x00010015, NUMICRO_BANKS_NUC100(32*1024)},
556         {"NUC100RC2AN", 0x00010016, NUMICRO_BANKS_NUC100(32*1024)},
557         {"NUC100RC1AN", 0x00010017, NUMICRO_BANKS_NUC100(32*1024)},
558         {"NUC100VE3AN", 0x00010018, NUMICRO_BANKS_NUC100(128*1024)},
559         {"NUC100VE2AN", 0x00010019, NUMICRO_BANKS_NUC100(128*1024)},
560         {"NUC100VE1AN", 0x00010020, NUMICRO_BANKS_NUC100(128*1024)},
561         {"NUC100VD3AN", 0x00010021, NUMICRO_BANKS_NUC100(64*1024)},
562         {"NUC100VD2AN", 0x00010022, NUMICRO_BANKS_NUC100(64*1024)},
563         {"NUC100VD1AN", 0x00010023, NUMICRO_BANKS_NUC100(64*1024)},
564         {"NUC100VC3AN", 0x00010024, NUMICRO_BANKS_NUC100(32*1024)},
565         {"NUC100VC2AN", 0x00010025, NUMICRO_BANKS_NUC100(32*1024)},
566         {"NUC100VC1AN", 0x00010026, NUMICRO_BANKS_NUC100(32*1024)},
567
568     /* NUC100 Version A */
569         {"NUC101LE3AN", 0x00010100, NUMICRO_BANKS_NUC100(128*1024)},
570         {"NUC101LE2AN", 0x00010101, NUMICRO_BANKS_NUC100(128*1024)},
571         {"NUC101LE1AN", 0x00010102, NUMICRO_BANKS_NUC100(128*1024)},
572         {"NUC101LD3AN", 0x00010103, NUMICRO_BANKS_NUC100(64*1024)},
573         {"NUC101LD2AN", 0x00010104, NUMICRO_BANKS_NUC100(64*1024)},
574         {"NUC101LD1AN", 0x00010105, NUMICRO_BANKS_NUC100(64*1024)},
575         {"NUC101LC3AN", 0x00010106, NUMICRO_BANKS_NUC100(32*1024)},
576         {"NUC101LC2AN", 0x00010107, NUMICRO_BANKS_NUC100(32*1024)},
577         {"NUC101LC1AN", 0x00010108, NUMICRO_BANKS_NUC100(32*1024)},
578         {"NUC101RE3AN", 0x00010109, NUMICRO_BANKS_NUC100(128*1024)},
579         {"NUC101RE2AN", 0x00010110, NUMICRO_BANKS_NUC100(128*1024)},
580         {"NUC101RE1AN", 0x00010111, NUMICRO_BANKS_NUC100(128*1024)},
581         {"NUC101RD3AN", 0x00010112, NUMICRO_BANKS_NUC100(64*1024)},
582         {"NUC101RD2AN", 0x00010113, NUMICRO_BANKS_NUC100(64*1024)},
583         {"NUC101RD1AN", 0x00010114, NUMICRO_BANKS_NUC100(64*1024)},
584         {"NUC101RC3AN", 0x00010115, NUMICRO_BANKS_NUC100(32*1024)},
585         {"NUC101RC2AN", 0x00010116, NUMICRO_BANKS_NUC100(32*1024)},
586         {"NUC101RC1AN", 0x00010117, NUMICRO_BANKS_NUC100(32*1024)},
587         {"NUC101VE3AN", 0x00010118, NUMICRO_BANKS_NUC100(128*1024)},
588         {"NUC101VE2AN", 0x00010119, NUMICRO_BANKS_NUC100(128*1024)},
589         {"NUC101VE1AN", 0x00010120, NUMICRO_BANKS_NUC100(128*1024)},
590         {"NUC101VD3AN", 0x00010121, NUMICRO_BANKS_NUC100(64*1024)},
591         {"NUC101VD2AN", 0x00010122, NUMICRO_BANKS_NUC100(64*1024)},
592         {"NUC101VD1AN", 0x00010123, NUMICRO_BANKS_NUC100(64*1024)},
593         {"NUC101VC3AN", 0x00010124, NUMICRO_BANKS_NUC100(32*1024)},
594         {"NUC101VC2AN", 0x00010125, NUMICRO_BANKS_NUC100(32*1024)},
595         {"NUC101VC1AN", 0x00010126, NUMICRO_BANKS_NUC100(32*1024)},
596
597     /* NUC120 Version A */
598         {"NUC120LE3AN", 0x00012000, NUMICRO_BANKS_NUC100(128*1024)},
599         {"NUC120LE2AN", 0x00012001, NUMICRO_BANKS_NUC100(128*1024)},
600         {"NUC120LE1AN", 0x00012002, NUMICRO_BANKS_NUC100(128*1024)},
601         {"NUC120LD3AN", 0x00012003, NUMICRO_BANKS_NUC100(64*1024)},
602         {"NUC120LD2AN", 0x00012004, NUMICRO_BANKS_NUC100(64*1024)},
603         {"NUC120LD1AN", 0x00012005, NUMICRO_BANKS_NUC100(64*1024)},
604         {"NUC120LC3AN", 0x00012006, NUMICRO_BANKS_NUC100(32*1024)},
605         {"NUC120LC2AN", 0x00012007, NUMICRO_BANKS_NUC100(32*1024)},
606         {"NUC120LC1AN", 0x00012008, NUMICRO_BANKS_NUC100(32*1024)},
607         {"NUC120RE3AN", 0x00012009, NUMICRO_BANKS_NUC100(128*1024)},
608         {"NUC120RE2AN", 0x00012010, NUMICRO_BANKS_NUC100(128*1024)},
609         {"NUC120RE1AN", 0x00012011, NUMICRO_BANKS_NUC100(128*1024)},
610         {"NUC120RD3AN", 0x00012012, NUMICRO_BANKS_NUC100(64*1024)},
611         {"NUC120RD2AN", 0x00012013, NUMICRO_BANKS_NUC100(64*1024)},
612         {"NUC120RD1AN", 0x00012014, NUMICRO_BANKS_NUC100(64*1024)},
613         {"NUC120RC3AN", 0x00012015, NUMICRO_BANKS_NUC100(32*1024)},
614         {"NUC120RC2AN", 0x00012016, NUMICRO_BANKS_NUC100(32*1024)},
615         {"NUC120RC1AN", 0x00012017, NUMICRO_BANKS_NUC100(32*1024)},
616         {"NUC120VE3AN", 0x00012018, NUMICRO_BANKS_NUC100(128*1024)},
617         {"NUC120VE2AN", 0x00012019, NUMICRO_BANKS_NUC100(128*1024)},
618         {"NUC120VE1AN", 0x00012020, NUMICRO_BANKS_NUC100(128*1024)},
619         {"NUC120VD3AN", 0x00012021, NUMICRO_BANKS_NUC100(64*1024)},
620         {"NUC120VD2AN", 0x00012022, NUMICRO_BANKS_NUC100(64*1024)},
621         {"NUC120VD1AN", 0x00012023, NUMICRO_BANKS_NUC100(64*1024)},
622         {"NUC120VC3AN", 0x00012024, NUMICRO_BANKS_NUC100(32*1024)},
623         {"NUC120VC2AN", 0x00012025, NUMICRO_BANKS_NUC100(32*1024)},
624         {"NUC120VC1AN", 0x00012026, NUMICRO_BANKS_NUC100(32*1024)},
625
626     /* NUC120 Version A */
627         {"NUC130LE3AN", 0x00013000, NUMICRO_BANKS_NUC100(128*1024)},
628         {"NUC130LE2AN", 0x00013001, NUMICRO_BANKS_NUC100(128*1024)},
629         {"NUC130LE1AN", 0x00013002, NUMICRO_BANKS_NUC100(128*1024)},
630         {"NUC130LD3AN", 0x00013003, NUMICRO_BANKS_NUC100(64*1024)},
631         {"NUC130LD2AN", 0x00013004, NUMICRO_BANKS_NUC100(64*1024)},
632         {"NUC130LD1AN", 0x00013005, NUMICRO_BANKS_NUC100(64*1024)},
633         {"NUC130LC3AN", 0x00013006, NUMICRO_BANKS_NUC100(32*1024)},
634         {"NUC130LC2AN", 0x00013007, NUMICRO_BANKS_NUC100(32*1024)},
635         {"NUC130LC1AN", 0x00013008, NUMICRO_BANKS_NUC100(32*1024)},
636         {"NUC130RE3AN", 0x00013009, NUMICRO_BANKS_NUC100(128*1024)},
637         {"NUC130RE2AN", 0x00013010, NUMICRO_BANKS_NUC100(128*1024)},
638         {"NUC130RE1AN", 0x00013011, NUMICRO_BANKS_NUC100(128*1024)},
639         {"NUC130RD3AN", 0x00013012, NUMICRO_BANKS_NUC100(64*1024)},
640         {"NUC130RD2AN", 0x00013013, NUMICRO_BANKS_NUC100(64*1024)},
641         {"NUC130RD1AN", 0x00013014, NUMICRO_BANKS_NUC100(64*1024)},
642         {"NUC130RC3AN", 0x00013015, NUMICRO_BANKS_NUC100(32*1024)},
643         {"NUC130RC2AN", 0x00013016, NUMICRO_BANKS_NUC100(32*1024)},
644         {"NUC130RC1AN", 0x00013017, NUMICRO_BANKS_NUC100(32*1024)},
645         {"NUC130VE3AN", 0x00013018, NUMICRO_BANKS_NUC100(128*1024)},
646         {"NUC130VE2AN", 0x00013019, NUMICRO_BANKS_NUC100(128*1024)},
647         {"NUC130VE1AN", 0x00013020, NUMICRO_BANKS_NUC100(128*1024)},
648         {"NUC130VD3AN", 0x00013021, NUMICRO_BANKS_NUC100(64*1024)},
649         {"NUC130VD2AN", 0x00013022, NUMICRO_BANKS_NUC100(64*1024)},
650         {"NUC130VD1AN", 0x00013023, NUMICRO_BANKS_NUC100(64*1024)},
651         {"NUC130VC3AN", 0x00013024, NUMICRO_BANKS_NUC100(32*1024)},
652         {"NUC130VC2AN", 0x00013025, NUMICRO_BANKS_NUC100(32*1024)},
653         {"NUC130VC1AN", 0x00013026, NUMICRO_BANKS_NUC100(32*1024)},
654
655     /* NUC140 Version A */
656         {"NUC140LE3AN", 0x00014000, NUMICRO_BANKS_NUC100(128*1024)},
657         {"NUC140LE2AN", 0x00014001, NUMICRO_BANKS_NUC100(128*1024)},
658         {"NUC140LE1AN", 0x00014002, NUMICRO_BANKS_NUC100(128*1024)},
659         {"NUC140LD3AN", 0x00014003, NUMICRO_BANKS_NUC100(64*1024)},
660         {"NUC140LD2AN", 0x00014004, NUMICRO_BANKS_NUC100(64*1024)},
661         {"NUC140LD1AN", 0x00014005, NUMICRO_BANKS_NUC100(64*1024)},
662         {"NUC140LC3AN", 0x00014006, NUMICRO_BANKS_NUC100(32*1024)},
663         {"NUC140LC2AN", 0x00014007, NUMICRO_BANKS_NUC100(32*1024)},
664         {"NUC140LC1AN", 0x00014008, NUMICRO_BANKS_NUC100(32*1024)},
665         {"NUC140RE3AN", 0x00014009, NUMICRO_BANKS_NUC100(128*1024)},
666         {"NUC140RE2AN", 0x00014010, NUMICRO_BANKS_NUC100(128*1024)},
667         {"NUC140RE1AN", 0x00014011, NUMICRO_BANKS_NUC100(128*1024)},
668         {"NUC140RD3AN", 0x00014012, NUMICRO_BANKS_NUC100(64*1024)},
669         {"NUC140RD2AN", 0x00014013, NUMICRO_BANKS_NUC100(64*1024)},
670         {"NUC140RD1AN", 0x00014014, NUMICRO_BANKS_NUC100(64*1024)},
671         {"NUC140RC3AN", 0x00014015, NUMICRO_BANKS_NUC100(32*1024)},
672         {"NUC140RC2AN", 0x00014016, NUMICRO_BANKS_NUC100(32*1024)},
673         {"NUC140RC1AN", 0x00014017, NUMICRO_BANKS_NUC100(32*1024)},
674         {"NUC140VE3AN", 0x00014018, NUMICRO_BANKS_NUC100(128*1024)},
675         {"NUC140VE2AN", 0x00014019, NUMICRO_BANKS_NUC100(128*1024)},
676         {"NUC140VE1AN", 0x00014020, NUMICRO_BANKS_NUC100(128*1024)},
677         {"NUC140VD3AN", 0x00014021, NUMICRO_BANKS_NUC100(64*1024)},
678         {"NUC140VD2AN", 0x00014022, NUMICRO_BANKS_NUC100(64*1024)},
679         {"NUC140VD1AN", 0x00014023, NUMICRO_BANKS_NUC100(64*1024)},
680         {"NUC140VC3AN", 0x00014024, NUMICRO_BANKS_NUC100(32*1024)},
681         {"NUC140VC2AN", 0x00014025, NUMICRO_BANKS_NUC100(32*1024)},
682         {"NUC140VC1AN", 0x00014026, NUMICRO_BANKS_NUC100(32*1024)},
683
684
685         /* M052 */
686         {"M052LAN"  , 0x00005200, NUMICRO_BANKS_M051(8*1024)},
687         {"M052PAN"  , 0x00005201, NUMICRO_BANKS_M051(8*1024)},
688         {"M052YAN"  , 0x00005202, NUMICRO_BANKS_M051(8*1024)},
689         {"M052ZAN"  , 0x00005203, NUMICRO_BANKS_M051(8*1024)},
690
691     /* M054 */
692         {"M054LAN"  , 0x00005400, NUMICRO_BANKS_M051(16*1024)},
693         {"M054PAN"  , 0x00005401, NUMICRO_BANKS_M051(16*1024)},
694         {"M054YAN"  , 0x00005402, NUMICRO_BANKS_M051(16*1024)},
695         {"M054ZAN"  , 0x00005403, NUMICRO_BANKS_M051(16*1024)},
696
697     /* M058 */
698         {"M058LAN"  , 0x00005800, NUMICRO_BANKS_M051(32*1024)},
699         {"M058PAN"  , 0x00005801, NUMICRO_BANKS_M051(32*1024)},
700         {"M058YAN"  , 0x00005802, NUMICRO_BANKS_M051(32*1024)},
701         {"M058ZAN"  , 0x00005803, NUMICRO_BANKS_M051(32*1024)},
702
703     /* M0516 */
704         {"M0516LAN" , 0x00005A00, NUMICRO_BANKS_M051(64*1024)},
705         {"M0516PAN" , 0x00005A01, NUMICRO_BANKS_M051(64*1024)},
706         {"M0516YAN" , 0x00005A02, NUMICRO_BANKS_M051(64*1024)},
707         {"M0516ZAN" , 0x00005A03, NUMICRO_BANKS_M051(64*1024)},
708         {"M051LBN"  , 0x10005100, NUMICRO_BANKS_M051(4*1024)},
709         {"M051PBN"  , 0x10005101, NUMICRO_BANKS_M051(4*1024)},
710         {"M051YBN"  , 0x10005102, NUMICRO_BANKS_M051(4*1024)},
711         {"M051ZBN"  , 0x10005103, NUMICRO_BANKS_M051(4*1024)},
712         {"M052LBN"  , 0x10005200, NUMICRO_BANKS_M051(8*1024)},
713         {"M052PBN"  , 0x10005201, NUMICRO_BANKS_M051(8*1024)},
714         {"M052YBN"  , 0x10005202, NUMICRO_BANKS_M051(8*1024)},
715         {"M052ZBN"  , 0x10005203, NUMICRO_BANKS_M051(8*1024)},
716         {"M054LBN"  , 0x10005400, NUMICRO_BANKS_M051(16*1024)},
717         {"M054PBN"  , 0x10005401, NUMICRO_BANKS_M051(16*1024)},
718         {"M054YBN"  , 0x10005402, NUMICRO_BANKS_M051(16*1024)},
719         {"M054ZBN"  , 0x10005403, NUMICRO_BANKS_M051(16*1024)},
720         {"M058LBN"  , 0x10005800, NUMICRO_BANKS_M051(32*1024)},
721         {"M058PBN"  , 0x10005801, NUMICRO_BANKS_M051(32*1024)},
722         {"M058YBN"  , 0x10005802, NUMICRO_BANKS_M051(32*1024)},
723         {"M058ZBN"  , 0x10005803, NUMICRO_BANKS_M051(32*1024)},
724         {"M0516LBN" , 0x10005A00, NUMICRO_BANKS_M051(64*1024)},
725         {"M0516PBN" , 0x10005A01, NUMICRO_BANKS_M051(64*1024)},
726         {"M0516YBN" , 0x10005A02, NUMICRO_BANKS_M051(64*1024)},
727         {"M0516ZBN" , 0x10005A03, NUMICRO_BANKS_M051(64*1024)},
728         {"M052LDN"  , 0x20005200, NUMICRO_BANKS_M051(8*1024)},
729         {"M054LDN"  , 0x20005400, NUMICRO_BANKS_M051(16*1024)},
730         {"M058LDN"  , 0x20005800, NUMICRO_BANKS_M051(32*1024)},
731         {"M0516LDN" , 0x20005A00, NUMICRO_BANKS_M051(64*1024)},
732         {"M052ZDN"  , 0x20005203, NUMICRO_BANKS_M051(8*1024)},
733         {"M054ZDN"  , 0x20005403, NUMICRO_BANKS_M051(16*1024)},
734         {"M058ZDN"  , 0x20005803, NUMICRO_BANKS_M051(32*1024)},
735         {"M0516ZDN" , 0x20005A03, NUMICRO_BANKS_M051(64*1024)},
736         {"M052TDN"  , 0x20005204, NUMICRO_BANKS_M051(8*1024)},
737         {"M054TDN"  , 0x20005404, NUMICRO_BANKS_M051(16*1024)},
738         {"M058TDN"  , 0x20005804, NUMICRO_BANKS_M051(32*1024)},
739         {"M0516TDN" , 0x20005A04, NUMICRO_BANKS_M051(64*1024)},
740         {"M052XDN"  , 0x20005205, NUMICRO_BANKS_M051(8*1024)},
741         {"M054XDN"  , 0x20005405, NUMICRO_BANKS_M051(16*1024)},
742         {"M058XDN"  , 0x20005805, NUMICRO_BANKS_M051(32*1024)},
743         {"M0516XDN" , 0x20005A05, NUMICRO_BANKS_M051(64*1024)},
744         {"M052LDE"  , 0x30005200, NUMICRO_BANKS_M051(8*1024)},
745         {"M054LDE"  , 0x30005400, NUMICRO_BANKS_M051(16*1024)},
746         {"M058LDE"  , 0x30005800, NUMICRO_BANKS_M051(32*1024)},
747         {"M0516LDE" , 0x30005A00, NUMICRO_BANKS_M051(64*1024)},
748         {"M052ZDE"  , 0x30005203, NUMICRO_BANKS_M051(8*1024)},
749         {"M054ZDE"  , 0x30005403, NUMICRO_BANKS_M051(16*1024)},
750         {"M058ZDE"  , 0x30005803, NUMICRO_BANKS_M051(32*1024)},
751         {"M0516ZDE" , 0x30005A03, NUMICRO_BANKS_M051(64*1024)},
752         {"M052TDE"  , 0x30005204, NUMICRO_BANKS_M051(8*1024)},
753         {"M054TDE"  , 0x30005404, NUMICRO_BANKS_M051(16*1024)},
754         {"M058TDE"  , 0x30005804, NUMICRO_BANKS_M051(32*1024)},
755         {"M0516TDE" , 0x30005A04, NUMICRO_BANKS_M051(64*1024)},
756         {"M052XDE"  , 0x30005205, NUMICRO_BANKS_M051(8*1024)},
757         {"M054XDE"  , 0x30005405, NUMICRO_BANKS_M051(16*1024)},
758         {"M058XDE"  , 0x30005805, NUMICRO_BANKS_M051(32*1024)},
759         {"M0516XDE" , 0x30005A05, NUMICRO_BANKS_M051(64*1024)},
760
761         /* Mini51 */
762         {"MINI51LAN",  0x00205100, NUMICRO_BANKS_MINI51(4*1024)},
763         {"MINI51QAN",  0x00205101, NUMICRO_BANKS_MINI51(4*1024)},
764         {"MINI51   ",  0x00205102, NUMICRO_BANKS_MINI51(4*1024)},
765         {"MINI51ZAN",  0x00205103, NUMICRO_BANKS_MINI51(4*1024)},
766         {"MINI51TAN",  0x00205104, NUMICRO_BANKS_MINI51(4*1024)},
767         {"MINI52LAN",  0x00205200, NUMICRO_BANKS_MINI51(8*1024)},
768         {"MINI52QAN",  0x00205201, NUMICRO_BANKS_MINI51(8*1024)},
769         {"MINI52   ",  0x00205202, NUMICRO_BANKS_MINI51(8*1024)},
770         {"MINI52ZAN",  0x00205203, NUMICRO_BANKS_MINI51(8*1024)},
771         {"MINI52TAN",  0x00205204, NUMICRO_BANKS_MINI51(8*1024)},
772         {"MINI54LAN",  0x00205400, NUMICRO_BANKS_MINI51(16*1024)},
773         {"MINI54QAN",  0x00205401, NUMICRO_BANKS_MINI51(16*1024)},
774         {"MINI54   ",  0x00205402, NUMICRO_BANKS_MINI51(16*1024)},
775         {"MINI54ZAN",  0x00205403, NUMICRO_BANKS_MINI51(16*1024)},
776         {"MINI54TAN",  0x00205404, NUMICRO_BANKS_MINI51(16*1024)},
777         {"MINI51LBN",  0x10205100, NUMICRO_BANKS_MINI51(4*1024)},
778         {"MINI51QBN",  0x10205101, NUMICRO_BANKS_MINI51(4*1024)},
779         {"MINI51   ",  0x10205102, NUMICRO_BANKS_MINI51(4*1024)},
780         {"MINI51ZBN",  0x10205103, NUMICRO_BANKS_MINI51(4*1024)},
781         {"MINI51TBN",  0x10205104, NUMICRO_BANKS_MINI51(4*1024)},
782         {"MINI52LBN",  0x10205200, NUMICRO_BANKS_MINI51(8*1024)},
783         {"MINI52QBN",  0x10205201, NUMICRO_BANKS_MINI51(8*1024)},
784         {"MINI52   ",  0x10205202, NUMICRO_BANKS_MINI51(8*1024)},
785         {"MINI52ZBN",  0x10205203, NUMICRO_BANKS_MINI51(8*1024)},
786         {"MINI52TBN",  0x10205204, NUMICRO_BANKS_MINI51(8*1024)},
787         {"MINI54LBN",  0x10205400, NUMICRO_BANKS_MINI51(16*1024)},
788         {"MINI54QBN",  0x10205401, NUMICRO_BANKS_MINI51(16*1024)},
789         {"MINI54   ",  0x10205402, NUMICRO_BANKS_MINI51(16*1024)},
790         {"MINI54ZBN" , 0x10205403, NUMICRO_BANKS_MINI51(16*1024)},
791         {"MINI54TBN" , 0x10205404, NUMICRO_BANKS_MINI51(16*1024)},
792         {"MINI51LDE" , 0x20205100, NUMICRO_BANKS_MINI51(4*1024)},
793         {"MINI51QDE" , 0x20205101, NUMICRO_BANKS_MINI51(4*1024)},
794         {"MINI51   " , 0x20205102, NUMICRO_BANKS_MINI51(4*1024)},
795         {"MINI51ZDE" , 0x20205103, NUMICRO_BANKS_MINI51(4*1024)},
796         {"MINI51TDE" , 0x20205104, NUMICRO_BANKS_MINI51(4*1024)},
797         {"MINI51FDE" , 0x20205105, NUMICRO_BANKS_MINI51(4*1024)},
798         {"MINI52LDE" , 0x20205200, NUMICRO_BANKS_MINI51(8*1024)},
799         {"MINI52QDE" , 0x20205201, NUMICRO_BANKS_MINI51(8*1024)},
800         {"MINI52   " , 0x20205202, NUMICRO_BANKS_MINI51(8*1024)},
801         {"MINI52ZDE" , 0x20205203, NUMICRO_BANKS_MINI51(8*1024)},
802         {"MINI52TDE" , 0x20205204, NUMICRO_BANKS_MINI51(8*1024)},
803         {"MINI52FDE" , 0x20205205, NUMICRO_BANKS_MINI51(8*1024)},
804         {"MINI54LDE" , 0x20205400, NUMICRO_BANKS_MINI51(16*1024)},
805         {"MINI54QDE" , 0x20205401, NUMICRO_BANKS_MINI51(16*1024)},
806         {"MINI54   " , 0x20205402, NUMICRO_BANKS_MINI51(16*1024)},
807         {"MINI54ZDE" , 0x20205403, NUMICRO_BANKS_MINI51(16*1024)},
808         {"MINI54TDE" , 0x20205404, NUMICRO_BANKS_MINI51(16*1024)},
809         {"MINI54FDE" , 0x20205405, NUMICRO_BANKS_MINI51(16*1024)},
810         {"MINI55LDE" , 0x20205500, NUMICRO_BANKS_MINI51(16*1024)},
811
812         /* NANO100 */
813         {"NANO100VF3AN" , 0x00110000, NUMICRO_BANKS_NANO(256*1024)},
814         {"NANO100VF2AN" , 0x00110001, NUMICRO_BANKS_NANO(256*1024)},
815         {"NANO100RF3AN" , 0x00110002, NUMICRO_BANKS_NANO(256*1024)},
816         {"NANO100RF2AN" , 0x00110003, NUMICRO_BANKS_NANO(256*1024)},
817         {"NANO100LF3AN" , 0x00110004, NUMICRO_BANKS_NANO(256*1024)},
818         {"NANO100LF2AN" , 0x00110005, NUMICRO_BANKS_NANO(256*1024)},
819         {"NANO100VE3AN" , 0x00110006, NUMICRO_BANKS_NANO(128*1024)},
820         {"NANO100VE2AN" , 0x00110007, NUMICRO_BANKS_NANO(128*1024)},
821         {"NANO100RE3AN" , 0x00110008, NUMICRO_BANKS_NANO(128*1024)},
822         {"NANO100RE2AN" , 0x00110009, NUMICRO_BANKS_NANO(128*1024)},
823         {"NANO100LE3AN" , 0x00110010, NUMICRO_BANKS_NANO(128*1024)},
824         {"NANO100LE2AN" , 0x00110011, NUMICRO_BANKS_NANO(128*1024)},
825         {"NANO100VD3AN" , 0x00110012, NUMICRO_BANKS_NANO(64*1024)},
826         {"NANO100VD2AN" , 0x00110013, NUMICRO_BANKS_NANO(64*1024)},
827         {"NANO100VD1AN" , 0x00110014, NUMICRO_BANKS_NANO(64*1024)},
828         {"NANO100RD3AN" , 0x00110015, NUMICRO_BANKS_NANO(64*1024)},
829         {"NANO100RD2AN" , 0x00110016, NUMICRO_BANKS_NANO(64*1024)},
830         {"NANO100RD1AN" , 0x00110017, NUMICRO_BANKS_NANO(64*1024)},
831         {"NANO100LD3AN" , 0x00110018, NUMICRO_BANKS_NANO(64*1024)},
832         {"NANO100LD2AN" , 0x00110019, NUMICRO_BANKS_NANO(64*1024)},
833         {"NANO100LD1AN" , 0x00110020, NUMICRO_BANKS_NANO(64*1024)},
834         {"NANO100VC2AN" , 0x00110021, NUMICRO_BANKS_NANO(32*1024)},
835         {"NANO100VC1AN" , 0x00110022, NUMICRO_BANKS_NANO(32*1024)},
836         {"NANO100RC2AN" , 0x00110023, NUMICRO_BANKS_NANO(32*1024)},
837         {"NANO100RC1AN" , 0x00110024, NUMICRO_BANKS_NANO(32*1024)},
838         {"NANO100LC2AN" , 0x00110025, NUMICRO_BANKS_NANO(32*1024)},
839         {"NANO100LC1AN" , 0x00110026, NUMICRO_BANKS_NANO(32*1024)},
840         {"NANO100VB1AN" , 0x00110027, NUMICRO_BANKS_NANO(16*1024)},
841         {"NANO100VB0AN" , 0x00110028, NUMICRO_BANKS_NANO(16*1024)},
842         {"NANO100RB1AN" , 0x00110029, NUMICRO_BANKS_NANO(16*1024)},
843
844         {"NANO110VF3AN" , 0x00111000, NUMICRO_BANKS_NANO(256*1024)},
845         {"NANO110VF2AN" , 0x00111001, NUMICRO_BANKS_NANO(256*1024)},
846         {"NANO110RF3AN" , 0x00111002, NUMICRO_BANKS_NANO(256*1024)},
847         {"NANO110RF2AN" , 0x00111003, NUMICRO_BANKS_NANO(256*1024)},
848         {"NANO110VE3AN" , 0x00111006, NUMICRO_BANKS_NANO(128*1024)},
849         {"NANO110VE2AN" , 0x00111007, NUMICRO_BANKS_NANO(128*1024)},
850         {"NANO110RE3AN" , 0x00111008, NUMICRO_BANKS_NANO(128*1024)},
851         {"NANO110RE2AN" , 0x00111009, NUMICRO_BANKS_NANO(128*1024)},
852         {"NANO110VD3AN" , 0x00111012, NUMICRO_BANKS_NANO(64*1024)},
853         {"NANO110VD2AN" , 0x00111013, NUMICRO_BANKS_NANO(64*1024)},
854         {"NANO110VD1AN" , 0x00111014, NUMICRO_BANKS_NANO(64*1024)},
855         {"NANO110RD3AN" , 0x00111015, NUMICRO_BANKS_NANO(64*1024)},
856         {"NANO110RD2AN" , 0x00111016, NUMICRO_BANKS_NANO(64*1024)},
857         {"NANO110RD1AN" , 0x00111017, NUMICRO_BANKS_NANO(64*1024)},
858         {"NANO110VC2AN" , 0x00111021, NUMICRO_BANKS_NANO(32*1024)},
859         {"NANO110VC1AN" , 0x00111022, NUMICRO_BANKS_NANO(32*1024)},
860         {"NANO110SC2AN" , 0x00111023, NUMICRO_BANKS_NANO(32*1024)},
861         {"NANO110SC1AN" , 0x00111024, NUMICRO_BANKS_NANO(32*1024)},
862         {"NANO120VF3AN" , 0x00112000, NUMICRO_BANKS_NANO(256*1024)},
863         {"NANO120VF2AN" , 0x00112001, NUMICRO_BANKS_NANO(256*1024)},
864         {"NANO120RF3AN" , 0x00112002, NUMICRO_BANKS_NANO(256*1024)},
865         {"NANO120RF2AN" , 0x00112003, NUMICRO_BANKS_NANO(256*1024)},
866         {"NANO120LF3AN" , 0x00112004, NUMICRO_BANKS_NANO(256*1024)},
867         {"NANO120LF2AN" , 0x00112005, NUMICRO_BANKS_NANO(256*1024)},
868         {"NANO120VE3AN" , 0x00112006, NUMICRO_BANKS_NANO(128*1024)},
869         {"NANO120VE2AN" , 0x00112007, NUMICRO_BANKS_NANO(128*1024)},
870         {"NANO120RE3AN" , 0x00112008, NUMICRO_BANKS_NANO(128*1024)},
871         {"NANO120RE2AN" , 0x00112009, NUMICRO_BANKS_NANO(128*1024)},
872         {"NANO120LE3AN" , 0x00112010, NUMICRO_BANKS_NANO(128*1024)},
873         {"NANO120LE2AN" , 0x00112011, NUMICRO_BANKS_NANO(128*1024)},
874         {"NANO120VD3AN" , 0x00112012, NUMICRO_BANKS_NANO(64*1024)},
875         {"NANO120VD2AN" , 0x00112013, NUMICRO_BANKS_NANO(64*1024)},
876         {"NANO120VD1AN" , 0x00112014, NUMICRO_BANKS_NANO(64*1024)},
877         {"NANO120SD3AN" , 0x00112015, NUMICRO_BANKS_NANO(64*1024)},
878         {"NANO120SD2AN" , 0x00112016, NUMICRO_BANKS_NANO(64*1024)},
879         {"NANO120SD1AN" , 0x00112017, NUMICRO_BANKS_NANO(64*1024)},
880         {"NANO120LD3AN" , 0x00112018, NUMICRO_BANKS_NANO(64*1024)},
881         {"NANO120LD2AN" , 0x00112019, NUMICRO_BANKS_NANO(64*1024)},
882         {"NANO120LD1AN" , 0x00112020, NUMICRO_BANKS_NANO(64*1024)},
883         {"NANO120VC2AN" , 0x00112021, NUMICRO_BANKS_NANO(32*1024)},
884         {"NANO120VC1AN" , 0x00112022, NUMICRO_BANKS_NANO(32*1024)},
885         {"NANO120SC2AN" , 0x00112023, NUMICRO_BANKS_NANO(32*1024)},
886         {"NANO120SC1AN" , 0x00112024, NUMICRO_BANKS_NANO(32*1024)},
887         {"NANO120LC2AN" , 0x00112025, NUMICRO_BANKS_NANO(32*1024)},
888         {"NANO120LC1AN" , 0x00112026, NUMICRO_BANKS_NANO(32*1024)},
889         {"NANO130VF3AN" , 0x00113000, NUMICRO_BANKS_NANO(256*1024)},
890         {"NANO130VF2AN" , 0x00113001, NUMICRO_BANKS_NANO(256*1024)},
891         {"NANO130SF3AN" , 0x00113002, NUMICRO_BANKS_NANO(256*1024)},
892         {"NANO130SF2AN" , 0x00113003, NUMICRO_BANKS_NANO(256*1024)},
893         {"NANO130VE3AN" , 0x00113006, NUMICRO_BANKS_NANO(128*1024)},
894         {"NANO130VE2AN" , 0x00113007, NUMICRO_BANKS_NANO(128*1024)},
895         {"NANO130SE3AN" , 0x00113008, NUMICRO_BANKS_NANO(128*1024)},
896         {"NANO130SE2AN" , 0x00113009, NUMICRO_BANKS_NANO(128*1024)},
897         {"NANO130VD3AN" , 0x00113012, NUMICRO_BANKS_NANO(64*1024)},
898         {"NANO130VD2AN" , 0x00113013, NUMICRO_BANKS_NANO(64*1024)},
899         {"NANO130VD1AN" , 0x00113014, NUMICRO_BANKS_NANO(64*1024)},
900         {"NANO130SD3AN" , 0x00113015, NUMICRO_BANKS_NANO(64*1024)},
901         {"NANO130SD2AN" , 0x00113016, NUMICRO_BANKS_NANO(64*1024)},
902         {"NANO130SD1AN" , 0x00113017, NUMICRO_BANKS_NANO(64*1024)},
903         {"NANO130VC2AN" , 0x00113021, NUMICRO_BANKS_NANO(32*1024)},
904         {"NANO130VC1AN" , 0x00113022, NUMICRO_BANKS_NANO(32*1024)},
905         {"NANO130SC2AN" , 0x00113023, NUMICRO_BANKS_NANO(32*1024)},
906         {"NANO130SC1AN" , 0x00113024, NUMICRO_BANKS_NANO(32*1024)},
907         {"NANO100KE3BN" , 0x00110030, NUMICRO_BANKS_NANO(128*1024)},
908         {"NANO100KE2BN" , 0x00110031, NUMICRO_BANKS_NANO(128*1024)},
909         {"NANO100VE3BN" , 0x00110032, NUMICRO_BANKS_NANO(128*1024)},
910         {"NANO100VE2BN" , 0x00110033, NUMICRO_BANKS_NANO(128*1024)},
911         {"NANO100SE3BN" , 0x00110034, NUMICRO_BANKS_NANO(128*1024)},
912         {"NANO100SE2BN" , 0x00110035, NUMICRO_BANKS_NANO(128*1024)},
913         {"NANO100LE3BN" , 0x00110036, NUMICRO_BANKS_NANO(128*1024)},
914         {"NANO100LE2BN" , 0x00110037, NUMICRO_BANKS_NANO(128*1024)},
915         {"NANO100KD3BN" , 0x00110038, NUMICRO_BANKS_NANO(64*1024)},
916         {"NANO100KD2BN" , 0x00110039, NUMICRO_BANKS_NANO(64*1024)},
917         {"NANO100VD3BN" , 0x0011003A, NUMICRO_BANKS_NANO(64*1024)},
918         {"NANO100VD2BN" , 0x0011003B, NUMICRO_BANKS_NANO(64*1024)},
919         {"NANO100SD3BN" , 0x0011003C, NUMICRO_BANKS_NANO(64*1024)},
920         {"NANO100SD2BN" , 0x0011003D, NUMICRO_BANKS_NANO(64*1024)},
921         {"NANO100LD3BN" , 0x0011003E, NUMICRO_BANKS_NANO(64*1024)},
922         {"NANO100LD2BN" , 0x0011003F, NUMICRO_BANKS_NANO(64*1024)},
923         {"NANO100KC2BN" , 0x00110040, NUMICRO_BANKS_NANO(32*1024)},
924         {"NANO100VC2BN" , 0x00110041, NUMICRO_BANKS_NANO(32*1024)},
925         {"NANO100SC2BN" , 0x00110042, NUMICRO_BANKS_NANO(32*1024)},
926         {"NANO100LC2BN" , 0x00110043, NUMICRO_BANKS_NANO(32*1024)},
927         {"NANO110KE3BN" , 0x00111030, NUMICRO_BANKS_NANO(128*1024)},
928         {"NANO110KE2BN" , 0x00111031, NUMICRO_BANKS_NANO(128*1024)},
929         {"NANO110VE3BN" , 0x00111032, NUMICRO_BANKS_NANO(128*1024)},
930         {"NANO110VE2BN" , 0x00111033, NUMICRO_BANKS_NANO(128*1024)},
931         {"NANO110SE3BN" , 0x00111034, NUMICRO_BANKS_NANO(128*1024)},
932         {"NANO110SE2BN" , 0x00111035, NUMICRO_BANKS_NANO(128*1024)},
933         {"NANO110KD3BN" , 0x00111038, NUMICRO_BANKS_NANO(64*1024)},
934         {"NANO110KD2BN" , 0x00111039, NUMICRO_BANKS_NANO(64*1024)},
935         {"NANO110VD3BN" , 0x0011103A, NUMICRO_BANKS_NANO(64*1024)},
936         {"NANO110VD2BN" , 0x0011103B, NUMICRO_BANKS_NANO(64*1024)},
937         {"NANO110SD3BN" , 0x0011103C, NUMICRO_BANKS_NANO(64*1024)},
938         {"NANO110SD2BN" , 0x0011103D, NUMICRO_BANKS_NANO(64*1024)},
939         {"NANO110KC2BN" , 0x00111040, NUMICRO_BANKS_NANO(32*1024)},
940         {"NANO110VC2BN" , 0x00111041, NUMICRO_BANKS_NANO(32*1024)},
941         {"NANO110SC2BN" , 0x00111042, NUMICRO_BANKS_NANO(32*1024)},
942         {"NANO120KE3BN" , 0x00112030, NUMICRO_BANKS_NANO(128*1024)},
943         {"NANO120KE2BN" , 0x00112031, NUMICRO_BANKS_NANO(128*1024)},
944         {"NANO120VE3BN" , 0x00112032, NUMICRO_BANKS_NANO(128*1024)},
945         {"NANO120VE2BN" , 0x00112033, NUMICRO_BANKS_NANO(128*1024)},
946         {"NANO120SE3BN" , 0x00112034, NUMICRO_BANKS_NANO(128*1024)},
947         {"NANO120SE2BN" , 0x00112035, NUMICRO_BANKS_NANO(128*1024)},
948         {"NANO120LE3BN" , 0x00112036, NUMICRO_BANKS_NANO(128*1024)},
949         {"NANO120LE2BN" , 0x00112037, NUMICRO_BANKS_NANO(128*1024)},
950         {"NANO120KD3BN" , 0x00112038, NUMICRO_BANKS_NANO(64*1024)},
951         {"NANO120KD2BN" , 0x00112039, NUMICRO_BANKS_NANO(64*1024)},
952         {"NANO120VD3BN" , 0x0011203A, NUMICRO_BANKS_NANO(64*1024)},
953         {"NANO120VD2BN" , 0x0011203B, NUMICRO_BANKS_NANO(64*1024)},
954         {"NANO120SD3BN" , 0x0011203C, NUMICRO_BANKS_NANO(64*1024)},
955         {"NANO120SD2BN" , 0x0011203D, NUMICRO_BANKS_NANO(64*1024)},
956         {"NANO120LD3BN" , 0x0011203E, NUMICRO_BANKS_NANO(64*1024)},
957         {"NANO120LD2BN" , 0x0011203F, NUMICRO_BANKS_NANO(64*1024)},
958         {"NANO120KC2BN" , 0x00112040, NUMICRO_BANKS_NANO(32*1024)},
959         {"NANO120VC2BN" , 0x00112041, NUMICRO_BANKS_NANO(32*1024)},
960         {"NANO120SC2BN" , 0x00112042, NUMICRO_BANKS_NANO(32*1024)},
961         {"NANO120LC2BN" , 0x00112043, NUMICRO_BANKS_NANO(32*1024)},
962         {"NANO130KE3BN" , 0x00113030, NUMICRO_BANKS_NANO(123*1024)},
963         {"NANO130KE2BN" , 0x00113031, NUMICRO_BANKS_NANO(123*1024)},
964         {"NANO130VE3BN" , 0x00113032, NUMICRO_BANKS_NANO(123*1024)},
965         {"NANO130VE2BN" , 0x00113033, NUMICRO_BANKS_NANO(123*1024)},
966         {"NANO130SE3BN" , 0x00113034, NUMICRO_BANKS_NANO(123*1024)},
967         {"NANO130SE2BN" , 0x00113035, NUMICRO_BANKS_NANO(123*1024)},
968         {"NANO130KD3BN" , 0x00113038, NUMICRO_BANKS_NANO(64*1024)},
969         {"NANO130KD2BN" , 0x00113039, NUMICRO_BANKS_NANO(64*1024)},
970         {"NANO130VD3BN" , 0x0011303A, NUMICRO_BANKS_NANO(64*1024)},
971         {"NANO130VD2BN" , 0x0011303B, NUMICRO_BANKS_NANO(64*1024)},
972         {"NANO130SD3BN" , 0x0011303C, NUMICRO_BANKS_NANO(64*1024)},
973         {"NANO130SD2BN" , 0x0011303D, NUMICRO_BANKS_NANO(64*1024)},
974         {"NANO130KC2BN" , 0x00113040, NUMICRO_BANKS_NANO(32*1024)},
975         {"NANO130VC2BN" , 0x00113041, NUMICRO_BANKS_NANO(32*1024)},
976         {"NANO130SC2BN" , 0x00113042, NUMICRO_BANKS_NANO(32*1024)},
977         {"N512DC4"      , 0x00100000, NUMICRO_BANKS_NANO(64*1024)},
978         {"N512LC4"      , 0x00100001, NUMICRO_BANKS_NANO(64*1024)},
979         {"N512MC4"      , 0x00100003, NUMICRO_BANKS_NANO(64*1024)},
980
981         {"N512SC4"      , 0x00100005, NUMICRO_BANKS_NANO(64*1024)},
982         {"N512VD4"      , 0x00100008, NUMICRO_BANKS_NANO(128*1024)},
983         {"N512MD4"      , 0x00100009, NUMICRO_BANKS_NANO(128*1024)},
984         {"N512SD4"      , 0x00100010, NUMICRO_BANKS_NANO(128*1024)},
985         {"NANO110RC2BN" , 0x00111043, NUMICRO_BANKS_NANO(32*1024)},
986         {"NANO110RD3BN" , 0x00111045, NUMICRO_BANKS_NANO(64*1024)},
987         {"TX110VE3BN"   , 0x00111036, NUMICRO_BANKS_NANO(128*1024)},
988
989         /* NANO102/NANO112 */
990         {"NANO112LB0AN" , 0x00111201, NUMICRO_BANKS_NANO(16*1024)},
991         {"NANO112LB1AN" , 0x00111202, NUMICRO_BANKS_NANO(16*1024)},
992         {"NANO112LC1AN" , 0x00111203, NUMICRO_BANKS_NANO(32*1024)},
993         {"NANO112LC2AN" , 0x00111204, NUMICRO_BANKS_NANO(32*1024)},
994         {"NANO112SB0AN" , 0x00111205, NUMICRO_BANKS_NANO(16*1024)},
995         {"NANO112SB1AN" , 0x00111206, NUMICRO_BANKS_NANO(16*1024)},
996         {"NANO112SC1AN" , 0x00111207, NUMICRO_BANKS_NANO(32*1024)},
997         {"NANO112SC2AN" , 0x00111208, NUMICRO_BANKS_NANO(32*1024)},
998         {"NANO112RB0AN" , 0x00111209, NUMICRO_BANKS_NANO(16*1024)},
999         {"NANO112RB1AN" , 0x00111210, NUMICRO_BANKS_NANO(16*1024)},
1000         {"NANO112RC1AN" , 0x00111211, NUMICRO_BANKS_NANO(32*1024)},
1001         {"NANO112RC2AN" , 0x00111212, NUMICRO_BANKS_NANO(32*1024)},
1002         {"NANO112VB0AN" , 0x00111213, NUMICRO_BANKS_NANO(16*1024)},
1003         {"NANO112VB1AN" , 0x00111214, NUMICRO_BANKS_NANO(16*1024)},
1004         {"NANO112VC1AN" , 0x00111215, NUMICRO_BANKS_NANO(32*1024)},
1005         {"NANO112VC2AN" , 0x00111216, NUMICRO_BANKS_NANO(32*1024)},
1006         {"NANO102ZB0AN" , 0x00110201, NUMICRO_BANKS_NANO(16*1024)},
1007         {"NANO102ZB1AN" , 0x00110202, NUMICRO_BANKS_NANO(16*1024)},
1008         {"NANO102ZC1AN" , 0x00110203, NUMICRO_BANKS_NANO(32*1024)},
1009         {"NANO102ZC2AN" , 0x00110204, NUMICRO_BANKS_NANO(32*1024)},
1010         {"NANO102LB0AN" , 0x00110205, NUMICRO_BANKS_NANO(16*1024)},
1011         {"NANO102LB1AN" , 0x00110206, NUMICRO_BANKS_NANO(16*1024)},
1012         {"NANO102LC1AN" , 0x00110207, NUMICRO_BANKS_NANO(32*1024)},
1013         {"NANO102LC2AN" , 0x00110208, NUMICRO_BANKS_NANO(32*1024)},
1014         {"NANO102SB0AN" , 0x00110209, NUMICRO_BANKS_NANO(16*1024)},
1015         {"NANO102SB1AN" , 0x00110210, NUMICRO_BANKS_NANO(16*1024)},
1016         {"NANO102SC1AN" , 0x00110211, NUMICRO_BANKS_NANO(32*1024)},
1017         {"NANO102SC2AN" , 0x00110212, NUMICRO_BANKS_NANO(32*1024)},
1018
1019         /* NUC103/NUC105/NUC123 */
1020         {"NUC123SC2AN" , 0x00012305, NUMICRO_BANKS_NUC100(36*1024)},
1021         {"NUC123SD4AN" , 0x00012315, NUMICRO_BANKS_NUC100(68*1024)},
1022         {"NUC123LC2AN" , 0x00012325, NUMICRO_BANKS_NUC100(36*1024)},
1023         {"NUC103LC2AN" , 0x00010325, NUMICRO_BANKS_NUC100(36*1024)},
1024         {"NUC105LC2AN" , 0x00010525, NUMICRO_BANKS_NUC100(36*1024)},
1025         {"NUC123LD4AN" , 0x00012335, NUMICRO_BANKS_NUC100(68*1024)},
1026         {"NUC103LD4AN" , 0x00010335, NUMICRO_BANKS_NUC100(68*1024)},
1027         {"NUC105LD4AN" , 0x00010535, NUMICRO_BANKS_NUC100(68*1024)},
1028         {"NUC123ZC2AN" , 0x00012345, NUMICRO_BANKS_NUC100(36*1024)},
1029         {"NUC103ZC2AN" , 0x00010345, NUMICRO_BANKS_NUC100(36*1024)},
1030         {"NUC105ZC2AN" , 0x00010545, NUMICRO_BANKS_NUC100(36*1024)},
1031         {"NUC123ZD4AN" , 0x00012355, NUMICRO_BANKS_NUC100(68*1024)},
1032         {"NUC103ZD4AN" , 0x00010355, NUMICRO_BANKS_NUC100(68*1024)},
1033         {"NUC105ZD4AN" , 0x00010555, NUMICRO_BANKS_NUC100(68*1024)},
1034
1035         /* NUC200 */
1036         {"NUC200LC2AN" , 0x00020007, NUMICRO_BANKS_NUC100(32*1024)},
1037         {"NUC200LD2AN" , 0x00020004, NUMICRO_BANKS_NUC100(64*1024)},
1038         {"NUC200LE3AN" , 0x00020000, NUMICRO_BANKS_NUC100(128*1024)},
1039         {"NUC200SC1AN" , 0x00020035, NUMICRO_BANKS_NUC100(32*1024)},
1040         {"NUC200SD2AN" , 0x00020031, NUMICRO_BANKS_NUC100(64*1024)},
1041         {"NUC200SE3AN" , 0x00020027, NUMICRO_BANKS_NUC100(128*1024)},
1042         {"NUC200VE3AN" , 0x00020018, NUMICRO_BANKS_NUC100(128*1024)},
1043         {"NUC220LC2AN" , 0x00022007, NUMICRO_BANKS_NUC100(32*1024)},
1044         {"NUC220LD2AN" , 0x00022004, NUMICRO_BANKS_NUC100(64*1024)},
1045         {"NUC220LE3AN" , 0x00022000, NUMICRO_BANKS_NUC100(128*1024)},
1046         {"NUC220SC1AN" , 0x00022035, NUMICRO_BANKS_NUC100(32*1024)},
1047         {"NUC220SD2AN" , 0x00022031, NUMICRO_BANKS_NUC100(64*1024)},
1048         {"NUC220SE3AN" , 0x00022027, NUMICRO_BANKS_NUC100(128*1024)},
1049         {"NUC220VE3AN" , 0x00022018, NUMICRO_BANKS_NUC100(128*1024)},
1050         {"NUC230LC2AN" , 0x00023007, NUMICRO_BANKS_NUC100(32*1024)},
1051         {"NUC230LD2AN" , 0x00023004, NUMICRO_BANKS_NUC100(64*1024)},
1052         {"NUC230LE3AN" , 0x00023000, NUMICRO_BANKS_NUC100(128*1024)},
1053         {"NUC230SC1AN" , 0x00023035, NUMICRO_BANKS_NUC100(32*1024)},
1054         {"NUC230SD2AN" , 0x00023031, NUMICRO_BANKS_NUC100(64*1024)},
1055         {"NUC230SE3AN" , 0x00023027, NUMICRO_BANKS_NUC100(128*1024)},
1056         {"NUC230VE3AN" , 0x00023018, NUMICRO_BANKS_NUC100(128*1024)},
1057         {"NUC240LC2AN" , 0x00024007, NUMICRO_BANKS_NUC100(32*1024)},
1058         {"NUC240LD2AN" , 0x00024004, NUMICRO_BANKS_NUC100(64*1024)},
1059         {"NUC240LE3AN" , 0x00024000, NUMICRO_BANKS_NUC100(128*1024)},
1060         {"NUC240SC1AN" , 0x00024035, NUMICRO_BANKS_NUC100(32*1024)},
1061         {"NUC240SD2AN" , 0x00024031, NUMICRO_BANKS_NUC100(64*1024)},
1062         {"NUC240SE3AN" , 0x00024027, NUMICRO_BANKS_NUC100(128*1024)},
1063         {"NUC240VE3AN" , 0x00024018, NUMICRO_BANKS_NUC100(128*1024)},
1064
1065         /* NUC200 NUC2XXAE */
1066         {"NUC230RC1AE" , 0x40013017, NUMICRO_BANKS_NUC100(32*1024)},
1067         {"NUC200LC2AE" , 0x10020007, NUMICRO_BANKS_NUC100(32*1024)},
1068         {"NUC200LD2AE" , 0x10020004, NUMICRO_BANKS_NUC100(64*1024)},
1069         {"NUC200LE3AE" , 0x10020000, NUMICRO_BANKS_NUC100(128*1024)},
1070         {"NUC200SC2AE" , 0x10020034, NUMICRO_BANKS_NUC100(32*1024)},
1071         {"NUC200SD2AE" , 0x10020031, NUMICRO_BANKS_NUC100(64*1024)},
1072         {"NUC200SE3AE" , 0x10020027, NUMICRO_BANKS_NUC100(128*1024)},
1073         {"NUC200VE3AE" , 0x10020018, NUMICRO_BANKS_NUC100(128*1024)},
1074         {"NUC230LC2AE" , 0x10023007, NUMICRO_BANKS_NUC100(32*1024)},
1075         {"NUC230LD2AE" , 0x10023004, NUMICRO_BANKS_NUC100(64*1024)},
1076         {"NUC230LE3AE" , 0x10023000, NUMICRO_BANKS_NUC100(128*1024)},
1077         {"NUC230SC2AE" , 0x10023034, NUMICRO_BANKS_NUC100(32*1024)},
1078         {"NUC230SD2AE" , 0x10023031, NUMICRO_BANKS_NUC100(64*1024)},
1079         {"NUC230SE3AE" , 0x10023027, NUMICRO_BANKS_NUC100(128*1024)},
1080         {"NUC230VE3AE" , 0x10023018, NUMICRO_BANKS_NUC100(128*1024)},
1081         {"NUC240LC2AE" , 0x10024007, NUMICRO_BANKS_NUC100(32*1024)},
1082         {"NUC240LD2AE" , 0x10024004, NUMICRO_BANKS_NUC100(64*1024)},
1083         {"NUC240LE3AE" , 0x10024000, NUMICRO_BANKS_NUC100(128*1024)},
1084         {"NUC240SC2AE" , 0x10024034, NUMICRO_BANKS_NUC100(32*1024)},
1085         {"NUC240SD2AE" , 0x10024031, NUMICRO_BANKS_NUC100(64*1024)},
1086         {"NUC240SE3AE" , 0x10024027, NUMICRO_BANKS_NUC100(128*1024)},
1087         {"NUC240VE3AE" , 0x10024018, NUMICRO_BANKS_NUC100(128*1024)},
1088
1089         /* NUC100 Version D */
1090         {"NUC100LC1DN" , 0x30010008, NUMICRO_BANKS_NUC100(32*1024)},
1091         {"NUC100LD1DN" , 0x30010005, NUMICRO_BANKS_NUC100(64*1024)},
1092         {"NUC100LD2DN" , 0x30010004, NUMICRO_BANKS_NUC100(64*1024)},
1093         {"NUC100RC1DN" , 0x30010017, NUMICRO_BANKS_NUC100(32*1024)},
1094         {"NUC100RD1DN" , 0x30010014, NUMICRO_BANKS_NUC100(64*1024)},
1095         {"NUC100RD2DN" , 0x30010013, NUMICRO_BANKS_NUC100(64*1024)},
1096         {"NUC100LD3DN" , 0x30010003, NUMICRO_BANKS_NUC100(64*1024)},
1097         {"NUC100LE3DN" , 0x30010000, NUMICRO_BANKS_NUC100(128*1024)},
1098         {"NUC100RD3DN" , 0x30010012, NUMICRO_BANKS_NUC100(64*1024)},
1099         {"NUC100RE3DN" , 0x30010009, NUMICRO_BANKS_NUC100(128*1024)},
1100         {"NUC100VD2DN" , 0x30010022, NUMICRO_BANKS_NUC100(64*1024)},
1101         {"NUC100VD3DN" , 0x30010021, NUMICRO_BANKS_NUC100(64*1024)},
1102         {"NUC100VE3DN" , 0x30010018, NUMICRO_BANKS_NUC100(128*1024)},
1103         {"NUC120LC1DN" , 0x30012008, NUMICRO_BANKS_NUC100(32*1024)},
1104         {"NUC120LD1DN" , 0x30012005, NUMICRO_BANKS_NUC100(64*1024)},
1105         {"NUC120LD2DN" , 0x30012004, NUMICRO_BANKS_NUC100(64*1024)},
1106         {"NUC120RC1DN" , 0x30012017, NUMICRO_BANKS_NUC100(32*1024)},
1107         {"NUC120RD1DN" , 0x30012014, NUMICRO_BANKS_NUC100(64*1024)},
1108         {"NUC120RD2DN" , 0x30012013, NUMICRO_BANKS_NUC100(64*1024)},
1109         {"NUC120LD3DN" , 0x30012003, NUMICRO_BANKS_NUC100(64*1024)},
1110         {"NUC120LE3DN" , 0x30012000, NUMICRO_BANKS_NUC100(128*1024)},
1111         {"NUC120RD3DN" , 0x30012012, NUMICRO_BANKS_NUC100(64*1024)},
1112         {"NUC120RE3DN" , 0x30012009, NUMICRO_BANKS_NUC100(128*1024)},
1113         {"NUC120VD2DN" , 0x30012022, NUMICRO_BANKS_NUC100(64*1024)},
1114         {"NUC120VD3DN" , 0x30012021, NUMICRO_BANKS_NUC100(64*1024)},
1115         {"NUC120VE3DN" , 0x30012018, NUMICRO_BANKS_NUC100(128*1024)},
1116         {"NUC130RC1DN" , 0x30013017, NUMICRO_BANKS_NUC100(32*1024)},
1117
1118         {"UNKNOWN"     , 0x00000000, NUMICRO_BANKS_NUC100(128*1024)},
1119 };
1120
1121 /* Private bank information for NuMicro. */
1122 struct  numicro_flash_bank {
1123         struct working_area *write_algorithm;
1124         bool probed;
1125         const struct numicro_cpu_type *cpu;
1126 };
1127
1128 /* Private methods */
1129 static int numicro_reg_unlock(struct target *target)
1130 {
1131         uint32_t is_protected;
1132         int retval = ERROR_OK;
1133
1134         /* Check to see if NUC is register unlocked or not */
1135         retval = target_read_u32(target, NUMICRO_SYS_WRPROT, &is_protected);
1136         if (retval != ERROR_OK)
1137                 return retval;
1138
1139         LOG_DEBUG("protected = 0x%08" PRIx32 "", is_protected);
1140         if (is_protected == 0) {        /* means protected - so unlock it */
1141                 /* unlock flash registers */
1142                 retval = target_write_u32(target, NUMICRO_SYS_WRPROT, REG_KEY1);
1143                 if (retval != ERROR_OK)
1144                         return retval;
1145                 retval = target_write_u32(target, NUMICRO_SYS_WRPROT, REG_KEY2);
1146                 if (retval != ERROR_OK)
1147                         return retval;
1148                 retval = target_write_u32(target, NUMICRO_SYS_WRPROT, REG_KEY3);
1149                 if (retval != ERROR_OK)
1150                         return retval;
1151         }
1152         /* Check that unlock worked */
1153         retval = target_read_u32(target, NUMICRO_SYS_WRPROT, &is_protected);
1154         if (retval != ERROR_OK)
1155                 return retval;
1156
1157         if (is_protected == 1) {        /* means unprotected */
1158                 LOG_DEBUG("protection removed");
1159         } else {
1160                 LOG_DEBUG("still protected!!");
1161         }
1162
1163         return ERROR_OK;
1164 }
1165
1166 static int numicro_init_isp(struct target *target)
1167 {
1168         uint32_t reg_stat;
1169         int retval = ERROR_OK;
1170
1171         if (target->state != TARGET_HALTED) {
1172                 LOG_ERROR("Target not halted");
1173                 return ERROR_TARGET_NOT_HALTED;
1174         }
1175
1176         retval = numicro_reg_unlock(target);
1177         if (retval != ERROR_OK)
1178                 return retval;
1179
1180         /* Enable ISP/SRAM/TICK Clock */
1181         retval = target_read_u32(target, NUMICRO_SYSCLK_AHBCLK, &reg_stat);
1182         if (retval != ERROR_OK)
1183                 return retval;
1184
1185         reg_stat |= AHBCLK_ISP_EN | AHBCLK_SRAM_EN | AHBCLK_TICK_EN;
1186         retval = target_write_u32(target, NUMICRO_SYSCLK_AHBCLK, reg_stat);
1187         if (retval != ERROR_OK)
1188                 return retval;
1189
1190         /* Enable ISP */
1191         retval = target_read_u32(target, NUMICRO_FLASH_ISPCON, &reg_stat);
1192         if (retval != ERROR_OK)
1193                 return retval;
1194
1195         reg_stat |= ISPCON_ISPFF | ISPCON_LDUEN | ISPCON_APUEN | ISPCON_CFGUEN | ISPCON_ISPEN;
1196         retval = target_write_u32(target, NUMICRO_FLASH_ISPCON, reg_stat);
1197         if (retval != ERROR_OK)
1198                 return retval;
1199
1200         /* Write one to undocumented flash control register */
1201         retval = target_write_u32(target, NUMICRO_FLASH_CHEAT, 1);
1202         if (retval != ERROR_OK)
1203                 return retval;
1204
1205         return ERROR_OK;
1206 }
1207
1208 static uint32_t numicro_fmc_cmd(struct target *target, uint32_t cmd, uint32_t addr, uint32_t wdata, uint32_t *rdata)
1209 {
1210         uint32_t timeout, status;
1211         int retval = ERROR_OK;
1212
1213         retval = target_write_u32(target, NUMICRO_FLASH_ISPCMD, cmd);
1214         if (retval != ERROR_OK)
1215                 return retval;
1216
1217         retval = target_write_u32(target, NUMICRO_FLASH_ISPDAT, wdata);
1218         if (retval != ERROR_OK)
1219                 return retval;
1220
1221         retval = target_write_u32(target, NUMICRO_FLASH_ISPADR, addr);
1222         if (retval != ERROR_OK)
1223                 return retval;
1224
1225         retval = target_write_u32(target, NUMICRO_FLASH_ISPTRG, ISPTRG_ISPGO);
1226         if (retval != ERROR_OK)
1227                 return retval;
1228
1229         /* Wait for busy to clear - check the GO flag */
1230         timeout = 100;
1231         for (;;) {
1232                 retval = target_read_u32(target, NUMICRO_FLASH_ISPTRG, &status);
1233                 if (retval != ERROR_OK)
1234                         return retval;
1235                 LOG_DEBUG("status: 0x%" PRIx32 "", status);
1236                 if ((status & (ISPTRG_ISPGO)) == 0)
1237                         break;
1238                 if (timeout-- <= 0) {
1239                         LOG_DEBUG("timed out waiting for flash");
1240                         return ERROR_FAIL;
1241                 }
1242                 busy_sleep(1);  /* can use busy sleep for short times. */
1243         }
1244
1245         retval = target_read_u32(target, NUMICRO_FLASH_ISPDAT, rdata);
1246         if (retval != ERROR_OK)
1247                 return retval;
1248
1249         return ERROR_OK;
1250 }
1251
1252
1253 /* NuMicro Program-LongWord Microcodes */
1254 static const uint8_t numicro_flash_write_code[] = {
1255                                 /* Params:
1256                                  * r0 - workarea buffer / result
1257                                  * r1 - target address
1258                                  * r2 - wordcount
1259                                  * Clobbered:
1260                                  * r4 - tmp
1261                                  * r5 - tmp
1262                                  * r6 - tmp
1263                                  * r7 - tmp
1264                                  */
1265
1266                                 /* .L1: */
1267                                                 /* for(register uint32_t i=0;i<wcount;i++){ */
1268         0x04, 0x1C,                             /* mov    r4, r0          */
1269         0x00, 0x23,                             /* mov    r3, #0          */
1270                                 /* .L2: */
1271         0x0D, 0x1A,                             /* sub    r5, r1, r0      */
1272         0x67, 0x19,                             /* add    r7, r4, r7      */
1273         0x93, 0x42,                             /* cmp    r3, r2                  */
1274         0x0C, 0xD0,                             /* beq    .L7             */
1275                                 /* .L4: */
1276                                                 /* NUMICRO_FLASH_ISPADR = faddr; */
1277         0x08, 0x4E,                             /* ldr  r6, .L8           */
1278         0x37, 0x60,                             /* str  r7, [r6]          */
1279                                                 /* NUMICRO_FLASH_ISPDAT = *pLW; */
1280         0x80, 0xCC,                             /* ldmia        r4!, {r7}     */
1281         0x08, 0x4D,                             /* ldr  r5, .L8+4         */
1282         0x2F, 0x60,                             /* str  r7, [r5]                  */
1283                                                         /* faddr += 4; */
1284                                                         /* pLW++; */
1285                                                         /*  Trigger write action  */
1286                                                 /* NUMICRO_FLASH_ISPTRG = ISPTRG_ISPGO; */
1287         0x08, 0x4D,                             /* ldr  r5, .L8+8         */
1288         0x01, 0x26,                             /* mov  r6, #1            */
1289         0x2E, 0x60,                             /* str  r6, [r5]          */
1290                                 /* .L3: */
1291                                                 /* while((NUMICRO_FLASH_ISPTRG & ISPTRG_ISPGO) == ISPTRG_ISPGO){}; */
1292         0x2F, 0x68,                             /* ldr  r7, [r5]          */
1293         0xFF, 0x07,                             /* lsl  r7, r7, #31       */
1294         0xFC, 0xD4,                             /* bmi  .L3               */
1295
1296         0x01, 0x33,                             /* add  r3, r3, #1        */
1297         0xEE, 0xE7,                             /* b    .L2               */
1298                                 /* .L7: */
1299                                                 /* return (NUMICRO_FLASH_ISPCON & ISPCON_ISPFF); */
1300         0x05, 0x4B,                             /* ldr  r3, .L8+12        */
1301         0x18, 0x68,                             /* ldr  r0, [r3]          */
1302         0x40, 0x21,                             /* mov  r1, #64           */
1303         0x08, 0x40,                             /* and  r0, r1            */
1304                                 /* .L9: */
1305         0x00, 0xBE,                             /* bkpt    #0             */
1306                                 /* .L8: */
1307         0x04, 0xC0, 0x00, 0x50,/* .word 1342226436    */
1308         0x08, 0xC0, 0x00, 0x50,/* .word 1342226440    */
1309         0x10, 0xC0, 0x00, 0x50,/* .word 1342226448    */
1310         0x00, 0xC0, 0x00, 0x50 /* .word 1342226432    */
1311 };
1312 /* Program LongWord Block Write */
1313 static int numicro_writeblock(struct flash_bank *bank, const uint8_t *buffer,
1314                 uint32_t offset, uint32_t count)
1315 {
1316         struct target *target = bank->target;
1317         uint32_t buffer_size = 1024;            /* Default minimum value */
1318         struct working_area *write_algorithm;
1319         struct working_area *source;
1320         uint32_t address = bank->base + offset;
1321         struct reg_param reg_params[3];
1322         struct armv7m_algorithm armv7m_info;
1323         int retval = ERROR_OK;
1324
1325         /* Params:
1326          * r0 - workarea buffer / result
1327          * r1 - target address
1328          * r2 - wordcount
1329          * Clobbered:
1330          * r4 - tmp
1331          * r5 - tmp
1332          * r6 - tmp
1333          * r7 - tmp
1334          */
1335
1336         /* Increase buffer_size if needed */
1337         if (buffer_size < (target->working_area_size/2))
1338                 buffer_size = (target->working_area_size/2);
1339
1340         /* check code alignment */
1341         if (offset & 0x1) {
1342                 LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
1343                 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
1344         }
1345
1346         /* allocate working area with flash programming code */
1347         if (target_alloc_working_area(target, sizeof(numicro_flash_write_code),
1348                         &write_algorithm) != ERROR_OK) {
1349                 LOG_WARNING("no working area available, can't do block memory writes");
1350                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1351         }
1352
1353         retval = target_write_buffer(target, write_algorithm->address,
1354                 sizeof(numicro_flash_write_code), numicro_flash_write_code);
1355         if (retval != ERROR_OK)
1356                 return retval;
1357
1358         /* memory buffer */
1359         while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK) {
1360                 buffer_size /= 4;
1361                 if (buffer_size <= 256) {
1362                         /* free working area, write algorithm already allocated */
1363                         target_free_working_area(target, write_algorithm);
1364
1365                         LOG_WARNING("No large enough working area available, can't do block memory writes");
1366                         return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1367                 }
1368         }
1369
1370         armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
1371         armv7m_info.core_mode = ARM_MODE_THREAD;
1372
1373         init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* *pLW (*buffer) */
1374         init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);    /* faddr */
1375         init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);    /* number of words to program */
1376
1377         /* write code buffer and use Flash programming code within NuMicro     */
1378         /* Set breakpoint to 0 with time-out of 1000 ms                        */
1379         while (count > 0) {
1380                 uint32_t thisrun_count = (count > (buffer_size / 4)) ? (buffer_size / 4) : count;
1381
1382                 retval = target_write_buffer(target, source->address, thisrun_count * 4, buffer);
1383                 if (retval != ERROR_OK)
1384                         break;
1385
1386                 buf_set_u32(reg_params[0].value, 0, 32, source->address);
1387                 buf_set_u32(reg_params[1].value, 0, 32, address);
1388                 buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
1389
1390                 retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
1391                                 write_algorithm->address, 0, 100000, &armv7m_info);
1392                 if (retval != ERROR_OK) {
1393                         LOG_ERROR("Error executing NuMicro Flash programming algorithm");
1394                         retval = ERROR_FLASH_OPERATION_FAILED;
1395                         break;
1396                 }
1397
1398                 buffer  += thisrun_count * 4;
1399                 address += thisrun_count * 4;
1400                 count   -= thisrun_count;
1401         }
1402
1403         target_free_working_area(target, source);
1404         target_free_working_area(target, write_algorithm);
1405
1406         destroy_reg_param(&reg_params[0]);
1407         destroy_reg_param(&reg_params[1]);
1408         destroy_reg_param(&reg_params[2]);
1409
1410         return retval;
1411 }
1412
1413 /* Flash Lock checking - examines the lock bit. */
1414 static int numicro_protect_check(struct flash_bank *bank)
1415 {
1416         struct target *target = bank->target;
1417         uint32_t set, config[2];
1418         int retval = ERROR_OK;
1419
1420         if (target->state != TARGET_HALTED) {
1421                 LOG_ERROR("Target not halted");
1422                 return ERROR_TARGET_NOT_HALTED;
1423         }
1424
1425         LOG_INFO("Nuvoton NuMicro: Flash Lock Check...");
1426
1427         retval = numicro_init_isp(target);
1428         if (retval != ERROR_OK)
1429                 return retval;
1430
1431         /* Read CONFIG0,CONFIG1 */
1432         numicro_fmc_cmd(target, ISPCMD_READ, NUMICRO_CONFIG0, 0 , &config[0]);
1433         numicro_fmc_cmd(target, ISPCMD_READ, NUMICRO_CONFIG1, 0 , &config[1]);
1434
1435         LOG_DEBUG("CONFIG0: 0x%" PRIx32 ",CONFIG1: 0x%" PRIx32 "", config[0], config[1]);
1436
1437         if ((config[0] & (1<<7)) == 0)
1438                 LOG_INFO("CBS=0: Boot From LPROM");
1439         else
1440                 LOG_INFO("CBS=1: Boot From APROM");
1441
1442         if ((config[0] & CONFIG0_LOCK_MASK) == 0) {
1443
1444                 LOG_INFO("Flash is secure locked!");
1445                 LOG_INFO("TO UNLOCK FLASH,EXECUTE chip_erase COMMAND!!");
1446                 set = 1;
1447         } else {
1448                 LOG_INFO("Flash is not locked!");
1449             set = 0;
1450         }
1451
1452         for (unsigned int i = 0; i < bank->num_sectors; i++)
1453                 bank->sectors[i].is_protected = set;
1454
1455         return ERROR_OK;
1456 }
1457
1458
1459 static int numicro_erase(struct flash_bank *bank, unsigned int first,
1460                 unsigned int last)
1461 {
1462         struct target *target = bank->target;
1463         uint32_t timeout, status;
1464         int retval = ERROR_OK;
1465
1466         if (target->state != TARGET_HALTED) {
1467                 LOG_ERROR("Target not halted");
1468                 return ERROR_TARGET_NOT_HALTED;
1469         }
1470
1471         LOG_INFO("Nuvoton NuMicro: Sector Erase ... (%u to %u)", first, last);
1472
1473         retval = numicro_init_isp(target);
1474         if (retval != ERROR_OK)
1475                 return retval;
1476
1477         retval = target_write_u32(target, NUMICRO_FLASH_ISPCMD, ISPCMD_ERASE);
1478         if (retval != ERROR_OK)
1479                 return retval;
1480
1481         for (unsigned int i = first; i <= last; i++) {
1482                 LOG_DEBUG("erasing sector %u at address " TARGET_ADDR_FMT, i,
1483                                 bank->base + bank->sectors[i].offset);
1484                 retval = target_write_u32(target, NUMICRO_FLASH_ISPADR, bank->base + bank->sectors[i].offset);
1485                 if (retval != ERROR_OK)
1486                         return retval;
1487                 retval = target_write_u32(target, NUMICRO_FLASH_ISPTRG, ISPTRG_ISPGO); /* This is the only bit available */
1488                 if (retval != ERROR_OK)
1489                         return retval;
1490
1491                 /* wait for busy to clear - check the GO flag */
1492                 timeout = 100;
1493                 for (;;) {
1494                         retval = target_read_u32(target, NUMICRO_FLASH_ISPTRG, &status);
1495                         if (retval != ERROR_OK)
1496                                 return retval;
1497                         LOG_DEBUG("status: 0x%" PRIx32 "", status);
1498                         if (status == 0)
1499                                 break;
1500                         if (timeout-- <= 0) {
1501                                 LOG_DEBUG("timed out waiting for flash");
1502                                 return ERROR_FAIL;
1503                         }
1504                         busy_sleep(1);  /* can use busy sleep for short times. */
1505                 }
1506
1507                 /* check for failure */
1508                 retval = target_read_u32(target, NUMICRO_FLASH_ISPCON, &status);
1509                 if (retval != ERROR_OK)
1510                         return retval;
1511                 if ((status & ISPCON_ISPFF) != 0) {
1512                         LOG_DEBUG("failure: 0x%" PRIx32 "", status);
1513                         /* if bit is set, then must write to it to clear it. */
1514                         retval = target_write_u32(target, NUMICRO_FLASH_ISPCON, (status | ISPCON_ISPFF));
1515                         if (retval != ERROR_OK)
1516                                 return retval;
1517                 }
1518         }
1519
1520         /* done, */
1521         LOG_DEBUG("Erase done.");
1522
1523         return ERROR_OK;
1524 }
1525
1526 /* The write routine stub. */
1527 static int numicro_write(struct flash_bank *bank, const uint8_t *buffer,
1528                 uint32_t offset, uint32_t count)
1529 {
1530         struct target *target = bank->target;
1531         uint32_t timeout, status;
1532         int retval = ERROR_OK;
1533
1534         if (target->state != TARGET_HALTED) {
1535                 LOG_ERROR("Target not halted");
1536                 return ERROR_TARGET_NOT_HALTED;
1537         }
1538
1539         LOG_INFO("Nuvoton NuMicro: Flash Write ...");
1540
1541         retval = numicro_init_isp(target);
1542         if (retval != ERROR_OK)
1543                 return retval;
1544
1545         retval = target_write_u32(target, NUMICRO_FLASH_ISPCMD, ISPCMD_WRITE);
1546         if (retval != ERROR_OK)
1547                 return retval;
1548
1549         assert(offset % 4 == 0);
1550         assert(count % 4 == 0);
1551
1552         uint32_t words_remaining = count / 4;
1553
1554         /* try using a block write */
1555         retval = numicro_writeblock(bank, buffer, offset, words_remaining);
1556
1557         if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
1558                 /* if block write failed (no sufficient working area),
1559                  * we use normal (slow) single word accesses */
1560                 LOG_WARNING("couldn't use block writes, falling back to single "
1561                         "memory accesses");
1562
1563                 /* program command */
1564                 for (uint32_t i = 0; i < count; i += 4) {
1565
1566                         LOG_DEBUG("write longword @ %08" PRIX32, offset + i);
1567
1568                         retval = target_write_u32(target, NUMICRO_FLASH_ISPADR, bank->base + offset + i);
1569                         if (retval != ERROR_OK)
1570                                 return retval;
1571                         retval = target_write_memory(target, NUMICRO_FLASH_ISPDAT, 4, 1, buffer + i);
1572                         if (retval != ERROR_OK)
1573                                 return retval;
1574                         retval = target_write_u32(target, NUMICRO_FLASH_ISPTRG, ISPTRG_ISPGO);
1575                         if (retval != ERROR_OK)
1576                                 return retval;
1577
1578                         /* wait for busy to clear - check the GO flag */
1579                         timeout = 100;
1580                         for (;;) {
1581                                 retval = target_read_u32(target, NUMICRO_FLASH_ISPTRG, &status);
1582                                 if (retval != ERROR_OK)
1583                                         return retval;
1584                                 LOG_DEBUG("status: 0x%" PRIx32 "", status);
1585                                 if (status == 0)
1586                                         break;
1587                                 if (timeout-- <= 0) {
1588                                         LOG_DEBUG("timed out waiting for flash");
1589                                         return ERROR_FAIL;
1590                                 }
1591                                 busy_sleep(1);  /* can use busy sleep for short times. */
1592                         }
1593
1594                 }
1595         }
1596
1597         /* check for failure */
1598         retval = target_read_u32(target, NUMICRO_FLASH_ISPCON, &status);
1599         if (retval != ERROR_OK)
1600                 return retval;
1601         if ((status & ISPCON_ISPFF) != 0) {
1602                 LOG_DEBUG("failure: 0x%" PRIx32 "", status);
1603                 /* if bit is set, then must write to it to clear it. */
1604                 retval = target_write_u32(target, NUMICRO_FLASH_ISPCON, (status | ISPCON_ISPFF));
1605                 if (retval != ERROR_OK)
1606                         return retval;
1607         } else {
1608                 LOG_DEBUG("Write OK");
1609         }
1610
1611         /* done. */
1612         LOG_DEBUG("Write done.");
1613
1614         return ERROR_OK;
1615 }
1616
1617 static int numicro_get_cpu_type(struct target *target, const struct numicro_cpu_type **cpu)
1618 {
1619         uint32_t part_id;
1620         int retval = ERROR_OK;
1621
1622         /* Read NuMicro PartID */
1623         retval = target_read_u32(target, NUMICRO_SYS_BASE, &part_id);
1624         if (retval != ERROR_OK) {
1625                 LOG_WARNING("NuMicro flash driver: Failed to Get PartID\n");
1626                 return ERROR_FLASH_OPERATION_FAILED;
1627         }
1628
1629         LOG_INFO("Device ID: 0x%08" PRIx32 "", part_id);
1630         /* search part numbers */
1631         for (size_t i = 0; i < ARRAY_SIZE(numicro_parts); i++) {
1632                 if (part_id == numicro_parts[i].partid) {
1633                         *cpu = &numicro_parts[i];
1634                         LOG_INFO("Device Name: %s", (*cpu)->partname);
1635                         return ERROR_OK;
1636                 }
1637         }
1638
1639         return ERROR_FAIL;
1640 }
1641
1642 static int numicro_get_flash_size(struct flash_bank *bank, const struct numicro_cpu_type *cpu, uint32_t *flash_size)
1643 {
1644         for (size_t i = 0; i < cpu->n_banks; i++) {
1645                 if (bank->base == cpu->bank[i].base) {
1646                         *flash_size = cpu->bank[i].size;
1647                         LOG_INFO("bank base = " TARGET_ADDR_FMT ", size = 0x%08"
1648                                         PRIx32, bank->base, *flash_size);
1649                         return ERROR_OK;
1650                 }
1651         }
1652         return ERROR_FLASH_OPERATION_FAILED;
1653 }
1654
1655 static int numicro_probe(struct flash_bank *bank)
1656 {
1657         uint32_t flash_size, offset = 0;
1658         int num_pages;
1659         const struct numicro_cpu_type *cpu;
1660         struct target *target = bank->target;
1661         int retval = ERROR_OK;
1662
1663         retval = numicro_get_cpu_type(target, &cpu);
1664         if (retval != ERROR_OK) {
1665                 LOG_WARNING("NuMicro flash driver: Failed to detect a known part\n");
1666                 return ERROR_FLASH_OPERATION_FAILED;
1667         }
1668
1669         retval = numicro_get_flash_size(bank, cpu, &flash_size);
1670         if (retval != ERROR_OK) {
1671                 LOG_WARNING("NuMicro flash driver: Failed to detect flash size\n");
1672                 return ERROR_FLASH_OPERATION_FAILED;
1673         }
1674
1675         num_pages = flash_size / NUMICRO_PAGESIZE;
1676
1677         bank->num_sectors = num_pages;
1678         bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
1679         bank->size = flash_size;
1680
1681         for (int i = 0; i < num_pages; i++) {
1682                 bank->sectors[i].offset = offset;
1683                 bank->sectors[i].size = NUMICRO_PAGESIZE;
1684                 bank->sectors[i].is_erased = -1;
1685                 bank->sectors[i].is_protected = 0;
1686                 offset += NUMICRO_PAGESIZE;
1687         }
1688
1689         struct numicro_flash_bank *numicro_info = bank->driver_priv;
1690         numicro_info->probed = true;
1691         numicro_info->cpu = cpu;
1692         LOG_DEBUG("Nuvoton NuMicro: Probed ...");
1693
1694         return ERROR_OK;
1695 }
1696
1697 /* Standard approach to autoprobing. */
1698 static int numicro_auto_probe(struct flash_bank *bank)
1699 {
1700         struct numicro_flash_bank *numicro_info = bank->driver_priv;
1701         if (numicro_info->probed)
1702                 return ERROR_OK;
1703         return numicro_probe(bank);
1704 }
1705
1706
1707 /* This is the function called in the config file. */
1708 FLASH_BANK_COMMAND_HANDLER(numicro_flash_bank_command)
1709 {
1710         struct numicro_flash_bank *bank_info;
1711
1712         if (CMD_ARGC < 6)
1713                 return ERROR_COMMAND_SYNTAX_ERROR;
1714
1715         LOG_DEBUG("add flash_bank numicro %s", bank->name);
1716
1717         bank_info = malloc(sizeof(struct numicro_flash_bank));
1718
1719         memset(bank_info, 0, sizeof(struct numicro_flash_bank));
1720
1721         bank->driver_priv = bank_info;
1722         bank->write_start_alignment = bank->write_end_alignment = 4;
1723
1724         return ERROR_OK;
1725
1726 }
1727
1728 COMMAND_HANDLER(numicro_handle_read_isp_command)
1729 {
1730         uint32_t address;
1731         uint32_t ispdat;
1732         int retval = ERROR_OK;
1733
1734         if (CMD_ARGC != 1)
1735                 return ERROR_COMMAND_SYNTAX_ERROR;
1736
1737         COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
1738
1739         struct target *target = get_current_target(CMD_CTX);
1740
1741         retval = numicro_init_isp(target);
1742         if (retval != ERROR_OK)
1743                 return retval;
1744
1745         retval = numicro_fmc_cmd(target, ISPCMD_READ, address, 0, &ispdat);
1746         if (retval != ERROR_OK)
1747                 return retval;
1748
1749         LOG_INFO("0x%08" PRIx32 ": 0x%08" PRIx32, address, ispdat);
1750
1751         return ERROR_OK;
1752 }
1753
1754 COMMAND_HANDLER(numicro_handle_write_isp_command)
1755 {
1756         uint32_t address;
1757         uint32_t ispdat, rdat;
1758         int retval = ERROR_OK;
1759
1760         if (CMD_ARGC != 2)
1761                 return ERROR_COMMAND_SYNTAX_ERROR;
1762
1763         COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
1764         COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], ispdat);
1765
1766         struct target *target = get_current_target(CMD_CTX);
1767
1768         retval = numicro_init_isp(target);
1769         if (retval != ERROR_OK)
1770                 return retval;
1771
1772         retval = numicro_fmc_cmd(target, ISPCMD_WRITE, address, ispdat, &rdat);
1773         if (retval != ERROR_OK)
1774                 return retval;
1775
1776         LOG_INFO("0x%08" PRIx32 ": 0x%08" PRIx32, address, ispdat);
1777         return ERROR_OK;
1778 }
1779
1780 COMMAND_HANDLER(numicro_handle_chip_erase_command)
1781 {
1782         int retval = ERROR_OK;
1783         uint32_t rdat;
1784
1785         if (CMD_ARGC != 0)
1786                 return ERROR_COMMAND_SYNTAX_ERROR;
1787
1788         struct target *target = get_current_target(CMD_CTX);
1789
1790         retval = numicro_init_isp(target);
1791         if (retval != ERROR_OK)
1792                 return retval;
1793
1794         retval = numicro_fmc_cmd(target, ISPCMD_CHIPERASE, 0, 0, &rdat);
1795         if (retval != ERROR_OK) {
1796                 command_print(CMD, "numicro chip_erase failed");
1797                 return retval;
1798         }
1799
1800         command_print(CMD, "numicro chip_erase complete");
1801
1802         return ERROR_OK;
1803 }
1804
1805 static const struct command_registration numicro_exec_command_handlers[] = {
1806         {
1807                 .name = "read_isp",
1808                 .handler = numicro_handle_read_isp_command,
1809                 .usage = "address",
1810                 .mode = COMMAND_EXEC,
1811                 .help = "read flash through ISP.",
1812         },
1813         {
1814                 .name = "write_isp",
1815                 .handler = numicro_handle_write_isp_command,
1816                 .usage = "address value",
1817                 .mode = COMMAND_EXEC,
1818                 .help = "write flash through ISP.",
1819         },
1820         {
1821                 .name = "chip_erase",
1822                 .handler = numicro_handle_chip_erase_command,
1823                 .mode = COMMAND_EXEC,
1824                 .help = "chip erase through ISP.",
1825                 .usage = "",
1826         },
1827         COMMAND_REGISTRATION_DONE
1828 };
1829
1830 static const struct command_registration numicro_command_handlers[] = {
1831         {
1832                 .name = "numicro",
1833                 .mode = COMMAND_ANY,
1834                 .help = "numicro flash command group",
1835                 .usage = "",
1836                 .chain = numicro_exec_command_handlers,
1837         },
1838         COMMAND_REGISTRATION_DONE
1839 };
1840
1841 const struct flash_driver numicro_flash = {
1842         .name = "numicro",
1843         .commands = numicro_command_handlers,
1844         .flash_bank_command = numicro_flash_bank_command,
1845         .erase = numicro_erase,
1846         .write = numicro_write,
1847         .read = default_flash_read,
1848         .probe = numicro_probe,
1849         .auto_probe = numicro_auto_probe,
1850         .erase_check = default_flash_blank_check,
1851         .protect_check = numicro_protect_check,
1852         .free_driver_priv = default_flash_free_driver_priv,
1853 };