flash: Analog Devices ADuCM360 support
[openocd.git] / src / flash / nor / nuc1x.c
blob3f39a05eed129a3e61dc2629d0d254580d322a15
1 /***************************************************************************
2 * Copyright (C) 2011 by James K. Larson *
3 * jlarson@pacifier.com *
4 * *
5 * Copyright (C) 2013 Nemui Trinomius *
6 * nemuisan_kawausogasuki@live.jp *
7 * *
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. *
12 * *
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. *
17 * *
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 ***************************************************************************/
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
28 #include "imp.h"
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)
64 /* isp commands */
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 */
73 #define KEY1 0x59
74 #define KEY2 0x16
75 #define KEY3 0x88
76 #define LOCK 0x00
78 /* part structs */
79 static const struct {
80 const char *partname;
81 uint32_t partno;
82 uint16_t num_page;
84 NuMicroParts[] = {
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)
165 return retval;
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)
172 return retval;
173 retval = target_write_u32(target, NUC1X_SYS_WRPROT, KEY2);
174 if (retval != ERROR_OK)
175 return retval;
176 retval = target_write_u32(target, NUC1X_SYS_WRPROT, KEY3);
177 if (retval != ERROR_OK)
178 return retval;
180 /* Check that unlock worked */
181 retval = target_read_u32(target, NUC1X_SYS_WRPROT, &is_protected);
182 if (retval != ERROR_OK)
183 return retval;
185 if (is_protected == 1) { /* means unprotected */
186 LOG_DEBUG("protection removed");
187 } else {
188 LOG_DEBUG("still protected!!");
191 return ERROR_OK;
194 static int nuc1x_reset(struct flash_bank *bank)
196 struct target *target = bank->target;
198 nuc1x_unlock(bank);
200 int retval = target_write_u32(target, NUC1X_SYS_IPRSTC1, IPRSTC1_CPU_RST);
201 if (retval != ERROR_OK)
202 return retval;
204 return ERROR_OK;
207 static int nuc1x_reset2lprom(struct flash_bank *bank)
209 struct target *target = bank->target;
211 nuc1x_unlock(bank);
212 int retval = target_write_u32(target, NUC1X_FLASH_ISPCON, ISPCON_BS_LP);
213 if (retval != ERROR_OK)
214 return retval;
216 nuc1x_reset(bank);
218 return 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)
232 return retval;
234 /* enable isp clock and ispen bit */
235 retval = target_write_u32(target, NUC1X_SYSCLK_AHBCLK, AHBCLK_ISP_EN);
236 if (retval != ERROR_OK)
237 return retval;
239 retval = target_write_u32(target, NUC1X_FLASH_ISPCON, ISPCON_ISPFF | ISPCON_LDUEN | ISPCON_CFGUEN | ISPCON_ISPEN);
240 if (retval != ERROR_OK)
241 return retval;
243 return ERROR_OK;
246 /* Private bank information for nuc1x. */
247 struct nuc1x_flash_bank {
248 struct working_area *write_algorithm;
249 int probed;
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;
257 if (CMD_ARGC < 6)
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;
268 return ERROR_OK;
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;
277 int i;
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)
287 return retval;
289 LOG_INFO("is_protected = 0x%08" PRIx32 "", is_protected);
290 if (is_protected == 0) { /* means protected */
291 set = 1;
292 } else {
293 set = 0;
295 for (i = 0; i < bank->num_sectors; i++)
296 bank->sectors[i].is_protected = set;
298 return ERROR_OK;
301 static int nuc1x_erase(struct flash_bank *bank, int first, int last)
303 struct target *target = bank->target;
304 uint32_t timeout, status;
305 int i;
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)
316 return retval;
318 retval = nuc1x_init_iap(bank);
319 if (retval != ERROR_OK)
320 return retval;
322 retval = nuc1x_unlock(bank);
323 if (retval != ERROR_OK)
324 return retval;
326 retval = target_write_u32(target, NUC1X_FLASH_ISPCMD, ISPCMD_ERASE);
327 if (retval != ERROR_OK)
328 return retval;
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)
334 return retval;
335 retval = target_write_u32(target, NUC1X_FLASH_ISPTRG, ISPTRG_ISPGO); /* This is the only bit available */
336 if (retval != ERROR_OK)
337 return retval;
339 /* wait for busy to clear - check the GO flag */
340 timeout = 100;
341 for (;;) {
342 retval = target_read_u32(target, NUC1X_FLASH_ISPTRG, &status);
343 if (retval != ERROR_OK)
344 return retval;
345 LOG_DEBUG("status: 0x%" PRIx32 "", status);
346 if (status == 0)
347 break;
348 if (timeout-- <= 0) {
349 LOG_DEBUG("timed out waiting for flash");
350 return ERROR_FAIL;
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)
358 return retval;
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)
364 return retval;
365 } else {
366 bank->sectors[i].is_erased = 1;
370 retval = nuc1x_reset(bank);
371 if (retval != ERROR_OK)
372 return retval;
374 /* done, */
375 LOG_DEBUG("Erase done.");
377 return ERROR_OK;
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)
396 return retval;
398 retval = nuc1x_init_iap(bank);
399 if (retval != ERROR_OK)
400 return retval;
402 retval = nuc1x_unlock(bank);
403 if (retval != ERROR_OK)
404 return retval;
406 retval = target_write_u32(target, NUC1X_FLASH_ISPCMD, ISPCMD_WRITE);
407 if (retval != ERROR_OK)
408 return retval;
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)
420 return retval;
421 retval = target_write_memory(target, NUC1X_FLASH_ISPDAT, 4, 1, padding);
422 if (retval != ERROR_OK)
423 return retval;
424 retval = target_write_u32(target, NUC1X_FLASH_ISPTRG, ISPTRG_ISPGO);
425 if (retval != ERROR_OK)
426 return retval;
428 /* wait for busy to clear - check the GO flag */
429 timeout = 100;
430 for (;;) {
431 retval = target_read_u32(target, NUC1X_FLASH_ISPTRG, &status);
432 if (retval != ERROR_OK)
433 return retval;
434 LOG_DEBUG("status: 0x%" PRIx32 "", status);
435 if (status == 0)
436 break;
437 if (timeout-- <= 0) {
438 LOG_DEBUG("timed out waiting for flash");
439 return ERROR_FAIL;
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)
447 return retval;
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)
453 return retval;
454 } else {
455 LOG_DEBUG("Write OK");
459 retval = nuc1x_reset(bank);
460 if (retval != ERROR_OK)
461 return retval;
463 /* done, */
464 LOG_DEBUG("Write done.");
466 return ERROR_OK;
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;
474 int i;
475 uint16_t num_pages;
476 uint32_t device_id;
477 int page_size;
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)
485 return retval;
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;
493 break;
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)));
499 } else {
500 LOG_INFO("No NUC Device Detected...");
501 return ERROR_FAIL;
504 if (bank->sectors) {
505 free(bank->sectors);
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 ...");
525 return ERROR_OK;
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)
533 return ERROR_OK;
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)
546 return retval;
548 /* search part numbers */
549 for (i = 0; NuMicroParts[i].partno; i++) {
550 if (NuMicroParts[i].partno == (device_id & 0x0FFFFFFF))
551 break;
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)));
556 } else {
557 LOG_INFO("No NUC Device Detected...");
558 return ERROR_FAIL;
561 return ERROR_OK;
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
566 * commands. */
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)");
579 return retval;
582 COMMAND_HANDLER(nuc1x_handle_mass_erase_command)
584 int i; /* for erasing sectors */
585 if (CMD_ARGC < 1) {
586 command_print(CMD_CTX, "nuc1x mass_erase <bank>");
587 return ERROR_OK;
590 struct flash_bank *bank;
591 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
592 if (ERROR_OK != retval)
593 return 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");
602 } else
603 command_print(CMD_CTX, "nuc1x mass erase failed");
605 return retval;
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,
613 .usage = "bank_id",
614 .help = "Erase entire Flash device.",
616 COMMAND_REGISTRATION_DONE
619 static const struct command_registration nuc1x_command_handlers[] = {
621 .name = "nuc1x",
622 .mode = COMMAND_ANY,
623 .help = "nuc1x Flash command group",
624 .chain = nuc1x_exec_command_handlers,
626 COMMAND_REGISTRATION_DONE
628 struct flash_driver nuc1x_flash = {
629 .name = "nuc1x",
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,