1 /***************************************************************************
2 * Copyright (C) 2011 by James K. Larson *
3 * jlarson@pacifier.com *
5 * Copyright (C) 2013 Nemui Trinomius *
6 * nemuisan_kawausogasuki@live.jp *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
22 ***************************************************************************/
30 /* nuc1x register locations */
31 #define NUC1X_SYS_BASE 0x50000000
32 #define NUC1X_SYS_WRPROT 0x50000100
33 #define NUC1X_SYS_IPRSTC1 0x50000008
35 #define NUC1X_SYSCLK_BASE 0x50000200
36 #define NUC1X_SYSCLK_PWRCON 0x50000200
37 #define NUC1X_SYSCLK_CLKSEL0 0x50000210
38 #define NUC1X_SYSCLK_CLKDIV 0x50000218
39 #define NUC1X_SYSCLK_AHBCLK 0x50000204
41 #define NUC1X_FLASH_BASE 0x5000C000
42 #define NUC1X_FLASH_ISPCON 0x5000C000
43 #define NUC1X_FLASH_ISPCMD 0x5000C00C
44 #define NUC1X_FLASH_ISPADR 0x5000C004
45 #define NUC1X_FLASH_ISPDAT 0x5000C008
46 #define NUC1X_FLASH_ISPTRG 0x5000C010
48 /* Command register bits */
49 #define PWRCON_OSC22M (1 << 2)
50 #define PWRCON_XTL12M (1 << 0)
52 #define IPRSTC1_CPU_RST (1<<1)
53 #define IPRSTC1_CHIP_RST (1<<0)
55 #define AHBCLK_ISP_EN (1 << 2)
57 #define ISPCON_ISPEN (1 << 0)
58 #define ISPCON_BS_AP (0 << 1)
59 #define ISPCON_BS_LP (1 << 1)
60 #define ISPCON_CFGUEN (1 << 4)
61 #define ISPCON_LDUEN (1 << 5)
62 #define ISPCON_ISPFF (1 << 6)
65 #define ISPCMD_FCTRL (0x2)
66 #define ISPCMD_FCEN (1 << 4)
67 #define ISPCMD_FOEN (1 << 5)
68 #define ISPCMD_ERASE (0x2 | ISPCMD_FOEN)
69 #define ISPCMD_WRITE (0x1 | ISPCMD_FOEN)
70 #define ISPTRG_ISPGO (1 << 0)
72 /* access unlock keys */
85 /*PART NO*/ /*PART ID*/ /*NUM PAGE*/
86 {"NUC100LC1", 0x00010008, 64},
87 {"NUC100LD1", 0x00010005, 128},
88 {"NUC100LD2", 0x00010004, 128},
89 {"NUC100RC1", 0x00010017, 64},
90 {"NUC100RD1", 0x00010014, 128},
91 {"NUC100RD2", 0x00010013, 128},
93 {"NUC100LD3", 0x00010003, 128},
94 {"NUC100LE3", 0x00010000, 256},
95 {"NUC100RD3", 0x00010012, 128},
96 {"NUC100RE3", 0x00010009, 256},
97 {"NUC100VD2", 0x00010022, 128},
98 {"NUC100VD3", 0x00010021, 128},
99 {"NUC100VE3", 0x00010018, 256},
101 {"NUC120LC1", 0x00012008, 64},
102 {"NUC120LD1", 0x00012005, 128},
103 {"NUC120LD2", 0x00012004, 128},
104 {"NUC120RC1", 0x00012017, 64},
105 {"NUC120RD1", 0x00012014, 128},
106 {"NUC120RD2", 0x00012013, 128},
108 {"NUC120LD3", 0x00012003, 128},
109 {"NUC120LE3", 0x00012000, 256},
110 {"NUC120RD3", 0x00012012, 128},
111 {"NUC120RE3", 0x00012009, 256},
112 {"NUC120VD2", 0x00012022, 128},
113 {"NUC120VD3", 0x00012021, 128},
114 {"NUC120VE3", 0x00012018, 256},
116 {"NUC122ZD2", 0x00012231, 128},
117 {"NUC122ZC1", 0x00012235, 64},
118 {"NUC122LD2", 0x00012204, 128},
119 {"NUC122LC1", 0x00012208, 64},
120 {"NUC122RD2", 0x00012213, 128},
121 {"NUC122RC1", 0x00012217, 64},
123 {"NUC123ZD4", 0x00012255, 136},
124 {"NUC123ZC2", 0x00012245, 68},
125 {"NUC123LD4", 0x00012235, 136},
126 {"NUC123LC2", 0x00012225, 68},
127 {"NUC123SD4", 0x00012215, 136},
128 {"NUC123SC2", 0x00012205, 68},
130 {"NUC130LC1", 0x00013008, 64},
131 {"NUC130LD2", 0x00013004, 128},
132 {"NUC130LE3", 0x00013000, 256},
133 {"NUC130RC1", 0x00013017, 64},
134 {"NUC130RD2", 0x00013013, 128},
135 {"NUC130RE3", 0x00013009, 256},
136 {"NUC130VE3", 0x00013018, 256},
138 {"M052L", 0x00005200, 16},
139 {"M052Z", 0x00005203, 16},
140 {"M054L", 0x00005400, 32},
141 {"M054Z", 0x00005403, 32},
142 {"M058L", 0x00005800, 64},
143 {"M058Z", 0x00005803, 64},
144 {"M0516L", 0x00005A00, 128},
145 {"M0516Z", 0x00005A03, 128},
147 {"MINI51L", 0x00205100, 8},
148 {"MINI51Z", 0x00205103, 8},
149 {"MINI52L", 0x00205200, 16},
150 {"MINI52Z", 0x00205203, 16},
151 {"MINI54L", 0x00205400, 32},
152 {"MINI54Z", 0x00205403, 32},
154 {"UNKNOWN", 0x00000000, 256},
157 static int nuc1x_unlock(struct flash_bank
*bank
)
159 uint32_t is_protected
;
160 struct target
*target
= bank
->target
;
162 /* Check to see if Nuc is unlocked or not */
163 int retval
= target_read_u32(target
, NUC1X_SYS_WRPROT
, &is_protected
);
164 if (retval
!= ERROR_OK
)
167 LOG_DEBUG("protected = 0x%08" PRIx32
"", is_protected
);
168 if (is_protected
== 0) { /* means protected - so unlock it */
169 /* unlock flash registers */
170 retval
= target_write_u32(target
, NUC1X_SYS_WRPROT
, KEY1
);
171 if (retval
!= ERROR_OK
)
173 retval
= target_write_u32(target
, NUC1X_SYS_WRPROT
, KEY2
);
174 if (retval
!= ERROR_OK
)
176 retval
= target_write_u32(target
, NUC1X_SYS_WRPROT
, KEY3
);
177 if (retval
!= ERROR_OK
)
180 /* Check that unlock worked */
181 retval
= target_read_u32(target
, NUC1X_SYS_WRPROT
, &is_protected
);
182 if (retval
!= ERROR_OK
)
185 if (is_protected
== 1) { /* means unprotected */
186 LOG_DEBUG("protection removed");
188 LOG_DEBUG("still protected!!");
194 static int nuc1x_reset(struct flash_bank
*bank
)
196 struct target
*target
= bank
->target
;
200 int retval
= target_write_u32(target
, NUC1X_SYS_IPRSTC1
, IPRSTC1_CPU_RST
);
201 if (retval
!= ERROR_OK
)
207 static int nuc1x_reset2lprom(struct flash_bank
*bank
)
209 struct target
*target
= bank
->target
;
212 int retval
= target_write_u32(target
, NUC1X_FLASH_ISPCON
, ISPCON_BS_LP
);
213 if (retval
!= ERROR_OK
)
221 static int nuc1x_init_iap(struct flash_bank
*bank
)
223 struct target
*target
= bank
->target
;
225 if (target
->state
!= TARGET_HALTED
) {
226 LOG_ERROR("Target not halted");
227 return ERROR_TARGET_NOT_HALTED
;
230 int retval
= nuc1x_unlock(bank
);
231 if (retval
!= ERROR_OK
)
234 /* enable isp clock and ispen bit */
235 retval
= target_write_u32(target
, NUC1X_SYSCLK_AHBCLK
, AHBCLK_ISP_EN
);
236 if (retval
!= ERROR_OK
)
239 retval
= target_write_u32(target
, NUC1X_FLASH_ISPCON
, ISPCON_ISPFF
| ISPCON_LDUEN
| ISPCON_CFGUEN
| ISPCON_ISPEN
);
240 if (retval
!= ERROR_OK
)
246 /* Private bank information for nuc1x. */
247 struct nuc1x_flash_bank
{
248 struct working_area
*write_algorithm
;
252 /* This is the function called in the config file. */
253 FLASH_BANK_COMMAND_HANDLER(nuc1x_flash_bank_command
)
255 struct nuc1x_flash_bank
*bank_info
;
258 return ERROR_COMMAND_SYNTAX_ERROR
;
260 LOG_INFO("add flash_bank nuc1x %s", bank
->name
);
262 bank_info
= malloc(sizeof(struct nuc1x_flash_bank
));
264 memset(bank_info
, 0, sizeof(struct nuc1x_flash_bank
));
266 bank
->driver_priv
= bank_info
;
272 /* Protection checking - examines the lock bit. */
273 static int nuc1x_protect_check(struct flash_bank
*bank
)
275 uint32_t is_protected
, set
;
276 struct target
*target
= bank
->target
;
279 if (target
->state
!= TARGET_HALTED
) {
280 LOG_ERROR("Target not halted");
281 return ERROR_TARGET_NOT_HALTED
;
284 /* Check to see if Nuc is unlocked or not */
285 int retval
= target_read_u32(target
, NUC1X_SYS_WRPROT
, &is_protected
);
286 if (retval
!= ERROR_OK
)
289 LOG_INFO("is_protected = 0x%08" PRIx32
"", is_protected
);
290 if (is_protected
== 0) { /* means protected */
295 for (i
= 0; i
< bank
->num_sectors
; i
++)
296 bank
->sectors
[i
].is_protected
= set
;
301 static int nuc1x_erase(struct flash_bank
*bank
, int first
, int last
)
303 struct target
*target
= bank
->target
;
304 uint32_t timeout
, status
;
307 if (bank
->target
->state
!= TARGET_HALTED
) {
308 LOG_ERROR("Target not halted");
309 return ERROR_TARGET_NOT_HALTED
;
312 LOG_INFO("Nuvoton NUC: Sector Erase ... (%d to %d)", first
, last
);
314 int retval
= nuc1x_reset2lprom(bank
);
315 if (retval
!= ERROR_OK
)
318 retval
= nuc1x_init_iap(bank
);
319 if (retval
!= ERROR_OK
)
322 retval
= nuc1x_unlock(bank
);
323 if (retval
!= ERROR_OK
)
326 retval
= target_write_u32(target
, NUC1X_FLASH_ISPCMD
, ISPCMD_ERASE
);
327 if (retval
!= ERROR_OK
)
330 for (i
= first
; i
<= last
; i
++) {
331 LOG_DEBUG("erasing sector %d at address 0x%" PRIx32
"", i
, bank
->base
+ bank
->sectors
[i
].offset
);
332 retval
= target_write_u32(target
, NUC1X_FLASH_ISPADR
, bank
->base
+ bank
->sectors
[i
].offset
);
333 if (retval
!= ERROR_OK
)
335 retval
= target_write_u32(target
, NUC1X_FLASH_ISPTRG
, ISPTRG_ISPGO
); /* This is the only bit available */
336 if (retval
!= ERROR_OK
)
339 /* wait for busy to clear - check the GO flag */
342 retval
= target_read_u32(target
, NUC1X_FLASH_ISPTRG
, &status
);
343 if (retval
!= ERROR_OK
)
345 LOG_DEBUG("status: 0x%" PRIx32
"", status
);
348 if (timeout
-- <= 0) {
349 LOG_DEBUG("timed out waiting for flash");
352 busy_sleep(1); /* can use busy sleep for short times. */
355 /* check for failure */
356 retval
= target_read_u32(target
, NUC1X_FLASH_ISPCON
, &status
);
357 if (retval
!= ERROR_OK
)
359 if ((status
& ISPCON_ISPFF
) != 0) {
360 LOG_DEBUG("failure: 0x%" PRIx32
"", status
);
361 /* if bit is set, then must write to it to clear it. */
362 retval
= target_write_u32(target
, NUC1X_FLASH_ISPCON
, ISPCON_ISPFF
);
363 if (retval
!= ERROR_OK
)
366 bank
->sectors
[i
].is_erased
= 1;
370 retval
= nuc1x_reset(bank
);
371 if (retval
!= ERROR_OK
)
375 LOG_DEBUG("Erase done.");
380 /* The write routine stub. */
381 static int nuc1x_write(struct flash_bank
*bank
, const uint8_t *buffer
,
382 uint32_t offset
, uint32_t count
)
384 struct target
*target
= bank
->target
;
385 uint32_t i
, timeout
, status
;
387 if (bank
->target
->state
!= TARGET_HALTED
) {
388 LOG_ERROR("Target not halted");
389 return ERROR_TARGET_NOT_HALTED
;
392 LOG_INFO("Nuvoton NUC: FLASH Write ...");
394 int retval
= nuc1x_reset2lprom(bank
);
395 if (retval
!= ERROR_OK
)
398 retval
= nuc1x_init_iap(bank
);
399 if (retval
!= ERROR_OK
)
402 retval
= nuc1x_unlock(bank
);
403 if (retval
!= ERROR_OK
)
406 retval
= target_write_u32(target
, NUC1X_FLASH_ISPCMD
, ISPCMD_WRITE
);
407 if (retval
!= ERROR_OK
)
410 /* program command */
411 for (i
= 0; i
< count
; i
+= 4) {
413 LOG_DEBUG("write longword @ %08" PRIX32
, (uint32_t)(offset
+ i
));
415 uint8_t padding
[4] = {0xff, 0xff, 0xff, 0xff};
416 memcpy(padding
, buffer
+ i
, MIN(4, count
-i
));
418 retval
= target_write_u32(target
, NUC1X_FLASH_ISPADR
, bank
->base
+ offset
+ i
);
419 if (retval
!= ERROR_OK
)
421 retval
= target_write_memory(target
, NUC1X_FLASH_ISPDAT
, 4, 1, padding
);
422 if (retval
!= ERROR_OK
)
424 retval
= target_write_u32(target
, NUC1X_FLASH_ISPTRG
, ISPTRG_ISPGO
);
425 if (retval
!= ERROR_OK
)
428 /* wait for busy to clear - check the GO flag */
431 retval
= target_read_u32(target
, NUC1X_FLASH_ISPTRG
, &status
);
432 if (retval
!= ERROR_OK
)
434 LOG_DEBUG("status: 0x%" PRIx32
"", status
);
437 if (timeout
-- <= 0) {
438 LOG_DEBUG("timed out waiting for flash");
441 busy_sleep(1); /* can use busy sleep for short times. */
444 /* check for failure */
445 retval
= target_read_u32(target
, NUC1X_FLASH_ISPCON
, &status
);
446 if (retval
!= ERROR_OK
)
448 if ((status
& ISPCON_ISPFF
) != 0) {
449 LOG_DEBUG("failure: 0x%" PRIx32
"", status
);
450 /* if bit is set, then must write to it to clear it. */
451 retval
= target_write_u32(target
, NUC1X_FLASH_ISPCON
, ISPCON_ISPFF
);
452 if (retval
!= ERROR_OK
)
455 LOG_DEBUG("Write OK");
459 retval
= nuc1x_reset(bank
);
460 if (retval
!= ERROR_OK
)
464 LOG_DEBUG("Write done.");
469 /* The probe routine for the nuc. Only recognizes the nuc120 right now. */
470 static int nuc1x_probe(struct flash_bank
*bank
)
472 struct target
*target
= bank
->target
;
473 struct nuc1x_flash_bank
*nuc1x_info
= bank
->driver_priv
;
478 uint32_t base_address
= 0x00000000;
480 nuc1x_info
->probed
= 0;
482 /* read nuc1x device id register */
483 int retval
= target_read_u32(target
, 0x50000000, &device_id
);
484 if (retval
!= ERROR_OK
)
487 page_size
= 512; /* all nuc parts has 512 byte per sector */
489 /* search part numbers */
490 for (i
= 0; NuMicroParts
[i
].partno
; i
++) {
491 if (NuMicroParts
[i
].partno
== (device_id
& 0x0FFFFFFF)) {
492 num_pages
= NuMicroParts
[i
].num_page
;
496 if (!(NuMicroParts
[i
].partno
== 0x00000000)) {
497 LOG_INFO("DeviceID : 0x%08" PRIx32
"", device_id
);
498 LOG_INFO("Detect %s%cN!", NuMicroParts
[i
].partname
, (char)('A'+(device_id
>>28)));
500 LOG_INFO("No NUC Device Detected...");
506 bank
->sectors
= NULL
;
509 bank
->base
= base_address
;
510 bank
->size
= (num_pages
* page_size
);
511 bank
->num_sectors
= num_pages
;
512 bank
->sectors
= malloc(sizeof(struct flash_sector
) * num_pages
);
514 for (i
= 0; i
< num_pages
; i
++) {
515 bank
->sectors
[i
].offset
= i
* page_size
;
516 bank
->sectors
[i
].size
= page_size
;
517 bank
->sectors
[i
].is_erased
= -1;
518 bank
->sectors
[i
].is_protected
= 1;
521 nuc1x_info
->probed
= 1;
523 LOG_DEBUG("Nuvoton NUC: Probed ...");
528 /* Standard approach to autoprobing. */
529 static int nuc1x_auto_probe(struct flash_bank
*bank
)
531 struct nuc1x_flash_bank
*nuc1x_info
= bank
->driver_priv
;
532 if (nuc1x_info
->probed
)
534 return nuc1x_probe(bank
);
537 /* Info doesn't really add much, but works correctly. */
538 static int get_nuc1x_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
540 struct target
*target
= bank
->target
;
541 uint32_t i
, device_id
;
543 /* read nuc1x device id register */
544 int retval
= target_read_u32(target
, 0x50000000, &device_id
);
545 if (retval
!= ERROR_OK
)
548 /* search part numbers */
549 for (i
= 0; NuMicroParts
[i
].partno
; i
++) {
550 if (NuMicroParts
[i
].partno
== (device_id
& 0x0FFFFFFF))
553 if (!(NuMicroParts
[i
].partno
== 0x00000000)) {
554 LOG_INFO("DeviceID : 0x%08" PRIx32
"", device_id
);
555 LOG_INFO("Detect %s%cN!", NuMicroParts
[i
].partname
, (char)('A'+(device_id
>>28)));
557 LOG_INFO("No NUC Device Detected...");
564 /* The nuc120 doesn't support mass erase, so this will probably be removed soon.
565 * The structure is left for now until I am sure I don't want to add any custom
567 static int nuc1x_mass_erase(struct flash_bank
*bank
)
569 struct target
*target
= bank
->target
;
570 int retval
= ERROR_OK
;
572 if (target
->state
!= TARGET_HALTED
) {
573 LOG_ERROR("Target not halted");
574 return ERROR_TARGET_NOT_HALTED
;
577 LOG_INFO("Nuvoton NUC: Chip Erase ... (may take several seconds)");
582 COMMAND_HANDLER(nuc1x_handle_mass_erase_command
)
584 int i
; /* for erasing sectors */
586 command_print(CMD_CTX
, "nuc1x mass_erase <bank>");
590 struct flash_bank
*bank
;
591 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
592 if (ERROR_OK
!= retval
)
595 retval
= nuc1x_mass_erase(bank
);
596 if (retval
== ERROR_OK
) {
597 /* set all sectors as erased */
598 for (i
= 0; i
< bank
->num_sectors
; i
++)
599 bank
->sectors
[i
].is_erased
= 1;
601 command_print(CMD_CTX
, "nuc1x mass erase complete");
603 command_print(CMD_CTX
, "nuc1x mass erase failed");
608 static const struct command_registration nuc1x_exec_command_handlers
[] = {
610 .name
= "mass_erase",
611 .handler
= nuc1x_handle_mass_erase_command
,
612 .mode
= COMMAND_EXEC
,
614 .help
= "Erase entire Flash device.",
616 COMMAND_REGISTRATION_DONE
619 static const struct command_registration nuc1x_command_handlers
[] = {
623 .help
= "nuc1x Flash command group",
624 .chain
= nuc1x_exec_command_handlers
,
626 COMMAND_REGISTRATION_DONE
628 struct flash_driver nuc1x_flash
= {
630 .commands
= nuc1x_command_handlers
,
631 .flash_bank_command
= nuc1x_flash_bank_command
,
632 .erase
= nuc1x_erase
,
633 .write
= nuc1x_write
,
634 .read
= default_flash_read
,
635 .probe
= nuc1x_probe
,
636 .auto_probe
= nuc1x_auto_probe
,
637 .erase_check
= default_flash_blank_check
,
638 .protect_check
= nuc1x_protect_check
,
639 .info
= get_nuc1x_info
,