jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / 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 * Copyright (C) 2017 Zale Yu *
17 * CYYU@nuvoton.com *
18 * *
19 * Copyright (C) 2022 Jian-Hong Pan *
20 * chienhung.pan@gmail.com *
21 ***************************************************************************/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include "imp.h"
28 #include <helper/binarybuffer.h>
29 #include <target/algorithm.h>
30 #include <target/armv7m.h>
31 #include <target/cortex_m.h>
32
33 /* Nuvoton NuMicro register locations */
34 #define NUMICRO_SYS_BASE 0x50000000
35 #define NUMICRO_SYS_WRPROT 0x50000100
36 #define NUMICRO_SYS_IPRSTC1 0x50000008
37
38 #define NUMICRO_SYSCLK_BASE 0x50000200
39 #define NUMICRO_SYSCLK_PWRCON 0x50000200
40 #define NUMICRO_SYSCLK_CLKSEL0 0x50000210
41 #define NUMICRO_SYSCLK_CLKDIV 0x50000218
42 #define NUMICRO_SYSCLK_AHBCLK 0x50000204
43
44 #define NUMICRO_FLASH_BASE 0x5000C000
45 #define NUMICRO_FLASH_ISPCON 0x5000C000
46 #define NUMICRO_FLASH_ISPADR 0x5000C004
47 #define NUMICRO_FLASH_ISPDAT 0x5000C008
48 #define NUMICRO_FLASH_ISPCMD 0x5000C00C
49 #define NUMICRO_FLASH_ISPTRG 0x5000C010
50 #define NUMICRO_FLASH_CHEAT 0x5000C01C /* Undocumented isp register(may be cheat register) */
51
52 #define NUMICRO_SCS_BASE 0xE000E000
53 #define NUMICRO_SCS_AIRCR 0xE000ED0C
54 #define NUMICRO_SCS_DHCSR 0xE000EDF0
55 #define NUMICRO_SCS_DEMCR 0xE000EDFC
56
57 #define NUMICRO_APROM_BASE 0x00000000
58 #define NUMICRO_DATA_BASE 0x0001F000
59 #define NUMICRO_LDROM_BASE 0x00100000
60 #define NUMICRO_CONFIG_BASE 0x00300000
61
62 #define NUMICRO_CONFIG0 0x5000C000
63 #define NUMICRO_CONFIG1 0x5000C004
64
65 /* Command register bits */
66 #define PWRCON_OSC22M (1 << 2)
67 #define PWRCON_XTL12M (1 << 0)
68
69 #define IPRSTC1_CPU_RST (1 << 1)
70 #define IPRSTC1_CHIP_RST (1 << 0)
71
72 #define AHBCLK_ISP_EN (1 << 2)
73 #define AHBCLK_SRAM_EN (1 << 4)
74 #define AHBCLK_TICK_EN (1 << 5)
75
76 #define ISPCON_ISPEN (1 << 0)
77 #define ISPCON_BS_AP (0 << 1)
78 #define ISPCON_BS_LP (1 << 1)
79 #define ISPCON_BS_MASK (1 << 1)
80 #define ISPCON_APUEN (1 << 3)
81 #define ISPCON_CFGUEN (1 << 4)
82 #define ISPCON_LDUEN (1 << 5)
83 #define ISPCON_ISPFF (1 << 6)
84
85 #define CONFIG0_LOCK_MASK (1 << 1)
86
87 /* isp commands */
88 #define ISPCMD_READ 0x00
89 #define ISPCMD_WRITE 0x21
90 #define ISPCMD_ERASE 0x22
91 #define ISPCMD_CHIPERASE 0x26 /* Undocumented isp "Chip-Erase" command */
92 #define ISPCMD_READ_CID 0x0B
93 #define ISPCMD_READ_DID 0x0C
94 #define ISPCMD_READ_UID 0x04
95 #define ISPCMD_VECMAP 0x2E
96 #define ISPTRG_ISPGO (1 << 0)
97
98 /* access unlock keys */
99 #define REG_KEY1 0x59
100 #define REG_KEY2 0x16
101 #define REG_KEY3 0x88
102 #define REG_LOCK 0x00
103
104 /* flash pagesizes */
105 #define NUMICRO_PAGESIZE 512
106 /* flash MAX banks */
107 #define NUMICRO_MAX_FLASH_BANKS 4
108
109 /* flash bank structs */
110 struct numicro_flash_bank_type {
111 uint32_t base;
112 uint32_t size;
113 };
114
115 /* part structs */
116 struct numicro_cpu_type {
117 char *partname;
118 uint32_t partid;
119 unsigned int n_banks;
120 struct numicro_flash_bank_type bank[NUMICRO_MAX_FLASH_BANKS];
121 };
122
123 /* If DataFlash size equals zero, it means the actual size depends on config settings. */
124 #define NUMICRO_BANKS_GENERAL(aprom_size, data_size, ldrom_size, config_size) \
125 .n_banks = 4, \
126 {{NUMICRO_APROM_BASE, (aprom_size)}, \
127 {NUMICRO_DATA_BASE, (data_size)}, \
128 {NUMICRO_LDROM_BASE, (ldrom_size)}, \
129 {NUMICRO_CONFIG_BASE, (config_size)}}
130
131 static const struct numicro_cpu_type numicro_parts[] = {
132 /*PART NO*/ /*PART ID*/ /*Banks*/
133 /* M051AN */
134 {"M052LAN", 0x00005200, NUMICRO_BANKS_GENERAL(8 * 1024, 4 * 1024, 4 * 1024, 4)},
135 {"M054LAN", 0x00005400, NUMICRO_BANKS_GENERAL(16 * 1024, 4 * 1024, 4 * 1024, 4)},
136 {"M058LAN", 0x00005800, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 4)},
137 {"M0516LAN", 0x00005A00, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 4)},
138 {"M052ZAN", 0x00005203, NUMICRO_BANKS_GENERAL(8 * 1024, 4 * 1024, 4 * 1024, 4)},
139 {"M054ZAN", 0x00005403, NUMICRO_BANKS_GENERAL(16 * 1024, 4 * 1024, 4 * 1024, 4)},
140 {"M058ZAN", 0x00005803, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 4)},
141 {"M0516ZAN", 0x00005A03, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 4)},
142
143 /* M051BN */
144 {"M052LBN", 0x10005200, NUMICRO_BANKS_GENERAL(8 * 1024, 4 * 1024, 4 * 1024, 4)},
145 {"M054LBN", 0x10005400, NUMICRO_BANKS_GENERAL(16 * 1024, 4 * 1024, 4 * 1024, 4)},
146 {"M058LBN", 0x10005800, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 4)},
147 {"M0516LBN", 0x10005A00, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 4)},
148 {"M052ZBN", 0x10005203, NUMICRO_BANKS_GENERAL(8 * 1024, 4 * 1024, 4 * 1024, 4)},
149 {"M054ZBN", 0x10005403, NUMICRO_BANKS_GENERAL(16 * 1024, 4 * 1024, 4 * 1024, 4)},
150 {"M058ZBN", 0x10005803, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 4)},
151 {"M0516ZBN", 0x10005A03, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 4)},
152
153 /* M051DN */
154 {"M0516LDN", 0x20005A00, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 4)},
155 {"M0516ZDN", 0x20005A03, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 4)},
156 {"M052LDN", 0x20005200, NUMICRO_BANKS_GENERAL(8 * 1024, 4 * 1024, 4 * 1024, 4)},
157 {"M052ZDN", 0x20005203, NUMICRO_BANKS_GENERAL(8 * 1024, 4 * 1024, 4 * 1024, 4)},
158 {"M054LDN", 0x20005400, NUMICRO_BANKS_GENERAL(16 * 1024, 4 * 1024, 4 * 1024, 4)},
159 {"M054ZDN", 0x20005403, NUMICRO_BANKS_GENERAL(16 * 1024, 4 * 1024, 4 * 1024, 4)},
160 {"M058LDN", 0x20005800, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 4)},
161 {"M058ZDN", 0x20005803, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 4)},
162
163 /* M051DE */
164 {"M0516LDE", 0x30005A00, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 4)},
165 {"M0516ZDE", 0x30005A03, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 4)},
166 {"M052LDE", 0x30005200, NUMICRO_BANKS_GENERAL(8 * 1024, 4 * 1024, 4 * 1024, 4)},
167 {"M052ZDE", 0x30005203, NUMICRO_BANKS_GENERAL(8 * 1024, 4 * 1024, 4 * 1024, 4)},
168 {"M054LDE", 0x30005400, NUMICRO_BANKS_GENERAL(16 * 1024, 4 * 1024, 4 * 1024, 4)},
169 {"M054ZDE", 0x30005403, NUMICRO_BANKS_GENERAL(16 * 1024, 4 * 1024, 4 * 1024, 4)},
170 {"M058LDE", 0x30005800, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 4)},
171 {"M058ZDE", 0x30005803, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 4)},
172
173 /* M0518 */
174 {"M0518LC2AE", 0x10051803, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
175 {"M0518LD2AE", 0x10051800, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
176 {"M0518SC2AE", 0x10051813, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
177 {"M0518SD2AE", 0x10051810, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
178
179 /* M0519 */
180 {"M0519LD3AE", 0x00051902, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 8 * 1024, 8)},
181 {"M0519LE3AE", 0x00051900, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 8 * 1024, 8)},
182 {"M0519SD3AE", 0x00051922, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 8 * 1024, 8)},
183 {"M0519SE3AE", 0x00051920, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 8 * 1024, 8)},
184 {"M0519VE3AE", 0x00051930, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 8 * 1024, 8)},
185
186 /* M058S */
187 {"M058SFAN", 0x00005818, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
188 {"M058SLAN", 0x00005810, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
189 {"M058SSAN", 0x00005816, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
190 {"M058SZAN", 0x00005813, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
191
192 /* MINI51AN */
193 {"MINI51LAN", 0x00205100, NUMICRO_BANKS_GENERAL(4 * 1024, 0 * 1024, 2 * 1024, 8)},
194 {"MINI51TAN", 0x00205104, NUMICRO_BANKS_GENERAL(4 * 1024, 0 * 1024, 2 * 1024, 8)},
195 {"MINI51ZAN", 0x00205103, NUMICRO_BANKS_GENERAL(4 * 1024, 0 * 1024, 2 * 1024, 8)},
196 {"MINI52LAN", 0x00205200, NUMICRO_BANKS_GENERAL(8 * 1024, 0 * 1024, 2 * 1024, 8)},
197 {"MINI52TAN", 0x00205204, NUMICRO_BANKS_GENERAL(8 * 1024, 0 * 1024, 2 * 1024, 8)},
198 {"MINI52ZAN", 0x00205203, NUMICRO_BANKS_GENERAL(8 * 1024, 0 * 1024, 2 * 1024, 8)},
199 {"MINI54LAN", 0x00205400, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 2 * 1024, 8)},
200 {"MINI54TAN", 0x00205404, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 2 * 1024, 8)},
201 {"MINI54ZAN", 0x00205403, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 2 * 1024, 8)},
202
203 /* MINI51DE */
204 {"MINI51FDE", 0x20205105, NUMICRO_BANKS_GENERAL(4 * 1024, 0 * 1024, 2 * 1024, 8)},
205 {"MINI51LDE", 0x20205100, NUMICRO_BANKS_GENERAL(4 * 1024, 0 * 1024, 2 * 1024, 8)},
206 {"MINI51TDE", 0x20205104, NUMICRO_BANKS_GENERAL(4 * 1024, 0 * 1024, 2 * 1024, 8)},
207 {"MINI51ZDE", 0x20205103, NUMICRO_BANKS_GENERAL(4 * 1024, 0 * 1024, 2 * 1024, 8)},
208 {"MINI52FDE", 0x20205205, NUMICRO_BANKS_GENERAL(8 * 1024, 0 * 1024, 2 * 1024, 8)},
209 {"MINI52LDE", 0x20205200, NUMICRO_BANKS_GENERAL(8 * 1024, 0 * 1024, 2 * 1024, 8)},
210 {"MINI52TDE", 0x20205204, NUMICRO_BANKS_GENERAL(8 * 1024, 0 * 1024, 2 * 1024, 8)},
211 {"MINI52ZDE", 0x20205203, NUMICRO_BANKS_GENERAL(8 * 1024, 0 * 1024, 2 * 1024, 8)},
212 {"MINI54FDE", 0x20205405, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 2 * 1024, 8)},
213 {"MINI54LDE", 0x20205400, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 2 * 1024, 8)},
214 {"MINI54TDE", 0x20205404, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 2 * 1024, 8)},
215 {"MINI54ZDE", 0x20205403, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 2 * 1024, 8)},
216
217 /* MINI55 */
218 {"MINI55LDE", 0x00505500, NUMICRO_BANKS_GENERAL(35 * 512, 0 * 1024, 2 * 1024, 8)},
219 {"MINI55ZDE", 0x00505503, NUMICRO_BANKS_GENERAL(35 * 512, 0 * 1024, 2 * 1024, 8)},
220
221 /* MINI58 */
222 {"MINI58FDE", 0x00A05805, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 5 * 512, 8)},
223 {"MINI58LDE", 0x00A05800, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 5 * 512, 8)},
224 {"MINI58TDE", 0x00A05804, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 5 * 512, 8)},
225 {"MINI58ZDE", 0x00A05803, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 5 * 512, 8)},
226
227 /* NANO100AN */
228 {"NANO100LC2AN", 0x00110025, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
229 {"NANO100LD2AN", 0x00110019, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
230 {"NANO100LD3AN", 0x00110018, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
231 {"NANO100SC2AN", 0x00110023, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
232 {"NANO100SD2AN", 0x00110016, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
233 {"NANO100SD3AN", 0x00110015, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
234 {"NANO100VD2AN", 0x00110013, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
235 {"NANO100VD3AN", 0x00110012, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
236 {"NANO100ZC2AN", 0x00110029, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
237 {"NANO100ZD2AN", 0x00110028, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
238 {"NANO100ZD3AN", 0x00110027, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
239 {"NANO120LC2AN", 0x00112025, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
240 {"NANO120LD2AN", 0x00112019, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
241 {"NANO120LD3AN", 0x00112018, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
242 {"NANO120SC2AN", 0x00112023, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
243 {"NANO120SD2AN", 0x00112016, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
244 {"NANO120SD3AN", 0x00112015, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
245 {"NANO120VD2AN", 0x00112013, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
246 {"NANO120VD3AN", 0x00112012, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
247 {"NANO120ZC2AN", 0x00112029, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
248 {"NANO120ZD2AN", 0x00112028, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
249 {"NANO120ZD3AN", 0x00112027, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
250
251 /* NANO100BN */
252 {"NANO100KC2BN", 0x00110040, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
253 {"NANO100KD2BN", 0x00110039, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
254 {"NANO100KD3BN", 0x00110038, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
255 {"NANO100KE3BN", 0x00110030, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
256 {"NANO100LC2BN", 0x00110043, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
257 {"NANO100LD2BN", 0x0011003F, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
258 {"NANO100LD3BN", 0x0011003E, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
259 {"NANO100LE3BN", 0x00110036, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
260 {"NANO100ND2BN", 0x00110046, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
261 {"NANO100ND3BN", 0x00110045, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
262 {"NANO100NE3BN", 0x00110044, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
263 {"NANO100SC2BN", 0x00110042, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
264 {"NANO100SD2BN", 0x0011003D, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
265 {"NANO100SD3BN", 0x0011003C, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
266 {"NANO100SE3BN", 0x00110034, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
267 {"NANO110KC2BN", 0x00111040, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
268 {"NANO110KD2BN", 0x00111039, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
269 {"NANO110KD3BN", 0x00111038, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
270 {"NANO110KE3BN", 0x00111030, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
271 {"NANO110RC2BN", 0x00111043, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
272 {"NANO110RD2BN", 0x00111044, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
273 {"NANO110RD3BN", 0x00111045, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
274 {"NANO110SC2BN", 0x00111042, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
275 {"NANO110SD2BN", 0x0011103D, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
276 {"NANO110SD3BN", 0x0011103C, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
277 {"NANO110SE3BN", 0x00111034, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
278 {"NANO120KC2BN", 0x00112040, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
279 {"NANO120KD2BN", 0x00112039, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
280 {"NANO120KD3BN", 0x00112038, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
281 {"NANO120KE3BN", 0x00112030, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
282 {"NANO120LC2BN", 0x00112043, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
283 {"NANO120LD2BN", 0x0011203F, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
284 {"NANO120LD3BN", 0x0011203E, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
285 {"NANO120LE3BN", 0x00112036, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
286 {"NANO120SC2BN", 0x00112042, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
287 {"NANO120SD2BN", 0x0011203D, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
288 {"NANO120SD3BN", 0x0011203C, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
289 {"NANO120SE3BN", 0x00112034, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
290 {"NANO130KC2BN", 0x00113040, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
291 {"NANO130KD2BN", 0x00113039, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
292 {"NANO130KD3BN", 0x00113038, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
293 {"NANO130KE3BN", 0x00113030, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
294 {"NANO130SC2BN", 0x00113042, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
295 {"NANO130SD2BN", 0x0011303D, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
296 {"NANO130SD3BN", 0x0011303C, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
297 {"NANO130SE3BN", 0x00113034, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
298
299 /* NANO103 */
300 {"NANO103SD3AE", 0x00110301, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
301 {"NANO103LD3AE", 0x00110304, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
302 {"NANO103ZD3AE", 0x00110307, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
303
304 /* NANO112AN */
305 {"NANO102LB1AN", 0x00110206, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 4 * 1024, 8)},
306 {"NANO102LC2AN", 0x00110208, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
307 {"NANO102SC2AN", 0x00110212, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
308 {"NANO102ZB1AN", 0x00110202, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 4 * 1024, 8)},
309 {"NANO102ZC2AN", 0x00110204, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
310 {"NANO112LB1AN", 0x00111202, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 4 * 1024, 8)},
311 {"NANO112LC2AN", 0x00111204, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
312 {"NANO112RB1AN", 0x00111210, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 4 * 1024, 8)},
313 {"NANO112RC2AN", 0x00111212, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
314 {"NANO112SB1AN", 0x00111206, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 4 * 1024, 8)},
315 {"NANO112SC2AN", 0x00111208, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
316 {"NANO112VC2AN", 0x00111216, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
317
318 /* NUC029AN */
319 {"NUC029LAN", 0x00295A00, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 4)},
320 {"NUC029TAN", 0x00295804, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 4)},
321
322 /* NUC029AE */
323 {"NUC029FAE", 0x00295415, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 2 * 1024, 8)},
324
325 /* NUC100AN */
326 {"NUC100LD3AN", 0x00010003, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
327 {"NUC100LE3AN", 0x00010000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
328 {"NUC100RD3AN", 0x00010012, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
329 {"NUC100RE3AN", 0x00010009, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
330 {"NUC100VD2AN", 0x00010022, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
331 {"NUC100VD3AN", 0x00010021, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
332 {"NUC100VE3AN", 0x00100018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
333 {"NUC120LD3AN", 0x00012003, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
334 {"NUC120LE3AN", 0x00120000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
335 {"NUC120RD3AN", 0x00012012, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
336 {"NUC120RE3AN", 0x00012009, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
337 {"NUC120VD2AN", 0x00012022, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
338 {"NUC120VD3AN", 0x00012021, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
339 {"NUC120VE3AN", 0x00012018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
340
341 /* NUC100BN */
342 {"NUC100LC1BN", 0x10010008, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
343 {"NUC100LD1BN", 0x10010005, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
344 {"NUC100LD2BN", 0x10010004, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
345 {"NUC100RC1BN", 0x10010017, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
346 {"NUC100RD1BN", 0x10010014, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
347 {"NUC100RD2BN", 0x10010013, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
348 {"NUC120LC1BN", 0x10012008, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
349 {"NUC120LD1BN", 0x10012005, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
350 {"NUC120LD2BN", 0x10012004, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
351 {"NUC120RC1BN", 0x10012017, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
352 {"NUC120RD1BN", 0x10012014, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
353 {"NUC120RD2BN", 0x10012013, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
354
355 /* NUC100CN */
356 {"NUC130LC1CN", 0x20013008, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
357 {"NUC130LD2CN", 0x20013004, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
358 {"NUC130LE3CN", 0x20013000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
359 {"NUC130RC1CN", 0x20013017, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
360 {"NUC130RD2CN", 0x20013013, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
361 {"NUC130RE3CN", 0x20013009, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
362 {"NUC130VE3CN", 0x20013018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
363 {"NUC140LC1CN", 0x20014008, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
364 {"NUC140LD2CN", 0x20014004, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
365 {"NUC140LE3CN", 0x20014000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
366 {"NUC140RC1CN", 0x20014017, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
367 {"NUC140RD2CN", 0x20014013, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
368 {"NUC140RE3CN", 0x20014009, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
369 {"NUC140VE3CN", 0x20014018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
370
371 /* NUC100DN */
372 {"NUC100LC1DN", 0x30010008, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
373 {"NUC100LD1DN", 0x30010005, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
374 {"NUC100LD2DN", 0x30010004, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
375 {"NUC100LD3DN", 0x30010003, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
376 {"NUC100LE3DN", 0x30010000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
377 {"NUC100RC1DN", 0x30010017, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
378 {"NUC100RD1DN", 0x30010014, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
379 {"NUC100RD2DN", 0x30010013, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
380 {"NUC100RD3DN", 0x30010012, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
381 {"NUC100RE3DN", 0x30010009, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
382 {"NUC100VD2DN", 0x30010022, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
383 {"NUC100VD3DN", 0x30010021, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
384 {"NUC100VE3DN", 0x30010018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
385 {"NUC120LC1DN", 0x30012008, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
386 {"NUC120LD1DN", 0x30012005, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
387 {"NUC120LD2DN", 0x30012004, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
388 {"NUC120LD3DN", 0x30012003, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
389 {"NUC120LE3DN", 0x30012000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
390 {"NUC120RC1DN", 0x30012035, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
391 {"NUC120RD1DN", 0x30012032, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
392 {"NUC120RD2DN", 0x30012031, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
393 {"NUC120RD3DN", 0x30012030, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
394 {"NUC120RE3DN", 0x30012027, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
395 {"NUC120VD2DN", 0x30012022, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
396 {"NUC120VD3DN", 0x30012021, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
397 {"NUC120VE3DN", 0x30012018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
398
399 /* NUC121 */
400 {"NUC121SC2AE", 0x00012105, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 9 * 512, 8)},
401 {"NUC121LC2AE", 0x00012125, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 9 * 512, 8)},
402 {"NUC121ZC2AE", 0x00012145, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 9 * 512, 8)},
403 {"NUC125SC2AE", 0x00012505, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 9 * 512, 8)},
404 {"NUC125LC2AE", 0x00012525, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 9 * 512, 8)},
405 {"NUC125ZC2AE", 0x00012545, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 9 * 512, 8)},
406
407 /* NUC122 */
408 {"NUC122LC1AN", 0x00012208, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
409 {"NUC122LD2AN", 0x00012204, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
410 {"NUC122SC1AN", 0x00012226, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
411 {"NUC122SD2AN", 0x00012222, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
412 {"NUC122ZC1AN", 0x00012235, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
413 {"NUC122ZD2AN", 0x00012231, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
414
415 /* NUC123AN */
416 {"NUC123LC2AN1", 0x00012325, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
417 {"NUC123LD4AN0", 0x00012335, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
418 {"NUC123SC2AN1", 0x00012305, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
419 {"NUC123SD4AN0", 0x00012315, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
420 {"NUC123ZC2AN1", 0x00012345, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
421 {"NUC123ZD4AN0", 0x00012355, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
422
423 /* NUC123AE */
424 {"NUC123LC2AE1", 0x10012325, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
425 {"NUC123LD4AE0", 0x10012335, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
426 {"NUC123SC2AE1", 0x10012305, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
427 {"NUC123SD4AE0", 0x10012315, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
428 {"NUC123ZC2AE1", 0x10012345, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
429 {"NUC123ZD4AE0", 0x10012355, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
430
431 /* NUC131AE */
432 {"NUC131LC2AE", 0x10013103, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
433 {"NUC131LD2AE", 0x10013100, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
434 {"NUC131SC2AE", 0x10013113, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
435 {"NUC131SD2AE", 0x10013110, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
436
437 /* NUC200/220AN */
438 {"NUC200LC2AN", 0x00020007, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
439 {"NUC200LD2AN", 0x00020004, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
440 {"NUC200LE3AN", 0x00020000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
441 {"NUC200SC2AN", 0x00020034, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
442 {"NUC200SD2AN", 0x00020031, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
443 {"NUC200SE3AN", 0x00020027, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
444 {"NUC200VE3AN", 0x00020018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
445 {"NUC220LC2AN", 0x00022007, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
446 {"NUC220LD2AN", 0x00022004, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
447 {"NUC220LE3AN", 0x00022000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
448 {"NUC220SC2AN", 0x00022034, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
449 {"NUC220SD2AN", 0x00022031, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
450 {"NUC220SE3AN", 0x00022027, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
451 {"NUC220VE3AN", 0x00022018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
452
453 /* NUC230/240AE */
454 {"NUC230LC2AE", 0x10023007, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 8 * 1024, 8)},
455 {"NUC230LD2AE", 0x10023004, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 8 * 1024, 8)},
456 {"NUC230LE3AE", 0x10023000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 8 * 1024, 8)},
457 {"NUC230SC2AE", 0x10023034, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 8 * 1024, 8)},
458 {"NUC230SD2AE", 0x10023031, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 8 * 1024, 8)},
459 {"NUC230SE3AE", 0x10023027, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 8 * 1024, 8)},
460 {"NUC230VE3AE", 0x10023018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 8 * 1024, 8)},
461 {"NUC240LC2AE", 0x10024007, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 8 * 1024, 8)},
462 {"NUC240LD2AE", 0x10024004, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 8 * 1024, 8)},
463 {"NUC240LE3AE", 0x10024000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 8 * 1024, 8)},
464 {"NUC240SC2AE", 0x10024034, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 8 * 1024, 8)},
465 {"NUC240SD2AE", 0x10024031, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 8 * 1024, 8)},
466 {"NUC240SE3AE", 0x10024027, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 8 * 1024, 8)},
467 {"NUC240VE3AE", 0x10024018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 8 * 1024, 8)},
468
469 /* M451 */
470 {"M451LC3AE", 0x00945101, NUMICRO_BANKS_GENERAL(40 * 1024, 0 * 1024, 4 * 1024, 8)},
471 {"M451LD3AE", 0x00945100, NUMICRO_BANKS_GENERAL(72 * 1024, 0 * 1024, 4 * 1024, 8)},
472 {"M451LE6AE", 0x00845101, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
473 {"M451LG6AE", 0x00845100, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
474 {"M451MLC3AE", 0x00945001, NUMICRO_BANKS_GENERAL(40 * 1024, 0 * 1024, 4 * 1024, 8)},
475 {"M451MLD3AE", 0x00945000, NUMICRO_BANKS_GENERAL(72 * 1024, 0 * 1024, 4 * 1024, 8)},
476 {"M451MLE6AE", 0x00845001, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
477 {"M451MLG6AE", 0x00845000, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
478 {"M451MSC3AE", 0x00945011, NUMICRO_BANKS_GENERAL(40 * 1024, 0 * 1024, 4 * 1024, 8)},
479 {"M451MSD3AE", 0x00945010, NUMICRO_BANKS_GENERAL(72 * 1024, 0 * 1024, 4 * 1024, 8)},
480 {"M451RC3AE", 0x00945121, NUMICRO_BANKS_GENERAL(40 * 1024, 0 * 1024, 4 * 1024, 8)},
481 {"M451RD3AE", 0x00945120, NUMICRO_BANKS_GENERAL(72 * 1024, 0 * 1024, 4 * 1024, 8)},
482 {"M451RE6AE", 0x00845121, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
483 {"M451RG6AE", 0x00845120, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
484 {"M451VE6AE", 0x00845131, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
485 {"M451VG6AE", 0x00845130, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
486 {"M452LC3AE", 0x00945201, NUMICRO_BANKS_GENERAL(40 * 1024, 0 * 1024, 4 * 1024, 8)},
487 {"M452LD3AE", 0x00945200, NUMICRO_BANKS_GENERAL(72 * 1024, 0 * 1024, 4 * 1024, 8)},
488 {"M452LE6AE", 0x00845201, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
489 {"M452LG6AE", 0x00845200, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
490 {"M452RD3AE", 0x00945220, NUMICRO_BANKS_GENERAL(72 * 1024, 0 * 1024, 4 * 1024, 8)},
491 {"M452RE6AE", 0x00845221, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
492 {"M452RG6AE", 0x00845220, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
493 {"M453LC3AE", 0x00945301, NUMICRO_BANKS_GENERAL(40 * 1024, 0 * 1024, 4 * 1024, 8)},
494 {"M453LD3AE", 0x00945300, NUMICRO_BANKS_GENERAL(72 * 1024, 0 * 1024, 4 * 1024, 8)},
495 {"M453LE6AE", 0x00845301, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
496 {"M453LG6AE", 0x00845300, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
497 {"M453RD3AE", 0x00945320, NUMICRO_BANKS_GENERAL(72 * 1024, 0 * 1024, 4 * 1024, 8)},
498 {"M453RE6AE", 0x00845321, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
499 {"M453RG6AE", 0x00845320, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
500 {"M453VD3AE", 0x00945330, NUMICRO_BANKS_GENERAL(72 * 1024, 0 * 1024, 4 * 1024, 8)},
501 {"M453VE6AE", 0x00845331, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
502 {"M453VG6AE", 0x00845330, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
503 {"M4TKVG6AE", 0x00845430, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
504 {"M4TKVE6AE", 0x00845431, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
505 {"M4TKRG6AE", 0x00845420, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
506 {"M4TKRE6AE", 0x00845421, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
507 {"M4TKLG6AE", 0x00845400, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
508 {"M4TKLE6AE", 0x00845401, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
509
510 /* NUC442_472 */
511 {"NUC442JG8AE", 0x00044203, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 16 * 1024, 16)},
512 {"NUC442JI8AE", 0x00044201, NUMICRO_BANKS_GENERAL(512 * 1024, 0 * 1024, 16 * 1024, 16)},
513 {"NUC442KG8AE", 0x00044206, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 16 * 1024, 16)},
514 {"NUC442KI8AE", 0x00044204, NUMICRO_BANKS_GENERAL(512 * 1024, 0 * 1024, 16 * 1024, 16)},
515 {"NUC442RG8AE", 0x00044212, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 16 * 1024, 16)},
516 {"NUC442RI8AE", 0x00044210, NUMICRO_BANKS_GENERAL(512 * 1024, 0 * 1024, 16 * 1024, 16)},
517 {"NUC442VG8AE", 0x00044209, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 16 * 1024, 16)},
518 {"NUC442VI8AE", 0x00044207, NUMICRO_BANKS_GENERAL(512 * 1024, 0 * 1024, 16 * 1024, 16)},
519 {"NUC472HG8AE", 0x00047203, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 16 * 1024, 16)},
520 {"NUC472HI8AE", 0x00047201, NUMICRO_BANKS_GENERAL(512 * 1024, 0 * 1024, 16 * 1024, 16)},
521 {"NUC472JG8AE", 0x00047206, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 16 * 1024, 16)},
522 {"NUC472JI8AE", 0x00047204, NUMICRO_BANKS_GENERAL(512 * 1024, 0 * 1024, 16 * 1024, 16)},
523 {"NUC472KG8AE", 0x00047209, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 16 * 1024, 16)},
524 {"NUC472KI8AE", 0x00047207, NUMICRO_BANKS_GENERAL(512 * 1024, 0 * 1024, 16 * 1024, 16)},
525 {"NUC472VG8AE", 0x00047212, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 16 * 1024, 16)},
526 {"NUC472VI8AE", 0x00047210, NUMICRO_BANKS_GENERAL(512 * 1024, 0 * 1024, 16 * 1024, 16)},
527
528 {"UNKNOWN", 0x00000000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 16 * 1024, 8)},
529 };
530
531 /* Private bank information for NuMicro. */
532 struct numicro_flash_bank {
533 struct working_area *write_algorithm;
534 bool probed;
535 const struct numicro_cpu_type *cpu;
536 };
537
538 /* Private variables */
539 static uint32_t m_page_size = NUMICRO_PAGESIZE;
540 static uint32_t m_address_bias_offset;
541
542 /* Private methods */
543 static int numicro_get_arm_arch(struct target *target)
544 {
545 struct armv7m_common *armv7m = target_to_armv7m(target);
546
547 if (armv7m->arm.arch != ARM_ARCH_V6M) {
548 LOG_DEBUG("NuMicro arm architecture: armv7m\n");
549 m_page_size = NUMICRO_PAGESIZE * 4;
550 m_address_bias_offset = 0x10000000;
551 } else {
552 LOG_DEBUG("NuMicro arm architecture: armv6m\n");
553 m_page_size = NUMICRO_PAGESIZE;
554 m_address_bias_offset = 0x0;
555 }
556
557 return ERROR_OK;
558 }
559
560 static int numicro_reg_unlock(struct target *target)
561 {
562 uint32_t is_protected;
563 int retval = ERROR_OK;
564
565 /* Check to see if NUC is register unlocked or not */
566 retval = target_read_u32(target, NUMICRO_SYS_WRPROT - m_address_bias_offset, &is_protected);
567 if (retval != ERROR_OK)
568 return retval;
569
570 LOG_DEBUG("protected = 0x%08" PRIx32 "", is_protected);
571 if (is_protected == 0) { /* means protected - so unlock it */
572 /* unlock flash registers */
573 retval = target_write_u32(target, NUMICRO_SYS_WRPROT - m_address_bias_offset, REG_KEY1);
574 if (retval != ERROR_OK)
575 return retval;
576 retval = target_write_u32(target, NUMICRO_SYS_WRPROT - m_address_bias_offset, REG_KEY2);
577 if (retval != ERROR_OK)
578 return retval;
579 retval = target_write_u32(target, NUMICRO_SYS_WRPROT - m_address_bias_offset, REG_KEY3);
580 if (retval != ERROR_OK)
581 return retval;
582 }
583 /* Check that unlock worked */
584 retval = target_read_u32(target, NUMICRO_SYS_WRPROT - m_address_bias_offset, &is_protected);
585 if (retval != ERROR_OK)
586 return retval;
587
588 if (is_protected == 1) { /* means unprotected */
589 LOG_DEBUG("protection removed");
590 } else {
591 LOG_DEBUG("still protected!!");
592 }
593
594 return ERROR_OK;
595 }
596
597 static int numicro_init_isp(struct target *target)
598 {
599 uint32_t reg_stat;
600 int retval = ERROR_OK;
601
602 if (target->state != TARGET_HALTED) {
603 LOG_ERROR("Target not halted");
604 return ERROR_TARGET_NOT_HALTED;
605 }
606
607 retval = numicro_reg_unlock(target);
608 if (retval != ERROR_OK)
609 return retval;
610
611 /* Enable ISP/SRAM/TICK Clock */
612 retval = target_read_u32(target, NUMICRO_SYSCLK_AHBCLK - m_address_bias_offset, &reg_stat);
613 if (retval != ERROR_OK)
614 return retval;
615
616 reg_stat |= AHBCLK_ISP_EN | AHBCLK_SRAM_EN | AHBCLK_TICK_EN;
617 retval = target_write_u32(target, NUMICRO_SYSCLK_AHBCLK - m_address_bias_offset, reg_stat);
618 if (retval != ERROR_OK)
619 return retval;
620
621 /* Enable ISP */
622 retval = target_read_u32(target, NUMICRO_FLASH_ISPCON - m_address_bias_offset, &reg_stat);
623 if (retval != ERROR_OK)
624 return retval;
625
626 reg_stat |= ISPCON_ISPFF | ISPCON_LDUEN | ISPCON_APUEN | ISPCON_CFGUEN | ISPCON_ISPEN;
627 retval = target_write_u32(target, NUMICRO_FLASH_ISPCON - m_address_bias_offset, reg_stat);
628 if (retval != ERROR_OK)
629 return retval;
630
631 /* Write one to undocumented flash control register */
632 retval = target_write_u32(target, NUMICRO_FLASH_CHEAT - m_address_bias_offset, 1);
633 if (retval != ERROR_OK)
634 return retval;
635
636 return ERROR_OK;
637 }
638
639 static uint32_t numicro_fmc_cmd(struct target *target, uint32_t cmd, uint32_t addr, uint32_t wdata, uint32_t *rdata)
640 {
641 uint32_t timeout, status;
642 int retval = ERROR_OK;
643
644 retval = target_write_u32(target, NUMICRO_FLASH_ISPCMD - m_address_bias_offset, cmd);
645 if (retval != ERROR_OK)
646 return retval;
647
648 retval = target_write_u32(target, NUMICRO_FLASH_ISPDAT - m_address_bias_offset, wdata);
649 if (retval != ERROR_OK)
650 return retval;
651
652 retval = target_write_u32(target, NUMICRO_FLASH_ISPADR - m_address_bias_offset, addr);
653 if (retval != ERROR_OK)
654 return retval;
655
656 retval = target_write_u32(target, NUMICRO_FLASH_ISPTRG - m_address_bias_offset, ISPTRG_ISPGO);
657 if (retval != ERROR_OK)
658 return retval;
659
660 /* Wait for busy to clear - check the GO flag */
661 timeout = 100;
662 for (;;) {
663 retval = target_read_u32(target, NUMICRO_FLASH_ISPTRG - m_address_bias_offset, &status);
664 if (retval != ERROR_OK)
665 return retval;
666 if ((status & (ISPTRG_ISPGO)) == 0)
667 break;
668 if (timeout-- <= 0) {
669 LOG_DEBUG("timed out waiting for flash");
670 return ERROR_FAIL;
671 }
672 busy_sleep(1); /* can use busy sleep for short times. */
673 }
674
675 retval = target_read_u32(target, NUMICRO_FLASH_ISPDAT - m_address_bias_offset, rdata);
676 if (retval != ERROR_OK)
677 return retval;
678
679 return ERROR_OK;
680 }
681
682 /* NuMicro Program-LongWord Microcodes */
683 static const uint8_t numicro_flash_write_code[] = {
684 #include "../../../contrib/loaders/flash/numicro/numicro_m0.inc"
685 };
686
687 static const uint8_t numicro_m4_flash_write_code[] = {
688 #include "../../../contrib/loaders/flash/numicro/numicro_m4.inc"
689 };
690
691 /* Program LongWord Block Write */
692 static int numicro_writeblock(struct flash_bank *bank, const uint8_t *buffer,
693 uint32_t offset, uint32_t count)
694 {
695 struct target *target = bank->target;
696 uint32_t buffer_size = 1024; /* Default minimum value */
697 struct working_area *write_algorithm;
698 struct working_area *source;
699 uint32_t address = bank->base + offset;
700 struct reg_param reg_params[3];
701 struct armv7m_algorithm armv7m_info;
702 int retval = ERROR_OK;
703
704 /* Params:
705 * r0 - workarea buffer / result
706 * r1 - target address
707 * r2 - wordcount
708 * Clobbered:
709 * r4 - tmp
710 * r5 - tmp
711 * r6 - tmp
712 * r7 - tmp
713 */
714
715 /* Increase buffer_size if needed */
716 if (buffer_size < (target->working_area_size/2))
717 buffer_size = (target->working_area_size/2);
718
719 /* check code alignment */
720 if (offset & 0x1) {
721 LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
722 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
723 }
724 /* Difference between M0 and M4 */
725 if (m_page_size == NUMICRO_PAGESIZE) {
726 /* allocate working area with flash programming code */
727 if (target_alloc_working_area(target, sizeof(numicro_flash_write_code),
728 &write_algorithm) != ERROR_OK) {
729 LOG_WARNING("no working area available, can't do block memory writes");
730 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
731 }
732
733 retval = target_write_buffer(target, write_algorithm->address,
734 sizeof(numicro_flash_write_code), numicro_flash_write_code);
735 if (retval != ERROR_OK)
736 return retval;
737 } else { /* for M4 */
738 /* allocate working area with flash programming code */
739 if (target_alloc_working_area(target, sizeof(numicro_m4_flash_write_code),
740 &write_algorithm) != ERROR_OK) {
741 LOG_WARNING("no working area available, can't do block memory writes");
742 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
743 }
744
745 retval = target_write_buffer(target, write_algorithm->address,
746 sizeof(numicro_m4_flash_write_code), numicro_m4_flash_write_code);
747 if (retval != ERROR_OK)
748 return retval;
749
750 buffer_size = m_page_size;
751 }
752
753 /* memory buffer */
754 while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK) {
755 buffer_size /= 4;
756 if (buffer_size <= 256) {
757 /* free working area, write algorithm already allocated */
758 target_free_working_area(target, write_algorithm);
759
760 LOG_WARNING("No large enough working area available, can't do block memory writes");
761 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
762 }
763 }
764
765 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
766 armv7m_info.core_mode = ARM_MODE_THREAD;
767
768 init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* *pLW (*buffer) */
769 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* faddr */
770 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* number of words to program */
771
772 /* write code buffer and use Flash programming code within NuMicro */
773 /* Set breakpoint to 0 with time-out of 1000 ms */
774 while (count > 0) {
775 uint32_t thisrun_count = (count > (buffer_size / 4)) ? (buffer_size / 4) : count;
776
777 retval = target_write_buffer(target, source->address, thisrun_count * 4, buffer);
778 if (retval != ERROR_OK)
779 break;
780
781 buf_set_u32(reg_params[0].value, 0, 32, source->address);
782 buf_set_u32(reg_params[1].value, 0, 32, address);
783 buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
784
785 retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
786 write_algorithm->address, 0, 100000, &armv7m_info);
787 if (retval != ERROR_OK) {
788 LOG_ERROR("Error executing NuMicro Flash programming algorithm");
789 retval = ERROR_FLASH_OPERATION_FAILED;
790 break;
791 }
792
793 buffer += thisrun_count * 4;
794 address += thisrun_count * 4;
795 count -= thisrun_count;
796 }
797
798 target_free_working_area(target, source);
799 target_free_working_area(target, write_algorithm);
800
801 destroy_reg_param(&reg_params[0]);
802 destroy_reg_param(&reg_params[1]);
803 destroy_reg_param(&reg_params[2]);
804
805 return retval;
806 }
807
808 /* Flash Lock checking - examines the lock bit. */
809 static int numicro_protect_check(struct flash_bank *bank)
810 {
811 struct target *target = bank->target;
812 uint32_t set, config[2];
813 int retval = ERROR_OK;
814
815 if (target->state != TARGET_HALTED) {
816 LOG_ERROR("Target not halted");
817 return ERROR_TARGET_NOT_HALTED;
818 }
819
820 LOG_INFO("Nuvoton NuMicro: Flash Lock Check...");
821
822 numicro_get_arm_arch(target);
823 retval = numicro_init_isp(target);
824 if (retval != ERROR_OK)
825 return retval;
826
827 /* Read CONFIG0,CONFIG1 */
828 numicro_fmc_cmd(target, ISPCMD_READ, NUMICRO_CONFIG0 - m_address_bias_offset, 0, &config[0]);
829 numicro_fmc_cmd(target, ISPCMD_READ, NUMICRO_CONFIG1 - m_address_bias_offset, 0, &config[1]);
830
831 LOG_DEBUG("CONFIG0: 0x%" PRIx32 ",CONFIG1: 0x%" PRIx32 "", config[0], config[1]);
832
833 if ((config[0] & (1<<7)) == 0)
834 LOG_INFO("CBS=0: Boot From LPROM");
835 else
836 LOG_INFO("CBS=1: Boot From APROM");
837
838 if ((config[0] & CONFIG0_LOCK_MASK) == 0) {
839
840 LOG_INFO("Flash is secure locked!");
841 LOG_INFO("TO UNLOCK FLASH,EXECUTE chip_erase COMMAND!!");
842 set = 1;
843 } else {
844 LOG_INFO("Flash is not locked!");
845 set = 0;
846 }
847
848 for (unsigned int i = 0; i < bank->num_sectors; i++)
849 bank->sectors[i].is_protected = set;
850
851 return ERROR_OK;
852 }
853
854
855 static int numicro_erase(struct flash_bank *bank, unsigned int first,
856 unsigned int last)
857 {
858 struct target *target = bank->target;
859 uint32_t timeout, status;
860 int retval = ERROR_OK;
861
862 if (target->state != TARGET_HALTED) {
863 LOG_ERROR("Target not halted");
864 return ERROR_TARGET_NOT_HALTED;
865 }
866
867 LOG_INFO("Nuvoton NuMicro: Sector Erase ... (%u to %u)", first, last);
868
869 numicro_get_arm_arch(target);
870 retval = numicro_init_isp(target);
871 if (retval != ERROR_OK)
872 return retval;
873
874 retval = target_write_u32(target, NUMICRO_FLASH_ISPCMD - m_address_bias_offset, ISPCMD_ERASE);
875 if (retval != ERROR_OK)
876 return retval;
877
878 for (unsigned int i = first; i <= last; i++) {
879 LOG_DEBUG("erasing sector %u at address " TARGET_ADDR_FMT, i, bank->base + bank->sectors[i].offset);
880 retval = target_write_u32(target,
881 NUMICRO_FLASH_ISPADR - m_address_bias_offset,
882 bank->base + bank->sectors[i].offset);
883 if (retval != ERROR_OK)
884 return retval;
885 retval = target_write_u32(target,
886 NUMICRO_FLASH_ISPTRG - m_address_bias_offset,
887 ISPTRG_ISPGO); /* This is the only bit available */
888 if (retval != ERROR_OK)
889 return retval;
890
891 /* wait for busy to clear - check the GO flag */
892 timeout = 100;
893 for (;;) {
894 retval = target_read_u32(target, NUMICRO_FLASH_ISPTRG - m_address_bias_offset, &status);
895 if (retval != ERROR_OK)
896 return retval;
897 if (status == 0)
898 break;
899 if (timeout-- <= 0) {
900 LOG_DEBUG("timed out waiting for flash");
901 return ERROR_FAIL;
902 }
903 busy_sleep(1); /* can use busy sleep for short times. */
904 }
905
906 /* check for failure */
907 retval = target_read_u32(target, NUMICRO_FLASH_ISPCON - m_address_bias_offset, &status);
908 if (retval != ERROR_OK)
909 return retval;
910 if ((status & ISPCON_ISPFF) != 0) {
911 LOG_DEBUG("failure: 0x%" PRIx32 "", status);
912 /* if bit is set, then must write to it to clear it. */
913 retval = target_write_u32(target, NUMICRO_FLASH_ISPCON - m_address_bias_offset, (status | ISPCON_ISPFF));
914 if (retval != ERROR_OK)
915 return retval;
916 }
917 }
918
919 /* done, */
920 LOG_DEBUG("Erase done.");
921
922 return ERROR_OK;
923 }
924
925 /* The write routine stub. */
926 static int numicro_write(struct flash_bank *bank, const uint8_t *buffer,
927 uint32_t offset, uint32_t count)
928 {
929 struct target *target = bank->target;
930 uint32_t timeout, status;
931 int retval = ERROR_OK;
932
933 if (target->state != TARGET_HALTED) {
934 LOG_ERROR("Target not halted");
935 return ERROR_TARGET_NOT_HALTED;
936 }
937
938 LOG_INFO("Nuvoton NuMicro: Flash Write ...");
939
940 numicro_get_arm_arch(target);
941 retval = numicro_init_isp(target);
942 if (retval != ERROR_OK)
943 return retval;
944
945 retval = target_write_u32(target, NUMICRO_FLASH_ISPCMD - m_address_bias_offset, ISPCMD_WRITE);
946 if (retval != ERROR_OK)
947 return retval;
948
949 assert(offset % 4 == 0);
950 assert(count % 4 == 0);
951
952 uint32_t words_remaining = count / 4;
953
954 /* try using a block write */
955 retval = numicro_writeblock(bank, buffer, offset, words_remaining);
956
957 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
958 /* if block write failed (no sufficient working area),
959 * we use normal (slow) single word accesses */
960 LOG_WARNING("couldn't use block writes, falling back to single "
961 "memory accesses");
962
963 /* program command */
964 for (uint32_t i = 0; i < count; i += 4) {
965 /* write 4 bytes each time with 0xff padding to avoid unaligned case */
966 uint8_t padding[4] = {0xff, 0xff, 0xff, 0xff};
967 memcpy(padding, buffer + i, MIN(4, count - i));
968
969 retval = target_write_u32(target,
970 NUMICRO_FLASH_ISPADR - m_address_bias_offset,
971 bank->base + offset + i);
972 if (retval != ERROR_OK)
973 return retval;
974 retval = target_write_memory(target,
975 NUMICRO_FLASH_ISPDAT - m_address_bias_offset,
976 4, 1, padding);
977 if (retval != ERROR_OK)
978 return retval;
979 retval = target_write_u32(target,
980 NUMICRO_FLASH_ISPTRG - m_address_bias_offset,
981 ISPTRG_ISPGO);
982 if (retval != ERROR_OK)
983 return retval;
984
985 /* wait for busy to clear - check the GO flag */
986 timeout = 100;
987 for (;;) {
988 retval = target_read_u32(target,
989 NUMICRO_FLASH_ISPTRG - m_address_bias_offset,
990 &status);
991 if (retval != ERROR_OK)
992 return retval;
993 if (status == 0)
994 break;
995 if (timeout-- <= 0) {
996 LOG_DEBUG("timed out waiting for flash");
997 return ERROR_FAIL;
998 }
999 busy_sleep(1); /* can use busy sleep for short times. */
1000 }
1001
1002 }
1003 }
1004
1005 /* check for failure */
1006 retval = target_read_u32(target, NUMICRO_FLASH_ISPCON - m_address_bias_offset, &status);
1007 if (retval != ERROR_OK)
1008 return retval;
1009 if ((status & ISPCON_ISPFF) != 0) {
1010 LOG_DEBUG("failure: 0x%" PRIx32 "", status);
1011 /* if bit is set, then must write to it to clear it. */
1012 retval = target_write_u32(target,
1013 NUMICRO_FLASH_ISPCON - m_address_bias_offset,
1014 (status | ISPCON_ISPFF));
1015 if (retval != ERROR_OK)
1016 return retval;
1017 } else {
1018 LOG_DEBUG("Write OK");
1019 }
1020
1021 /* done. */
1022 LOG_DEBUG("Write done.");
1023
1024 return ERROR_OK;
1025 }
1026
1027 static int numicro_get_cpu_type(struct target *target, const struct numicro_cpu_type **cpu)
1028 {
1029 uint32_t part_id;
1030 int retval = ERROR_OK;
1031
1032 numicro_get_arm_arch(target);
1033 /* Read NuMicro PartID */
1034 retval = target_read_u32(target, NUMICRO_SYS_BASE - m_address_bias_offset, &part_id);
1035 if (retval != ERROR_OK) {
1036 LOG_WARNING("NuMicro flash driver: Failed to Get PartID\n");
1037 return ERROR_FLASH_OPERATION_FAILED;
1038 }
1039
1040 LOG_INFO("Device ID: 0x%08" PRIx32 "", part_id);
1041 /* search part numbers */
1042 for (size_t i = 0; i < ARRAY_SIZE(numicro_parts); i++) {
1043 if (part_id == numicro_parts[i].partid) {
1044 *cpu = &numicro_parts[i];
1045 LOG_INFO("Device Name: %s", (*cpu)->partname);
1046 return ERROR_OK;
1047 }
1048 }
1049
1050 return ERROR_FAIL;
1051 }
1052
1053 static int numicro_get_flash_size(struct flash_bank *bank, const struct numicro_cpu_type *cpu, uint32_t *flash_size)
1054 {
1055 for (size_t i = 0; i < cpu->n_banks; i++) {
1056 if (bank->base == cpu->bank[i].base) {
1057 *flash_size = cpu->bank[i].size;
1058 LOG_INFO("bank base = " TARGET_ADDR_FMT ", size = 0x%08"
1059 PRIx32, bank->base, *flash_size);
1060 return ERROR_OK;
1061 }
1062 }
1063 return ERROR_FLASH_OPERATION_FAILED;
1064 }
1065
1066 static int numicro_probe(struct flash_bank *bank)
1067 {
1068 uint32_t flash_size, offset = 0;
1069 int num_pages;
1070 const struct numicro_cpu_type *cpu;
1071 struct target *target = bank->target;
1072 int retval = ERROR_OK;
1073
1074 retval = numicro_get_cpu_type(target, &cpu);
1075 if (retval != ERROR_OK) {
1076 LOG_WARNING("NuMicro flash driver: Failed to detect a known part\n");
1077 return ERROR_FLASH_OPERATION_FAILED;
1078 }
1079
1080 retval = numicro_get_flash_size(bank, cpu, &flash_size);
1081 if (retval != ERROR_OK) {
1082 LOG_WARNING("NuMicro flash driver: Failed to detect flash size\n");
1083 return ERROR_FLASH_OPERATION_FAILED;
1084 }
1085
1086 num_pages = flash_size / m_page_size;
1087
1088 bank->num_sectors = num_pages;
1089 bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
1090 bank->size = flash_size;
1091
1092 for (int i = 0; i < num_pages; i++) {
1093 bank->sectors[i].offset = offset;
1094 bank->sectors[i].size = m_page_size;
1095 bank->sectors[i].is_erased = -1;
1096 bank->sectors[i].is_protected = 0;
1097 offset += m_page_size;
1098 }
1099
1100 struct numicro_flash_bank *numicro_info = bank->driver_priv;
1101 numicro_info->probed = true;
1102 numicro_info->cpu = cpu;
1103 LOG_DEBUG("Nuvoton NuMicro: Probed ...");
1104
1105 return ERROR_OK;
1106 }
1107
1108 /* Standard approach to autoprobing. */
1109 static int numicro_auto_probe(struct flash_bank *bank)
1110 {
1111 struct numicro_flash_bank *numicro_info = bank->driver_priv;
1112 if (numicro_info->probed)
1113 return ERROR_OK;
1114 return numicro_probe(bank);
1115 }
1116
1117
1118 /* This is the function called in the config file. */
1119 FLASH_BANK_COMMAND_HANDLER(numicro_flash_bank_command)
1120 {
1121 struct numicro_flash_bank *bank_info;
1122
1123 if (CMD_ARGC < 6)
1124 return ERROR_COMMAND_SYNTAX_ERROR;
1125
1126 LOG_DEBUG("add flash_bank numicro %s", bank->name);
1127
1128 bank_info = malloc(sizeof(struct numicro_flash_bank));
1129
1130 memset(bank_info, 0, sizeof(struct numicro_flash_bank));
1131
1132 bank->driver_priv = bank_info;
1133 bank->write_start_alignment = bank->write_end_alignment = 4;
1134
1135 return ERROR_OK;
1136 }
1137
1138 COMMAND_HANDLER(numicro_handle_read_isp_command)
1139 {
1140 uint32_t address;
1141 uint32_t ispdat;
1142 int retval = ERROR_OK;
1143
1144 if (CMD_ARGC != 1)
1145 return ERROR_COMMAND_SYNTAX_ERROR;
1146
1147 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
1148
1149 struct target *target = get_current_target(CMD_CTX);
1150
1151 numicro_get_arm_arch(target);
1152 retval = numicro_init_isp(target);
1153 if (retval != ERROR_OK)
1154 return retval;
1155
1156 retval = numicro_fmc_cmd(target, ISPCMD_READ, address, 0, &ispdat);
1157 if (retval != ERROR_OK)
1158 return retval;
1159
1160 LOG_INFO("0x%08" PRIx32 ": 0x%08" PRIx32, address, ispdat);
1161
1162 return ERROR_OK;
1163 }
1164
1165 COMMAND_HANDLER(numicro_handle_write_isp_command)
1166 {
1167 uint32_t address;
1168 uint32_t ispdat, rdat;
1169 int retval = ERROR_OK;
1170
1171 if (CMD_ARGC != 2)
1172 return ERROR_COMMAND_SYNTAX_ERROR;
1173
1174 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
1175 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], ispdat);
1176
1177 struct target *target = get_current_target(CMD_CTX);
1178
1179 numicro_get_arm_arch(target);
1180 retval = numicro_init_isp(target);
1181 if (retval != ERROR_OK)
1182 return retval;
1183
1184 retval = numicro_fmc_cmd(target, ISPCMD_WRITE, address, ispdat, &rdat);
1185 if (retval != ERROR_OK)
1186 return retval;
1187
1188 LOG_INFO("0x%08" PRIx32 ": 0x%08" PRIx32, address, ispdat);
1189 return ERROR_OK;
1190 }
1191
1192 COMMAND_HANDLER(numicro_handle_chip_erase_command)
1193 {
1194 int retval = ERROR_OK;
1195 uint32_t rdat;
1196
1197 if (CMD_ARGC != 0)
1198 return ERROR_COMMAND_SYNTAX_ERROR;
1199
1200 struct target *target = get_current_target(CMD_CTX);
1201
1202 numicro_get_arm_arch(target);
1203 retval = numicro_init_isp(target);
1204 if (retval != ERROR_OK)
1205 return retval;
1206
1207 retval = numicro_fmc_cmd(target, ISPCMD_CHIPERASE, 0, 0, &rdat);
1208 if (retval != ERROR_OK) {
1209 command_print(CMD, "numicro chip_erase failed");
1210 return retval;
1211 }
1212
1213 command_print(CMD, "numicro chip_erase complete");
1214
1215 return ERROR_OK;
1216 }
1217
1218 static const struct command_registration numicro_exec_command_handlers[] = {
1219 {
1220 .name = "read_isp",
1221 .handler = numicro_handle_read_isp_command,
1222 .usage = "address",
1223 .mode = COMMAND_EXEC,
1224 .help = "read flash through ISP.",
1225 },
1226 {
1227 .name = "write_isp",
1228 .handler = numicro_handle_write_isp_command,
1229 .usage = "address value",
1230 .mode = COMMAND_EXEC,
1231 .help = "write flash through ISP.",
1232 },
1233 {
1234 .name = "chip_erase",
1235 .handler = numicro_handle_chip_erase_command,
1236 .mode = COMMAND_EXEC,
1237 .help = "chip erase through ISP.",
1238 .usage = "",
1239 },
1240 COMMAND_REGISTRATION_DONE
1241 };
1242
1243 static const struct command_registration numicro_command_handlers[] = {
1244 {
1245 .name = "numicro",
1246 .mode = COMMAND_ANY,
1247 .help = "numicro flash command group",
1248 .usage = "",
1249 .chain = numicro_exec_command_handlers,
1250 },
1251 COMMAND_REGISTRATION_DONE
1252 };
1253
1254 const struct flash_driver numicro_flash = {
1255 .name = "numicro",
1256 .commands = numicro_command_handlers,
1257 .flash_bank_command = numicro_flash_bank_command,
1258 .erase = numicro_erase,
1259 .write = numicro_write,
1260 .read = default_flash_read,
1261 .probe = numicro_probe,
1262 .auto_probe = numicro_auto_probe,
1263 .erase_check = default_flash_blank_check,
1264 .protect_check = numicro_protect_check,
1265 .free_driver_priv = default_flash_free_driver_priv,
1266 };

Linking to existing account procedure

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

SSH host keys fingerprints

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