target/xtensa: avoid IHI for writes to non-executable memory
[openocd.git] / src / flash / nor / numicro.c
bloba0c6e0c8151d177194d93c0b239abcb2f32f4249
1 // SPDX-License-Identifier: GPL-2.0-or-later
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 ***************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
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>
33 /* Nuvoton NuMicro register locations */
34 #define NUMICRO_SYS_BASE 0x50000000
35 #define NUMICRO_SYS_WRPROT 0x50000100
36 #define NUMICRO_SYS_IPRSTC1 0x50000008
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
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) */
52 #define NUMICRO_SCS_BASE 0xE000E000
53 #define NUMICRO_SCS_AIRCR 0xE000ED0C
54 #define NUMICRO_SCS_DHCSR 0xE000EDF0
55 #define NUMICRO_SCS_DEMCR 0xE000EDFC
57 #define NUMICRO_APROM_BASE 0x00000000
58 #define NUMICRO_DATA_BASE 0x0001F000
59 #define NUMICRO_LDROM_BASE 0x00100000
60 #define NUMICRO_CONFIG_BASE 0x00300000
62 #define NUMICRO_CONFIG0 0x5000C000
63 #define NUMICRO_CONFIG1 0x5000C004
65 /* Command register bits */
66 #define PWRCON_OSC22M (1 << 2)
67 #define PWRCON_XTL12M (1 << 0)
69 #define IPRSTC1_CPU_RST (1 << 1)
70 #define IPRSTC1_CHIP_RST (1 << 0)
72 #define AHBCLK_ISP_EN (1 << 2)
73 #define AHBCLK_SRAM_EN (1 << 4)
74 #define AHBCLK_TICK_EN (1 << 5)
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)
85 #define CONFIG0_LOCK_MASK (1 << 1)
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)
98 /* access unlock keys */
99 #define REG_KEY1 0x59
100 #define REG_KEY2 0x16
101 #define REG_KEY3 0x88
102 #define REG_LOCK 0x00
104 /* flash pagesizes */
105 #define NUMICRO_PAGESIZE 512
106 /* flash MAX banks */
107 #define NUMICRO_MAX_FLASH_BANKS 4
109 /* flash bank structs */
110 struct numicro_flash_bank_type {
111 uint32_t base;
112 uint32_t size;
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];
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)}}
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)},
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)},
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)},
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)},
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)},
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)},
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)},
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)},
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)},
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)},
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)},
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)},
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)},
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)},
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)},
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)},
322 /* NUC029AE */
323 {"NUC029FAE", 0x00295415, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 2 * 1024, 8)},
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)},
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)},
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)},
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)},
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)},
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)},
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)},
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)},
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)},
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)},
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)},
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)},
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)},
528 {"UNKNOWN", 0x00000000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 16 * 1024, 8)},
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;
538 /* Private variables */
539 static uint32_t m_page_size = NUMICRO_PAGESIZE;
540 static uint32_t m_address_bias_offset;
542 /* Private methods */
543 static int numicro_get_arm_arch(struct target *target)
545 struct armv7m_common *armv7m = target_to_armv7m(target);
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;
557 return ERROR_OK;
560 static int numicro_reg_unlock(struct target *target)
562 uint32_t is_protected;
563 int retval = ERROR_OK;
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;
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;
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;
588 if (is_protected == 1) { /* means unprotected */
589 LOG_DEBUG("protection removed");
590 } else {
591 LOG_DEBUG("still protected!!");
594 return ERROR_OK;
597 static int numicro_init_isp(struct target *target)
599 uint32_t reg_stat;
600 int retval = ERROR_OK;
602 if (target->state != TARGET_HALTED) {
603 LOG_ERROR("Target not halted");
604 return ERROR_TARGET_NOT_HALTED;
607 retval = numicro_reg_unlock(target);
608 if (retval != ERROR_OK)
609 return retval;
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;
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;
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;
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;
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;
636 return ERROR_OK;
639 static uint32_t numicro_fmc_cmd(struct target *target, uint32_t cmd, uint32_t addr, uint32_t wdata, uint32_t *rdata)
641 uint32_t timeout, status;
642 int retval = ERROR_OK;
644 retval = target_write_u32(target, NUMICRO_FLASH_ISPCMD - m_address_bias_offset, cmd);
645 if (retval != ERROR_OK)
646 return retval;
648 retval = target_write_u32(target, NUMICRO_FLASH_ISPDAT - m_address_bias_offset, wdata);
649 if (retval != ERROR_OK)
650 return retval;
652 retval = target_write_u32(target, NUMICRO_FLASH_ISPADR - m_address_bias_offset, addr);
653 if (retval != ERROR_OK)
654 return retval;
656 retval = target_write_u32(target, NUMICRO_FLASH_ISPTRG - m_address_bias_offset, ISPTRG_ISPGO);
657 if (retval != ERROR_OK)
658 return retval;
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;
672 busy_sleep(1); /* can use busy sleep for short times. */
675 retval = target_read_u32(target, NUMICRO_FLASH_ISPDAT - m_address_bias_offset, rdata);
676 if (retval != ERROR_OK)
677 return retval;
679 return ERROR_OK;
682 /* NuMicro Program-LongWord Microcodes */
683 static const uint8_t numicro_flash_write_code[] = {
684 #include "../../../contrib/loaders/flash/numicro/numicro_m0.inc"
687 static const uint8_t numicro_m4_flash_write_code[] = {
688 #include "../../../contrib/loaders/flash/numicro/numicro_m4.inc"
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)
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;
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
715 /* Increase buffer_size if needed */
716 if (buffer_size < (target->working_area_size/2))
717 buffer_size = (target->working_area_size/2);
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;
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;
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;
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;
750 buffer_size = m_page_size;
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);
760 LOG_WARNING("No large enough working area available, can't do block memory writes");
761 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
765 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
766 armv7m_info.core_mode = ARM_MODE_THREAD;
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 */
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;
777 retval = target_write_buffer(target, source->address, thisrun_count * 4, buffer);
778 if (retval != ERROR_OK)
779 break;
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);
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;
793 buffer += thisrun_count * 4;
794 address += thisrun_count * 4;
795 count -= thisrun_count;
798 target_free_working_area(target, source);
799 target_free_working_area(target, write_algorithm);
801 destroy_reg_param(&reg_params[0]);
802 destroy_reg_param(&reg_params[1]);
803 destroy_reg_param(&reg_params[2]);
805 return retval;
808 /* Flash Lock checking - examines the lock bit. */
809 static int numicro_protect_check(struct flash_bank *bank)
811 struct target *target = bank->target;
812 uint32_t set, config[2];
813 int retval = ERROR_OK;
815 if (target->state != TARGET_HALTED) {
816 LOG_ERROR("Target not halted");
817 return ERROR_TARGET_NOT_HALTED;
820 LOG_INFO("Nuvoton NuMicro: Flash Lock Check...");
822 numicro_get_arm_arch(target);
823 retval = numicro_init_isp(target);
824 if (retval != ERROR_OK)
825 return retval;
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]);
831 LOG_DEBUG("CONFIG0: 0x%" PRIx32 ",CONFIG1: 0x%" PRIx32 "", config[0], config[1]);
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");
838 if ((config[0] & CONFIG0_LOCK_MASK) == 0) {
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;
848 for (unsigned int i = 0; i < bank->num_sectors; i++)
849 bank->sectors[i].is_protected = set;
851 return ERROR_OK;
855 static int numicro_erase(struct flash_bank *bank, unsigned int first,
856 unsigned int last)
858 struct target *target = bank->target;
859 uint32_t timeout, status;
860 int retval = ERROR_OK;
862 if (target->state != TARGET_HALTED) {
863 LOG_ERROR("Target not halted");
864 return ERROR_TARGET_NOT_HALTED;
867 LOG_INFO("Nuvoton NuMicro: Sector Erase ... (%u to %u)", first, last);
869 numicro_get_arm_arch(target);
870 retval = numicro_init_isp(target);
871 if (retval != ERROR_OK)
872 return retval;
874 retval = target_write_u32(target, NUMICRO_FLASH_ISPCMD - m_address_bias_offset, ISPCMD_ERASE);
875 if (retval != ERROR_OK)
876 return retval;
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;
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;
903 busy_sleep(1); /* can use busy sleep for short times. */
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;
919 /* done, */
920 LOG_DEBUG("Erase done.");
922 return ERROR_OK;
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)
929 struct target *target = bank->target;
930 uint32_t timeout, status;
931 int retval = ERROR_OK;
933 if (target->state != TARGET_HALTED) {
934 LOG_ERROR("Target not halted");
935 return ERROR_TARGET_NOT_HALTED;
938 LOG_INFO("Nuvoton NuMicro: Flash Write ...");
940 numicro_get_arm_arch(target);
941 retval = numicro_init_isp(target);
942 if (retval != ERROR_OK)
943 return retval;
945 retval = target_write_u32(target, NUMICRO_FLASH_ISPCMD - m_address_bias_offset, ISPCMD_WRITE);
946 if (retval != ERROR_OK)
947 return retval;
949 assert(offset % 4 == 0);
950 assert(count % 4 == 0);
952 uint32_t words_remaining = count / 4;
954 /* try using a block write */
955 retval = numicro_writeblock(bank, buffer, offset, words_remaining);
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");
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));
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;
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;
999 busy_sleep(1); /* can use busy sleep for short times. */
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");
1021 /* done. */
1022 LOG_DEBUG("Write done.");
1024 return ERROR_OK;
1027 static int numicro_get_cpu_type(struct target *target, const struct numicro_cpu_type **cpu)
1029 uint32_t part_id;
1030 int retval = ERROR_OK;
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;
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;
1050 return ERROR_FAIL;
1053 static int numicro_get_flash_size(struct flash_bank *bank, const struct numicro_cpu_type *cpu, uint32_t *flash_size)
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;
1063 return ERROR_FLASH_OPERATION_FAILED;
1066 static int numicro_probe(struct flash_bank *bank)
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;
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;
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;
1086 num_pages = flash_size / m_page_size;
1088 bank->num_sectors = num_pages;
1089 bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
1090 bank->size = flash_size;
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;
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 ...");
1105 return ERROR_OK;
1108 /* Standard approach to autoprobing. */
1109 static int numicro_auto_probe(struct flash_bank *bank)
1111 struct numicro_flash_bank *numicro_info = bank->driver_priv;
1112 if (numicro_info->probed)
1113 return ERROR_OK;
1114 return numicro_probe(bank);
1118 /* This is the function called in the config file. */
1119 FLASH_BANK_COMMAND_HANDLER(numicro_flash_bank_command)
1121 struct numicro_flash_bank *bank_info;
1123 if (CMD_ARGC < 6)
1124 return ERROR_COMMAND_SYNTAX_ERROR;
1126 LOG_DEBUG("add flash_bank numicro %s", bank->name);
1128 bank_info = malloc(sizeof(struct numicro_flash_bank));
1130 memset(bank_info, 0, sizeof(struct numicro_flash_bank));
1132 bank->driver_priv = bank_info;
1133 bank->write_start_alignment = bank->write_end_alignment = 4;
1135 return ERROR_OK;
1138 COMMAND_HANDLER(numicro_handle_read_isp_command)
1140 uint32_t address;
1141 uint32_t ispdat;
1142 int retval = ERROR_OK;
1144 if (CMD_ARGC != 1)
1145 return ERROR_COMMAND_SYNTAX_ERROR;
1147 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
1149 struct target *target = get_current_target(CMD_CTX);
1151 numicro_get_arm_arch(target);
1152 retval = numicro_init_isp(target);
1153 if (retval != ERROR_OK)
1154 return retval;
1156 retval = numicro_fmc_cmd(target, ISPCMD_READ, address, 0, &ispdat);
1157 if (retval != ERROR_OK)
1158 return retval;
1160 LOG_INFO("0x%08" PRIx32 ": 0x%08" PRIx32, address, ispdat);
1162 return ERROR_OK;
1165 COMMAND_HANDLER(numicro_handle_write_isp_command)
1167 uint32_t address;
1168 uint32_t ispdat, rdat;
1169 int retval = ERROR_OK;
1171 if (CMD_ARGC != 2)
1172 return ERROR_COMMAND_SYNTAX_ERROR;
1174 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
1175 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], ispdat);
1177 struct target *target = get_current_target(CMD_CTX);
1179 numicro_get_arm_arch(target);
1180 retval = numicro_init_isp(target);
1181 if (retval != ERROR_OK)
1182 return retval;
1184 retval = numicro_fmc_cmd(target, ISPCMD_WRITE, address, ispdat, &rdat);
1185 if (retval != ERROR_OK)
1186 return retval;
1188 LOG_INFO("0x%08" PRIx32 ": 0x%08" PRIx32, address, ispdat);
1189 return ERROR_OK;
1192 COMMAND_HANDLER(numicro_handle_chip_erase_command)
1194 int retval = ERROR_OK;
1195 uint32_t rdat;
1197 if (CMD_ARGC != 0)
1198 return ERROR_COMMAND_SYNTAX_ERROR;
1200 struct target *target = get_current_target(CMD_CTX);
1202 numicro_get_arm_arch(target);
1203 retval = numicro_init_isp(target);
1204 if (retval != ERROR_OK)
1205 return retval;
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;
1213 command_print(CMD, "numicro chip_erase complete");
1215 return ERROR_OK;
1218 static const struct command_registration numicro_exec_command_handlers[] = {
1220 .name = "read_isp",
1221 .handler = numicro_handle_read_isp_command,
1222 .usage = "address",
1223 .mode = COMMAND_EXEC,
1224 .help = "read flash through ISP.",
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.",
1234 .name = "chip_erase",
1235 .handler = numicro_handle_chip_erase_command,
1236 .mode = COMMAND_EXEC,
1237 .help = "chip erase through ISP.",
1238 .usage = "",
1240 COMMAND_REGISTRATION_DONE
1243 static const struct command_registration numicro_command_handlers[] = {
1245 .name = "numicro",
1246 .mode = COMMAND_ANY,
1247 .help = "numicro flash command group",
1248 .usage = "",
1249 .chain = numicro_exec_command_handlers,
1251 COMMAND_REGISTRATION_DONE
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,