flash : Add support for Atmel at91sam4sa16b
[fw/openocd] / src / flash / nor / mini51.c
1 /***************************************************************************
2  *   Copyright (C) 2013 Cosmin Gorgovan                                    *
3  *   cosmin [at] linux-geek [dot] org                                      *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
19  ***************************************************************************/
20
21 /*
22         Flash driver for the Nuvoton NuMicro Mini51 and M051 series microcontrollers
23
24         Part             |APROM Size |Part ID (at 0x5000_0000)
25         ----------------------------------------------
26         MINI51LAN        4 KB                   0x00205100
27         MINI51ZAN        4 KB                   0x00205103
28         MINI51TAN        4 KB                   0x00205104
29         MINI52LAN        8 KB                   0x00205200
30         MINI52ZAN        8 KB                   0x00205203
31         MINI52TAN        8 KB                   0x00205204
32         MINI54LAN        16 KB           0x00205400
33         MINI54ZAN        16 KB           0x00205403
34         MINI54TAN        16 KB           0x00205404
35         M052LBN           8 KB           0x10005200
36         M054LBN          16 KB           0x10005400
37         M058LBN          32 KB           0x10005800
38         M0516LBN         64 KB           0x10005A00
39         M052ZBN           8 KB           0x10005203
40         M054ZBN          16 KB           0x10005403
41         M058ZBN          32 KB           0x10005803
42         M0516ZBN         64 KB           0x10005A03
43         M052LDN           8 KB           0x20005200
44         M054LDN          16 KB           0x20005400
45         M058LDN          32 KB           0x20005800
46         M0516LDN         64 KB           0x20005A00
47         M052ZDN           8 KB           0x20005203
48         M054ZDN          16 KB           0x20005403
49         M058ZDN          32 KB           0x20005803
50         M0516ZDN         64 KB           0x20005A03
51         M052LDE           8 KB           0x30005200
52         M054LDE          16 KB           0x30005400
53         M058LDE          32 KB           0x30005800
54         M0516LDE         64 KB           0x30005A00
55         M052ZDE           8 KB           0x30005203
56         M054ZDE          16 KB           0x30005403
57         M058ZDE          32 KB           0x30005803
58         M0516ZDE         64 KB           0x30005A03
59
60         Datasheet & TRM
61         ---------------
62
63         The ISP flash programming procedure is described on pages 130 and 131 of the (not very verbose) TRM.
64
65         http://www.keil.com/dd/docs/datashts/nuvoton/mini51/da00-mini51_52_54c1.pdf
66
67         M051 ISP datasheet pages 190-206:
68         http://www.nuvoton.com/hq/resource-download.jsp?tp_GUID=DA05-M052-54-58-516
69
70         This driver
71         -----------
72
73         * chip_erase, erase, read and write operations have been implemented;
74         * All operations support APROM, LDROM, FLASH DATA and CONFIG;
75
76         Flash access limitations
77         ------------------------
78
79         For implementing the read operation, please note that the APROM isn't memory mapped when booted from LDROM.
80 */
81
82 #ifdef HAVE_CONFIG_H
83 #include "config.h"
84 #endif
85
86 #include "imp.h"
87
88 #define PART_ID_REG     0x50000000
89 #define IPRSTC1         0x50000008
90 #define REGLOCKADDR     0x50000100
91 #define ISPCON          0x5000C000
92 #define ISPADR          0x5000C004
93 #define ISPDAT          0x5000C008
94 #define ISPCMD          0x5000C00C
95 #define ISPTRG          0x5000C010
96 /* Undocumented isp register */
97 #define ISPUNKNOWN      0x5000C01C
98
99 #define IPRSTC_CPU_RST      0x02
100
101 #define ISPCON_ISPFF        0x40
102 #define ISPCON_LDUEN        0x20
103 #define ISPCON_CFGUEN       0x10
104 #define ISPCON_APUEN        0x08
105 #define ISPCON_BS_LDROM     0x02
106 #define ISPCON_ISPEN        0x01
107
108 #define ISPCMD_READ         0x00
109 #define ISPCMD_PROGRAM      0x21
110 #define ISPCMD_ERASE        0x22
111 #define ISPCMD_CHIP_ERASE   0x26
112
113 #define ISPTRG_ISPGO        0x01
114
115 #define MINI51_APROM_BASE  0x00000000
116 #define MINI51_DATA_BASE   0x0001F000
117 #define MINI51_LDROM_BASE  0x00100000
118 #define MINI51_CONFIG_BASE 0x00300000
119
120 #define MINI51_KB          1024
121 #define MINI51_PAGE_SIZE   512
122 #define MINI51_TIMEOUT     1000
123
124
125 #define ENSURE_OK(status) if (status != ERROR_OK) return status
126
127 #define MINI51_MAX_FLASH_BANKS 4
128
129 struct mini51_flash_bank_type {
130         uint32_t base;
131         uint32_t size;
132 };
133
134 struct mini51_cpu_type {
135         char *name;
136         uint32_t ppid;
137         unsigned n_banks;
138         struct mini51_flash_bank_type bank[MINI51_MAX_FLASH_BANKS];
139 };
140
141 #define MINI51_BANKS_MINI51(aprom_size) \
142         .n_banks = 3, \
143         { {MINI51_APROM_BASE, (aprom_size)}, {MINI51_LDROM_BASE, 2*1024}, {MINI51_CONFIG_BASE, 512} }
144
145 #define MINI51_BANKS_M051(aprom_size) \
146         .n_banks = 4, \
147         { {MINI51_APROM_BASE, (aprom_size)}, {MINI51_DATA_BASE, 4*1024}, {MINI51_LDROM_BASE, 4*1024}, \
148         {MINI51_CONFIG_BASE, 1024} }
149
150 static const struct mini51_cpu_type mini51_cpu[] = {
151         { "MINI51LAN", 0x00205100, MINI51_BANKS_MINI51(4*1024) },
152         { "MINI51ZAN", 0x00205103, MINI51_BANKS_MINI51(4*1024) },
153         { "MINI51TAN", 0x00205104, MINI51_BANKS_MINI51(4*1024) },
154         { "MINI52LAN", 0x00205200, MINI51_BANKS_MINI51(8*1024) },
155         { "MINI52ZAN", 0x00205203, MINI51_BANKS_MINI51(8*1024) },
156         { "MINI52TAN", 0x00205204, MINI51_BANKS_MINI51(8*1024) },
157         { "MINI54LAN", 0x00205400, MINI51_BANKS_MINI51(16*1024) },
158         { "MINI54ZAN", 0x00205403, MINI51_BANKS_MINI51(16*1024) },
159         { "MINI54TAN", 0x00205404, MINI51_BANKS_MINI51(16*1024) },
160
161         { "M052LBN",   0x10005200, MINI51_BANKS_M051(8*1024) },
162         { "M054LBN",   0x10005400, MINI51_BANKS_M051(16*1024) },
163         { "M058LBN",   0x10005800, MINI51_BANKS_M051(32*1024) },
164         { "M0516LBN",  0x10005A00, MINI51_BANKS_M051(64*1024) },
165         { "M052ZBN",   0x10005203, MINI51_BANKS_M051(8*1024) },
166         { "M054ZBN",   0x10005403, MINI51_BANKS_M051(16*1024) },
167         { "M058ZBN",   0x10005803, MINI51_BANKS_M051(32*1024) },
168         { "M0516ZBN",  0x10005A03, MINI51_BANKS_M051(64*1024) },
169         { "M052LDN",   0x20005200, MINI51_BANKS_M051(8*1024) },
170         { "M054LDN",   0x20005400, MINI51_BANKS_M051(16*1024) },
171         { "M058LDN",   0x20005800, MINI51_BANKS_M051(32*1024) },
172         { "M0516LDN",  0x20005A00, MINI51_BANKS_M051(64*1024) },
173         { "M052ZDN",   0x20005203, MINI51_BANKS_M051(8*1024) },
174         { "M054ZDN",   0x20005403, MINI51_BANKS_M051(16*1024) },
175         { "M058ZDN",   0x20005803, MINI51_BANKS_M051(32*1024) },
176         { "M0516ZDN",  0x20005A03, MINI51_BANKS_M051(64*1024) },
177         { "M052LDE",   0x30005200, MINI51_BANKS_M051(8*1024) },
178         { "M054LDE",   0x30005400, MINI51_BANKS_M051(16*1024) },
179         { "M058LDE",   0x30005800, MINI51_BANKS_M051(32*1024) },
180         { "M0516LDE",  0x30005A00, MINI51_BANKS_M051(64*1024) },
181         { "M052ZDE",   0x30005203, MINI51_BANKS_M051(8*1024) },
182         { "M054ZDE",   0x30005403, MINI51_BANKS_M051(16*1024) },
183         { "M058ZDE",   0x30005803, MINI51_BANKS_M051(32*1024) },
184         { "M0516ZDE",  0x30005A03, MINI51_BANKS_M051(64*1024) },
185 };
186
187 struct mini51_flash_bank {
188         bool probed;
189         const struct mini51_cpu_type *cpu;
190 };
191
192 /* Private methods */
193
194 static int mini51_unlock_reg(struct target *target)
195 {
196         int status;
197         status = target_write_u32(target, REGLOCKADDR, 0x59);
198         if (status != ERROR_OK)
199                 return status;
200         status = target_write_u32(target, REGLOCKADDR, 0x16);
201         if (status != ERROR_OK)
202                 return status;
203         status = target_write_u32(target, REGLOCKADDR, 0x88);
204         if (status != ERROR_OK)
205                 return status;
206
207         return ERROR_OK;
208 }
209
210
211 static int mini51_get_part_id(struct target *target, uint32_t *part_id)
212 {
213         int retu = target_read_u32(target, PART_ID_REG, part_id);
214         LOG_INFO("device id = 0x%08" PRIx32 "", *part_id);
215         return retu;
216 }
217
218 static int mini51_get_cpu_type(struct target *target, const struct mini51_cpu_type** cpu)
219 {
220         uint32_t part_id;
221         int status;
222
223         status = mini51_get_part_id(target, &part_id);
224         ENSURE_OK(status);
225
226         for (size_t i = 0; i < sizeof(mini51_cpu)/sizeof(mini51_cpu[0]); i++) {
227                 if (part_id == mini51_cpu[i].ppid) {
228                         *cpu = &mini51_cpu[i];
229                         LOG_INFO("device name = %s", (*cpu)->name);
230                         return ERROR_OK;
231                 }
232         }
233
234         return ERROR_FLASH_OPERATION_FAILED;
235 }
236
237 static int mini51_get_flash_size(struct flash_bank *bank, const struct mini51_cpu_type *cpu, uint32_t *flash_size)
238 {
239         for (size_t i = 0; i < cpu->n_banks; i++) {
240                 if (bank->base == cpu->bank[i].base) {
241                         *flash_size = cpu->bank[i].size;
242                         LOG_INFO("bank base = 0x%08" PRIx32 ", size = 0x%08" PRIx32 "", bank->base, *flash_size);
243                         return ERROR_OK;
244                 }
245         }
246         return ERROR_FLASH_OPERATION_FAILED;
247 }
248
249 static int mini51_isp_execute(struct target *target)
250 {
251         int status;
252         uint32_t ispcon;
253         int timeout;
254         uint32_t isptrg;
255
256         /* start ISP operation */
257         status = target_write_u32(target, ISPTRG, ISPTRG_ISPGO);
258         ENSURE_OK(status);
259
260         /* Wait for for command to finish executing */
261         timeout = MINI51_TIMEOUT;
262         do {
263                 target_read_u32(target, ISPTRG, &isptrg);
264                 timeout--;
265         } while ((isptrg & ISPTRG_ISPGO) && (timeout > 0));
266         if (timeout == 0) {
267                 LOG_WARNING("Mini51 flash driver: Timeout executing flash command\n");
268                 return ERROR_FLASH_OPERATION_FAILED;
269         }
270
271         /* Check for errors */
272         status = target_read_u32(target, ISPCON, &ispcon);
273         ENSURE_OK(status);
274         if (ispcon & ISPCON_ISPFF) {
275                 LOG_WARNING("Mini51 flash driver: operation failed\n");
276                 return ERROR_FLASH_OPERATION_FAILED;
277         }
278         return status;
279 }
280
281 static int mini51_isp_execute_cmd(struct target *target, uint32_t cmd, uint32_t address, uint32_t data)
282 {
283         int status;
284         status = target_write_u32(target, ISPDAT, data);
285         ENSURE_OK(status);
286         status = target_write_u32(target, ISPADR, address);
287         ENSURE_OK(status);
288         status = target_write_u32(target, ISPCMD, cmd);
289         ENSURE_OK(status);
290
291         status = mini51_isp_execute(target);
292         return status;
293 }
294
295 static int mini51_isp_execute_cmd_read(struct target *target, uint32_t cmd, uint32_t address, uint32_t *data)
296 {
297         int status;
298         status = target_write_u32(target, ISPADR, address);
299         ENSURE_OK(status);
300         status = target_write_u32(target, ISPCMD, cmd);
301         ENSURE_OK(status);
302
303         status = mini51_isp_execute(target);
304         ENSURE_OK(status);
305
306         status = target_read_u32(target, ISPDAT, data);
307         ENSURE_OK(status);
308
309         return status;
310 }
311
312 static int mini51_isp_enable(struct target *target)
313 {
314         int status;
315         uint32_t ispcon;
316
317         if (target->state != TARGET_HALTED) {
318                 LOG_ERROR("Target not halted");
319                 return ERROR_TARGET_NOT_HALTED;
320         }
321
322         status = mini51_unlock_reg(target);
323         ENSURE_OK(status);
324         status = target_read_u32(target, ISPCON, &ispcon);
325         ENSURE_OK(status);
326         ispcon |= ISPCON_ISPEN | ISPCON_LDUEN | ISPCON_APUEN | ISPCON_CFGUEN;
327         status = target_write_u32(target, ISPCON, ispcon);
328         return status;
329 }
330
331 /* Public (API) methods */
332
333 FLASH_BANK_COMMAND_HANDLER(mini51_flash_bank_command)
334 {
335         struct mini51_flash_bank *mini51_info;
336         mini51_info = malloc(sizeof(struct mini51_flash_bank));
337         mini51_info->probed = false;
338         bank->driver_priv = mini51_info;
339
340         return ERROR_OK;
341 }
342
343 static int mini51_protect_check(struct flash_bank *bank)
344 {
345         LOG_WARNING("Mini51 flash driver: protect_check not implemented yet\n");
346
347         return ERROR_FLASH_OPERATION_FAILED;
348 }
349
350 static int mini51_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
351 {
352         int status;
353         uint32_t ispdat;
354         struct target *target = bank->target;
355
356         if ((offset & 0x3) || (count & 0x3)) {
357                 LOG_WARNING("Mini51 flash driver: unaligned access not supported\n");
358                 return ERROR_FLASH_OPERATION_FAILED;
359         }
360
361         status = mini51_isp_enable(target);
362         ENSURE_OK(status);
363
364         for (uint32_t i = offset; i < offset + count; i += 4) {
365                 status = mini51_isp_execute_cmd_read(target, ISPCMD_READ, bank->base + i, &ispdat);
366                 memcpy(buffer, &ispdat, sizeof(ispdat));
367                 ENSURE_OK(status);
368                 buffer += sizeof(ispdat);
369         }
370
371         return ERROR_OK;
372 }
373
374
375 static int mini51_erase(struct flash_bank *bank, int first, int last)
376 {
377         int status;
378         struct target *target = bank->target;
379
380         /* Enable ISP */
381         status = mini51_isp_enable(target);
382         ENSURE_OK(status);
383
384         for (int page_start = first; page_start <= last; page_start++) {
385                 /* Set up erase command */
386                 uint32_t address = bank->base + page_start*MINI51_PAGE_SIZE;
387                 status = mini51_isp_execute_cmd(target, ISPCMD_ERASE, address, 0);
388                 ENSURE_OK(status);
389         }
390
391         return ERROR_OK;
392 }
393
394 static int mini51_protect(struct flash_bank *bank, int set, int first, int last)
395 {
396         LOG_WARNING("Mini51 flash driver: protect operation not implemented yet\n");
397
398         return ERROR_FLASH_OPERATION_FAILED;
399 }
400
401 static int mini51_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
402 {
403         int status;
404         uint32_t ispdat;
405         struct target *target = bank->target;
406
407         if ((offset & 0x3) || (count & 0x3)) {
408                 LOG_WARNING("Mini51 flash driver: unaligned access not supported\n");
409                 return ERROR_FLASH_OPERATION_FAILED;
410         }
411
412         status = mini51_isp_enable(target);
413         ENSURE_OK(status);
414
415         for (uint32_t i = offset; i < offset + count; i += 4) {
416                 memcpy(&ispdat, buffer, sizeof(ispdat));
417                 status = mini51_isp_execute_cmd(target, ISPCMD_PROGRAM, bank->base + i, ispdat);
418                 ENSURE_OK(status);
419                 buffer += sizeof(ispdat);
420         }
421
422         return ERROR_OK;
423 }
424
425 static int mini51_probe(struct flash_bank *bank)
426 {
427         uint32_t flash_size;
428         int status;
429         int num_pages;
430         uint32_t offset = 0;
431         const struct mini51_cpu_type *cpu;
432         struct target *target = bank->target;
433
434         status = mini51_get_cpu_type(target, &cpu);
435         if (status != ERROR_OK) {
436                 LOG_WARNING("Mini51 flash driver: Failed to detect a known part\n");
437                 return ERROR_FLASH_OPERATION_FAILED;
438         }
439
440         status = mini51_get_flash_size(bank, cpu, &flash_size);
441         if (status != ERROR_OK) {
442                 LOG_WARNING("Mini51 flash driver: Failed to detect flash size\n");
443                 return ERROR_FLASH_OPERATION_FAILED;
444         }
445
446         num_pages = flash_size / MINI51_PAGE_SIZE;
447
448         bank->num_sectors = num_pages;
449         bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
450         bank->size = flash_size;
451
452         for (int i = 0; i < num_pages; i++) {
453                 bank->sectors[i].offset = offset;
454                 bank->sectors[i].size = MINI51_PAGE_SIZE;
455                 bank->sectors[i].is_erased = -1;
456                 bank->sectors[i].is_protected = 0;
457                 offset += MINI51_PAGE_SIZE;
458         }
459
460         struct mini51_flash_bank *mini51_info = bank->driver_priv;
461         mini51_info->probed = true;
462         mini51_info->cpu = cpu;
463
464         return ERROR_OK;
465 }
466
467 static int mini51_auto_probe(struct flash_bank *bank)
468 {
469         struct mini51_flash_bank *mini51_info = bank->driver_priv;
470         if (mini51_info->probed)
471                 return ERROR_OK;
472         return mini51_probe(bank);
473 }
474
475 COMMAND_HANDLER(mini51_handle_read_isp_command)
476 {
477         uint32_t address;
478         uint32_t ispdat;
479         int status;
480
481         if (CMD_ARGC != 1)
482                 return ERROR_COMMAND_SYNTAX_ERROR;
483
484         COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
485
486         struct target *target = get_current_target(CMD_CTX);
487
488         status = mini51_isp_enable(target);
489         ENSURE_OK(status);
490         status = mini51_isp_execute_cmd_read(target, ISPCMD_READ, address, &ispdat);
491         ENSURE_OK(status);
492         LOG_INFO("0x%08" PRIx32 ": 0x%08" PRIx32, address, ispdat);
493         return ERROR_OK;
494 }
495
496 COMMAND_HANDLER(mini51_handle_write_isp_command)
497 {
498         uint32_t address;
499         uint32_t ispdat;
500         int status;
501
502         if (CMD_ARGC != 2)
503                 return ERROR_COMMAND_SYNTAX_ERROR;
504
505         COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
506         COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], ispdat);
507
508         struct target *target = get_current_target(CMD_CTX);
509
510         status = mini51_isp_enable(target);
511         ENSURE_OK(status);
512         status = mini51_isp_execute_cmd(target, ISPCMD_PROGRAM, address, ispdat);
513         ENSURE_OK(status);
514         LOG_INFO("0x%08" PRIx32 ": 0x%08" PRIx32, address, ispdat);
515         return ERROR_OK;
516 }
517
518 COMMAND_HANDLER(mini51_handle_chip_erase_command)
519 {
520         int status;
521         if (CMD_ARGC != 0)
522                 return ERROR_COMMAND_SYNTAX_ERROR;
523
524         struct target *target = get_current_target(CMD_CTX);
525
526         status = mini51_isp_enable(target);
527         ENSURE_OK(status);
528         /* Write one to undocumented flash control register */
529         status = target_write_u32(target, ISPUNKNOWN, 1);
530         ENSURE_OK(status);
531
532         status = mini51_isp_execute_cmd(target, ISPCMD_CHIP_ERASE, 0, 0);
533         ENSURE_OK(status);
534         return ERROR_OK;
535 }
536
537 static const struct command_registration mini51_exec_command_handlers[] = {
538         {
539                 .name = "read_isp",
540                 .handler = mini51_handle_read_isp_command,
541                 .usage = "address",
542                 .mode = COMMAND_EXEC,
543                 .help = "read flash through ISP.",
544         },
545         {
546                 .name = "write_isp",
547                 .handler = mini51_handle_write_isp_command,
548                 .usage = "address value",
549                 .mode = COMMAND_EXEC,
550                 .help = "write flash through ISP.",
551         },
552         {
553                 .name = "chip_erase",
554                 .handler = mini51_handle_chip_erase_command,
555                 .mode = COMMAND_EXEC,
556                 .help = "chip erase.",
557         },
558         COMMAND_REGISTRATION_DONE
559 };
560
561 static const struct command_registration mini51_command_handlers[] = {
562         {
563                 .name = "mini51",
564                 .mode = COMMAND_ANY,
565                 .help = "mini51 flash command group",
566                 .usage = "",
567                 .chain = mini51_exec_command_handlers,
568         },
569         COMMAND_REGISTRATION_DONE
570 };
571
572 struct flash_driver mini51_flash = {
573         .name = "mini51",
574         .commands = mini51_command_handlers,
575         .flash_bank_command = mini51_flash_bank_command,
576         .erase = mini51_erase,
577         .protect = mini51_protect,
578         .write = mini51_write,
579         .read = mini51_read,
580         .probe = mini51_probe,
581         .auto_probe = mini51_auto_probe,
582         .erase_check = default_flash_blank_check,
583         .protect_check = mini51_protect_check,
584 };