]> git.sur5r.net Git - openocd/blob - src/flash/nor/pic32mx.c
8cd0fe656ddf03c99740f6332223bcc3a21b7cc0
[openocd] / src / flash / nor / pic32mx.c
1 /***************************************************************************
2  *   Copyright (C) 2005 by Dominic Rath                                    *
3  *   Dominic.Rath@gmx.de                                                   *
4  *                                                                         *
5  *   Copyright (C) 2008 by Spencer Oliver                                  *
6  *   spen@spen-soft.co.uk                                                  *
7  *                                                                         *
8  *   Copyright (C) 2008 by John McCarthy                                   *
9  *   jgmcc@magma.ca                                                        *
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  *   This program is distributed in the hope that it will be useful,       *
17  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
18  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
19  *   GNU General Public License for more details.                          *
20  *                                                                         *
21  *   You should have received a copy of the GNU General Public License     *
22  *   along with this program; if not, write to the                         *
23  *   Free Software Foundation, Inc.,                                       *
24  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
25  ***************************************************************************/
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include "imp.h"
32 #include <target/algorithm.h>
33 #include <target/mips32.h>
34 #include <target/mips_m4k.h>
35
36 #define PIC32MX_MANUF_ID        0x029
37
38 /* pic32mx memory locations */
39
40 #define PIC32MX_PHYS_RAM                        0x00000000
41 #define PIC32MX_PHYS_PGM_FLASH          0x1D000000
42 #define PIC32MX_PHYS_PERIPHERALS        0x1F800000
43 #define PIC32MX_PHYS_BOOT_FLASH         0x1FC00000
44
45 /*
46  * Translate Virtual and Physical addresses.
47  * Note: These macros only work for KSEG0/KSEG1 addresses.
48  */
49
50 #define Virt2Phys(v)    ((v) & 0x1FFFFFFF)
51
52 /* pic32mx configuration register locations */
53
54 #define PIC32MX_DEVCFG0_1_2     0xBFC00BFC
55 #define PIC32MX_DEVCFG0         0xBFC02FFC
56 #define PIC32MX_DEVCFG1         0xBFC02FF8
57 #define PIC32MX_DEVCFG2         0xBFC02FF4
58 #define PIC32MX_DEVCFG3         0xBFC02FF0
59 #define PIC32MX_DEVID           0xBF80F220
60
61 #define PIC32MX_BMXPFMSZ        0xBF882060
62 #define PIC32MX_BMXBOOTSZ       0xBF882070
63 #define PIC32MX_BMXDRMSZ        0xBF882040
64
65 /* pic32mx flash controller register locations */
66
67 #define PIC32MX_NVMCON          0xBF80F400
68 #define PIC32MX_NVMCONCLR       0xBF80F404
69 #define PIC32MX_NVMCONSET       0xBF80F408
70 #define PIC32MX_NVMCONINV       0xBF80F40C
71 #define NVMCON_NVMWR            (1 << 15)
72 #define NVMCON_NVMWREN          (1 << 14)
73 #define NVMCON_NVMERR           (1 << 13)
74 #define NVMCON_LVDERR           (1 << 12)
75 #define NVMCON_LVDSTAT          (1 << 11)
76 #define NVMCON_OP_PFM_ERASE             0x5
77 #define NVMCON_OP_PAGE_ERASE    0x4
78 #define NVMCON_OP_ROW_PROG              0x3
79 #define NVMCON_OP_WORD_PROG             0x1
80 #define NVMCON_OP_NOP                   0x0
81
82 #define PIC32MX_NVMKEY          0xBF80F410
83 #define PIC32MX_NVMADDR         0xBF80F420
84 #define PIC32MX_NVMADDRCLR      0xBF80F424
85 #define PIC32MX_NVMADDRSET      0xBF80F428
86 #define PIC32MX_NVMADDRINV      0xBF80F42C
87 #define PIC32MX_NVMDATA         0xBF80F430
88 #define PIC32MX_NVMSRCADDR      0xBF80F440
89
90 /* flash unlock keys */
91
92 #define NVMKEY1                 0xAA996655
93 #define NVMKEY2                 0x556699AA
94
95 #define MX_1_2                  1       /* PIC32mx1xx/2xx */
96
97 struct pic32mx_flash_bank {
98         struct working_area *write_algorithm;
99         int probed;
100         int dev_type;           /* Default 0. 1 for Pic32MX1XX/2XX variant */
101 };
102
103 /*
104  * DEVID values as per PIC32MX Flash Programming Specification Rev J
105  */
106
107 static const struct pic32mx_devs_s {
108         uint32_t devid;
109         const char *name;
110 } pic32mx_devs[] = {
111         {0x04A07053, "110F016B"},
112         {0x04A09053, "110F016C"},
113         {0x04A0B053, "110F016D"},
114         {0x04A06053, "120F032B"},
115         {0x04A08053, "120F032C"},
116         {0x04A0A053, "120F032D"},
117         {0x04D07053, "130F064B"},
118         {0x04D09053, "130F064C"},
119         {0x04D0B053, "130F064D"},
120         {0x04D06053, "150F128B"},
121         {0x04D08053, "150F128C"},
122         {0x04D0A053, "150F128D"},
123         {0x04A01053, "210F016B"},
124         {0x04A03053, "210F016C"},
125         {0x04A05053, "210F016D"},
126         {0x04A00053, "220F032B"},
127         {0x04A02053, "220F032C"},
128         {0x04A04053, "220F032D"},
129         {0x04D01053, "230F064B"},
130         {0x04D03053, "230F064C"},
131         {0x04D05053, "230F064D"},
132         {0x04D00053, "250F128B"},
133         {0x04D02053, "250F128C"},
134         {0x04D04053, "250F128D"},
135         {0x00938053, "360F512L"},
136         {0x00934053, "360F256L"},
137         {0x0092D053, "340F128L"},
138         {0x0092A053, "320F128L"},
139         {0x00916053, "340F512H"},
140         {0x00912053, "340F256H"},
141         {0x0090D053, "340F128H"},
142         {0x0090A053, "320F128H"},
143         {0x00906053, "320F064H"},
144         {0x00902053, "320F032H"},
145         {0x00978053, "460F512L"},
146         {0x00974053, "460F256L"},
147         {0x0096D053, "440F128L"},
148         {0x00952053, "440F256H"},
149         {0x00956053, "440F512H"},
150         {0x0094D053, "440F128H"},
151         {0x00942053, "420F032H"},
152         {0x04307053, "795F512L"},
153         {0x0430E053, "795F512H"},
154         {0x04306053, "775F512L"},
155         {0x0430D053, "775F512H"},
156         {0x04312053, "775F256L"},
157         {0x04303053, "775F256H"},
158         {0x04417053, "764F128L"},
159         {0x0440B053, "764F128H"},
160         {0x04341053, "695F512L"},
161         {0x04325053, "695F512H"},
162         {0x04311053, "675F512L"},
163         {0x0430C053, "675F512H"},
164         {0x04305053, "675F256L"},
165         {0x0430B053, "675F256H"},
166         {0x04413053, "664F128L"},
167         {0x04407053, "664F128H"},
168         {0x04411053, "664F064L"},
169         {0x04405053, "664F064H"},
170         {0x0430F053, "575F512L"},
171         {0x04309053, "575F512H"},
172         {0x04333053, "575F256L"},
173         {0x04317053, "575F256H"},
174         {0x0440F053, "564F128L"},
175         {0x04403053, "564F128H"},
176         {0x0440D053, "564F064L"},
177         {0x04401053, "564F064H"},
178         {0x04400053, "534F064H"},
179         {0x0440C053, "534F064L"},
180         {0x00000000, NULL}
181 };
182
183 /* flash bank pic32mx <base> <size> 0 0 <target#>
184  */
185 FLASH_BANK_COMMAND_HANDLER(pic32mx_flash_bank_command)
186 {
187         struct pic32mx_flash_bank *pic32mx_info;
188
189         if (CMD_ARGC < 6)
190                 return ERROR_COMMAND_SYNTAX_ERROR;
191
192         pic32mx_info = malloc(sizeof(struct pic32mx_flash_bank));
193         bank->driver_priv = pic32mx_info;
194
195         pic32mx_info->write_algorithm = NULL;
196         pic32mx_info->probed = 0;
197         pic32mx_info->dev_type = 0;
198
199         return ERROR_OK;
200 }
201
202 static uint32_t pic32mx_get_flash_status(struct flash_bank *bank)
203 {
204         struct target *target = bank->target;
205         uint32_t status;
206
207         target_read_u32(target, PIC32MX_NVMCON, &status);
208
209         return status;
210 }
211
212 static uint32_t pic32mx_wait_status_busy(struct flash_bank *bank, int timeout)
213 {
214         uint32_t status;
215
216         /* wait for busy to clear */
217         while (((status = pic32mx_get_flash_status(bank)) & NVMCON_NVMWR) && (timeout-- > 0)) {
218                 LOG_DEBUG("status: 0x%" PRIx32, status);
219                 alive_sleep(1);
220         }
221         if (timeout <= 0)
222                 LOG_DEBUG("timeout: status: 0x%" PRIx32, status);
223
224         return status;
225 }
226
227 static int pic32mx_nvm_exec(struct flash_bank *bank, uint32_t op, uint32_t timeout)
228 {
229         struct target *target = bank->target;
230         uint32_t status;
231
232         target_write_u32(target, PIC32MX_NVMCON, NVMCON_NVMWREN | op);
233
234         /* unlock flash registers */
235         target_write_u32(target, PIC32MX_NVMKEY, NVMKEY1);
236         target_write_u32(target, PIC32MX_NVMKEY, NVMKEY2);
237
238         /* start operation */
239         target_write_u32(target, PIC32MX_NVMCONSET, NVMCON_NVMWR);
240
241         status = pic32mx_wait_status_busy(bank, timeout);
242
243         /* lock flash registers */
244         target_write_u32(target, PIC32MX_NVMCONCLR, NVMCON_NVMWREN);
245
246         return status;
247 }
248
249 static int pic32mx_protect_check(struct flash_bank *bank)
250 {
251         struct target *target = bank->target;
252         struct pic32mx_flash_bank *pic32mx_info = bank->driver_priv;
253
254         uint32_t config0_address;
255         uint32_t devcfg0;
256         int s;
257         int num_pages;
258
259         if (target->state != TARGET_HALTED) {
260                 LOG_ERROR("Target not halted");
261                 return ERROR_TARGET_NOT_HALTED;
262         }
263
264         if (pic32mx_info->dev_type == MX_1_2)
265                 config0_address = PIC32MX_DEVCFG0_1_2;
266         else
267                 config0_address = PIC32MX_DEVCFG0;
268
269         target_read_u32(target, config0_address, &devcfg0);
270
271         if ((devcfg0 & (1 << 28)) == 0) /* code protect bit */
272                 num_pages = 0xffff;                     /* All pages protected */
273         else if (Virt2Phys(bank->base) == PIC32MX_PHYS_BOOT_FLASH) {
274                 if (devcfg0 & (1 << 24))
275                         num_pages = 0;                  /* All pages unprotected */
276                 else
277                         num_pages = 0xffff;             /* All pages protected */
278         } else {
279                 /* pgm flash */
280                 if (pic32mx_info->dev_type == MX_1_2)
281                         num_pages = (~devcfg0 >> 10) & 0x3f;
282                 else
283                         num_pages = (~devcfg0 >> 12) & 0xff;
284         }
285
286         for (s = 0; s < bank->num_sectors && s < num_pages; s++)
287                 bank->sectors[s].is_protected = 1;
288         for (; s < bank->num_sectors; s++)
289                 bank->sectors[s].is_protected = 0;
290
291         return ERROR_OK;
292 }
293
294 static int pic32mx_erase(struct flash_bank *bank, int first, int last)
295 {
296         struct target *target = bank->target;
297         int i;
298         uint32_t status;
299
300         if (bank->target->state != TARGET_HALTED) {
301                 LOG_ERROR("Target not halted");
302                 return ERROR_TARGET_NOT_HALTED;
303         }
304
305         if ((first == 0) && (last == (bank->num_sectors - 1))
306                 && (Virt2Phys(bank->base) == PIC32MX_PHYS_PGM_FLASH)) {
307                 /* this will only erase the Program Flash (PFM), not the Boot Flash (BFM)
308                  * we need to use the MTAP to perform a full erase */
309                 LOG_DEBUG("Erasing entire program flash");
310                 status = pic32mx_nvm_exec(bank, NVMCON_OP_PFM_ERASE, 50);
311                 if (status & NVMCON_NVMERR)
312                         return ERROR_FLASH_OPERATION_FAILED;
313                 if (status & NVMCON_LVDERR)
314                         return ERROR_FLASH_OPERATION_FAILED;
315                 return ERROR_OK;
316         }
317
318         for (i = first; i <= last; i++) {
319                 target_write_u32(target, PIC32MX_NVMADDR, Virt2Phys(bank->base + bank->sectors[i].offset));
320
321                 status = pic32mx_nvm_exec(bank, NVMCON_OP_PAGE_ERASE, 10);
322
323                 if (status & NVMCON_NVMERR)
324                         return ERROR_FLASH_OPERATION_FAILED;
325                 if (status & NVMCON_LVDERR)
326                         return ERROR_FLASH_OPERATION_FAILED;
327                 bank->sectors[i].is_erased = 1;
328         }
329
330         return ERROR_OK;
331 }
332
333 static int pic32mx_protect(struct flash_bank *bank, int set, int first, int last)
334 {
335         struct target *target = bank->target;
336
337         if (target->state != TARGET_HALTED) {
338                 LOG_ERROR("Target not halted");
339                 return ERROR_TARGET_NOT_HALTED;
340         }
341
342         return ERROR_OK;
343 }
344
345 /* see contib/loaders/flash/pic32mx.s for src */
346
347 static uint32_t pic32mx_flash_write_code[] = {
348                                         /* write: */
349         0x3C08AA99,             /* lui $t0, 0xaa99 */
350         0x35086655,             /* ori $t0, 0x6655 */
351         0x3C095566,             /* lui $t1, 0x5566 */
352         0x352999AA,             /* ori $t1, 0x99aa */
353         0x3C0ABF80,             /* lui $t2, 0xbf80 */
354         0x354AF400,             /* ori $t2, 0xf400 */
355         0x340B4003,             /* ori $t3, $zero, 0x4003 */
356         0x340C8000,             /* ori $t4, $zero, 0x8000 */
357                                         /* write_row: */
358         0x2CD30080,             /* sltiu $s3, $a2, 128 */
359         0x16600008,             /* bne $s3, $zero, write_word */
360         0x340D4000,             /* ori $t5, $zero, 0x4000 */
361         0xAD450020,             /* sw $a1, 32($t2) */
362         0xAD440040,             /* sw $a0, 64($t2) */
363         0x04110016,             /* bal progflash */
364         0x24840200,             /* addiu $a0, $a0, 512 */
365         0x24A50200,             /* addiu $a1, $a1, 512 */
366         0x1000FFF7,             /* beq $zero, $zero, write_row */
367         0x24C6FF80,             /* addiu $a2, $a2, -128 */
368                                         /* write_word: */
369         0x3C15A000,             /* lui $s5, 0xa000 */
370         0x36B50000,             /* ori $s5, $s5, 0x0 */
371         0x00952025,             /* or $a0, $a0, $s5 */
372         0x10000008,             /* beq $zero, $zero, next_word */
373         0x340B4001,             /* ori $t3, $zero, 0x4001 */
374                                         /* prog_word: */
375         0x8C940000,             /* lw $s4, 0($a0) */
376         0xAD540030,             /* sw $s4, 48($t2) */
377         0xAD450020,             /* sw $a1, 32($t2) */
378         0x04110009,             /* bal progflash */
379         0x24840004,             /* addiu $a0, $a0, 4 */
380         0x24A50004,             /* addiu $a1, $a1, 4 */
381         0x24C6FFFF,             /* addiu $a2, $a2, -1 */
382                                         /* next_word: */
383         0x14C0FFF8,             /* bne $a2, $zero, prog_word */
384         0x00000000,             /* nop */
385                                         /* done: */
386         0x10000002,             /* beq $zero, $zero, exit */
387         0x24040000,             /* addiu $a0, $zero, 0 */
388                                         /* error: */
389         0x26240000,             /* addiu $a0, $s1, 0 */
390                                         /* exit: */
391         0x7000003F,             /* sdbbp */
392                                         /* progflash: */
393         0xAD4B0000,             /* sw $t3, 0($t2) */
394         0xAD480010,             /* sw $t0, 16($t2) */
395         0xAD490010,             /* sw $t1, 16($t2) */
396         0xAD4C0008,             /* sw $t4, 8($t2) */
397                                         /* waitflash: */
398         0x8D500000,             /* lw $s0, 0($t2) */
399         0x020C8024,             /* and $s0, $s0, $t4 */
400         0x1600FFFD,             /* bne $s0, $zero, waitflash */
401         0x00000000,             /* nop */
402         0x00000000,             /* nop */
403         0x00000000,             /* nop */
404         0x00000000,             /* nop */
405         0x00000000,             /* nop */
406         0x8D510000,             /* lw $s1, 0($t2) */
407         0x30113000,             /* andi $s1, $zero, 0x3000 */
408         0x1620FFEF,             /* bne $s1, $zero, error */
409         0xAD4D0004,             /* sw $t5, 4($t2) */
410         0x03E00008,             /* jr $ra */
411         0x00000000              /* nop */
412 };
413
414 static int pic32mx_write_block(struct flash_bank *bank, uint8_t *buffer,
415                 uint32_t offset, uint32_t count)
416 {
417         struct target *target = bank->target;
418         uint32_t buffer_size = 16384;
419         struct working_area *source;
420         uint32_t address = bank->base + offset;
421         struct reg_param reg_params[3];
422         int retval = ERROR_OK;
423
424         struct pic32mx_flash_bank *pic32mx_info = bank->driver_priv;
425         struct mips32_algorithm mips32_info;
426
427         /* flash write code */
428         if (target_alloc_working_area(target, sizeof(pic32mx_flash_write_code),
429                         &pic32mx_info->write_algorithm) != ERROR_OK) {
430                 LOG_WARNING("no working area available, can't do block memory writes");
431                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
432         };
433
434         /* Change values for counters and row size, depending on variant */
435         if (pic32mx_info->dev_type == MX_1_2) {
436                 /* 128 byte row */
437                 pic32mx_flash_write_code[8] = 0x2CD30020;
438                 pic32mx_flash_write_code[14] = 0x24840080;
439                 pic32mx_flash_write_code[15] = 0x24A50080;
440                 pic32mx_flash_write_code[17] = 0x24C6FFE0;
441         } else {
442                 /* 512 byte row */
443                 pic32mx_flash_write_code[8] = 0x2CD30080;
444                 pic32mx_flash_write_code[14] = 0x24840200;
445                 pic32mx_flash_write_code[15] = 0x24A50200;
446                 pic32mx_flash_write_code[17] = 0x24C6FF80;
447         }
448
449         retval = target_write_buffer(target, pic32mx_info->write_algorithm->address,
450                         sizeof(pic32mx_flash_write_code), (uint8_t *)pic32mx_flash_write_code);
451         if (retval != ERROR_OK)
452                 return retval;
453
454         /* memory buffer */
455         while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
456                 buffer_size /= 2;
457                 if (buffer_size <= 256) {
458                         /* if we already allocated the writing code, but failed to get a
459                          * buffer, free the algorithm */
460                         if (pic32mx_info->write_algorithm)
461                                 target_free_working_area(target, pic32mx_info->write_algorithm);
462
463                         LOG_WARNING("no large enough working area available, can't do block memory writes");
464                         return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
465                 }
466         };
467
468         mips32_info.common_magic = MIPS32_COMMON_MAGIC;
469         mips32_info.isa_mode = MIPS32_ISA_MIPS32;
470
471         init_reg_param(&reg_params[0], "a0", 32, PARAM_IN_OUT);
472         init_reg_param(&reg_params[1], "a1", 32, PARAM_OUT);
473         init_reg_param(&reg_params[2], "a2", 32, PARAM_OUT);
474
475         while (count > 0) {
476                 uint32_t status;
477                 uint32_t thisrun_count = (count > (buffer_size / 4)) ?
478                                 (buffer_size / 4) : count;
479
480                 retval = target_write_buffer(target, source->address,
481                                 thisrun_count * 4, buffer);
482                 if (retval != ERROR_OK)
483                         break;
484
485                 buf_set_u32(reg_params[0].value, 0, 32, Virt2Phys(source->address));
486                 buf_set_u32(reg_params[1].value, 0, 32, Virt2Phys(address));
487                 buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
488
489                 retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
490                                 pic32mx_info->write_algorithm->address,
491                                 0, 10000, &mips32_info);
492                 if (retval != ERROR_OK) {
493                         LOG_ERROR("error executing pic32mx flash write algorithm");
494                         retval = ERROR_FLASH_OPERATION_FAILED;
495                         break;
496                 }
497
498                 status = buf_get_u32(reg_params[0].value, 0, 32);
499
500                 if (status & NVMCON_NVMERR) {
501                         LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status);
502                         retval = ERROR_FLASH_OPERATION_FAILED;
503                         break;
504                 }
505
506                 if (status & NVMCON_LVDERR) {
507                         LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status);
508                         retval = ERROR_FLASH_OPERATION_FAILED;
509                         break;
510                 }
511
512                 buffer += thisrun_count * 4;
513                 address += thisrun_count * 4;
514                 count -= thisrun_count;
515         }
516
517         target_free_working_area(target, source);
518         target_free_working_area(target, pic32mx_info->write_algorithm);
519
520         destroy_reg_param(&reg_params[0]);
521         destroy_reg_param(&reg_params[1]);
522         destroy_reg_param(&reg_params[2]);
523
524         return retval;
525 }
526
527 static int pic32mx_write_word(struct flash_bank *bank, uint32_t address, uint32_t word)
528 {
529         struct target *target = bank->target;
530
531         target_write_u32(target, PIC32MX_NVMADDR, Virt2Phys(address));
532         target_write_u32(target, PIC32MX_NVMDATA, word);
533
534         return pic32mx_nvm_exec(bank, NVMCON_OP_WORD_PROG, 5);
535 }
536
537 static int pic32mx_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
538 {
539         uint32_t words_remaining = (count / 4);
540         uint32_t bytes_remaining = (count & 0x00000003);
541         uint32_t address = bank->base + offset;
542         uint32_t bytes_written = 0;
543         uint32_t status;
544         int retval;
545
546         if (bank->target->state != TARGET_HALTED) {
547                 LOG_ERROR("Target not halted");
548                 return ERROR_TARGET_NOT_HALTED;
549         }
550
551         LOG_DEBUG("writing to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32
552                         " count: 0x%8.8" PRIx32 "", bank->base, offset, count);
553
554         if (offset & 0x3) {
555                 LOG_WARNING("offset 0x%" PRIx32 "breaks required 4-byte alignment", offset);
556                 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
557         }
558
559         /* multiple words (4-byte) to be programmed? */
560         if (words_remaining > 0) {
561                 /* try using a block write */
562                 retval = pic32mx_write_block(bank, buffer, offset, words_remaining);
563                 if (retval != ERROR_OK) {
564                         if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
565                                 /* if block write failed (no sufficient working area),
566                                  * we use normal (slow) single dword accesses */
567                                 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
568                         } else if (retval == ERROR_FLASH_OPERATION_FAILED) {
569                                 LOG_ERROR("flash writing failed");
570                                 return retval;
571                         }
572                 } else {
573                         buffer += words_remaining * 4;
574                         address += words_remaining * 4;
575                         words_remaining = 0;
576                 }
577         }
578
579         while (words_remaining > 0) {
580                 uint32_t value;
581                 memcpy(&value, buffer + bytes_written, sizeof(uint32_t));
582
583                 status = pic32mx_write_word(bank, address, value);
584
585                 if (status & NVMCON_NVMERR) {
586                         LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status);
587                         return ERROR_FLASH_OPERATION_FAILED;
588                 }
589
590                 if (status & NVMCON_LVDERR) {
591                         LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status);
592                         return ERROR_FLASH_OPERATION_FAILED;
593                 }
594
595                 bytes_written += 4;
596                 words_remaining--;
597                 address += 4;
598         }
599
600         if (bytes_remaining) {
601                 uint32_t value = 0xffffffff;
602                 memcpy(&value, buffer + bytes_written, bytes_remaining);
603
604                 status = pic32mx_write_word(bank, address, value);
605
606                 if (status & NVMCON_NVMERR) {
607                         LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status);
608                         return ERROR_FLASH_OPERATION_FAILED;
609                 }
610
611                 if (status & NVMCON_LVDERR) {
612                         LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status);
613                         return ERROR_FLASH_OPERATION_FAILED;
614                 }
615         }
616
617         return ERROR_OK;
618 }
619
620 static int pic32mx_probe(struct flash_bank *bank)
621 {
622         struct target *target = bank->target;
623         struct pic32mx_flash_bank *pic32mx_info = bank->driver_priv;
624         struct mips32_common *mips32 = target->arch_info;
625         struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
626         int i;
627         uint32_t num_pages = 0;
628         uint32_t device_id;
629         int page_size;
630
631         pic32mx_info->probed = 0;
632
633         device_id = ejtag_info->idcode;
634         LOG_INFO("device id = 0x%08" PRIx32 " (manuf 0x%03x dev 0x%04x, ver 0x%02x)",
635                           device_id,
636                           (unsigned)((device_id >> 1) & 0x7ff),
637                           (unsigned)((device_id >> 12) & 0xffff),
638                           (unsigned)((device_id >> 28) & 0xf));
639
640         if (((device_id >> 1) & 0x7ff) != PIC32MX_MANUF_ID) {
641                 LOG_WARNING("Cannot identify target as a PIC32MX family.");
642                 return ERROR_FLASH_OPERATION_FAILED;
643         }
644
645         /* Check for PIC32mx1xx/2xx */
646         for (i = 0; pic32mx_devs[i].name != NULL; i++) {
647                 if (pic32mx_devs[i].devid == (device_id & 0x0fffffff)) {
648                         if ((*(pic32mx_devs[i].name) == '1') || (*(pic32mx_devs[i].name) == '2'))
649                                 pic32mx_info->dev_type = MX_1_2;
650                         break;
651                 }
652         }
653
654         if (pic32mx_info->dev_type == MX_1_2)
655                 page_size = 1024;
656         else
657                 page_size = 4096;
658
659
660         if (Virt2Phys(bank->base) == PIC32MX_PHYS_BOOT_FLASH) {
661                 /* 0x1FC00000: Boot flash size */
662 #if 0
663                 /* for some reason this register returns 8k for the boot bank size
664                  * this does not match the docs, so for now set the boot bank at a
665                  * fixed 12k */
666                 if (target_read_u32(target, PIC32MX_BMXBOOTSZ, &num_pages) != ERROR_OK) {
667                         LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 12k flash");
668                         num_pages = (12 * 1024);
669                 }
670 #else
671                 /* fixed 12k boot bank - see comments above */
672                 if (pic32mx_info->dev_type == MX_1_2)
673                         num_pages = (3 * 1024);
674                 else
675                         num_pages = (12 * 1024);
676 #endif
677         } else {
678                 /* read the flash size from the device */
679                 if (target_read_u32(target, PIC32MX_BMXPFMSZ, &num_pages) != ERROR_OK) {
680                         if (pic32mx_info->dev_type == MX_1_2) {
681                                 LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 32k flash");
682                                 num_pages = (32 * 1024);
683                         } else {
684                                 LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 512k flash");
685                                 num_pages = (512 * 1024);
686                         }
687                 }
688         }
689
690         LOG_INFO("flash size = %" PRId32 "kbytes", num_pages / 1024);
691
692         if (bank->sectors) {
693                 free(bank->sectors);
694                 bank->sectors = NULL;
695         }
696
697         /* calculate numbers of pages */
698         num_pages /= page_size;
699         bank->size = (num_pages * page_size);
700         bank->num_sectors = num_pages;
701         bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
702
703         for (i = 0; i < (int)num_pages; i++) {
704                 bank->sectors[i].offset = i * page_size;
705                 bank->sectors[i].size = page_size;
706                 bank->sectors[i].is_erased = -1;
707                 bank->sectors[i].is_protected = 1;
708         }
709
710         pic32mx_info->probed = 1;
711
712         return ERROR_OK;
713 }
714
715 static int pic32mx_auto_probe(struct flash_bank *bank)
716 {
717         struct pic32mx_flash_bank *pic32mx_info = bank->driver_priv;
718         if (pic32mx_info->probed)
719                 return ERROR_OK;
720         return pic32mx_probe(bank);
721 }
722
723 static int pic32mx_info(struct flash_bank *bank, char *buf, int buf_size)
724 {
725         struct target *target = bank->target;
726         struct mips32_common *mips32 = target->arch_info;
727         struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
728         uint32_t device_id;
729         int printed = 0, i;
730
731         device_id = ejtag_info->idcode;
732
733         if (((device_id >> 1) & 0x7ff) != PIC32MX_MANUF_ID) {
734                 snprintf(buf, buf_size,
735                                  "Cannot identify target as a PIC32MX family (manufacturer 0x%03d != 0x%03d)\n",
736                                  (unsigned)((device_id >> 1) & 0x7ff),
737                                  PIC32MX_MANUF_ID);
738                 return ERROR_FLASH_OPERATION_FAILED;
739         }
740
741         for (i = 0; pic32mx_devs[i].name != NULL; i++) {
742                 if (pic32mx_devs[i].devid == (device_id & 0x0fffffff)) {
743                         printed = snprintf(buf, buf_size, "PIC32MX%s", pic32mx_devs[i].name);
744                         break;
745                 }
746         }
747
748         if (pic32mx_devs[i].name == NULL)
749                 printed = snprintf(buf, buf_size, "Unknown");
750
751         buf += printed;
752         buf_size -= printed;
753         snprintf(buf, buf_size, " Ver: 0x%02x",
754                         (unsigned)((device_id >> 28) & 0xf));
755
756         return ERROR_OK;
757 }
758
759 COMMAND_HANDLER(pic32mx_handle_pgm_word_command)
760 {
761         uint32_t address, value;
762         int status, res;
763
764         if (CMD_ARGC != 3)
765                 return ERROR_COMMAND_SYNTAX_ERROR;
766
767         COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
768         COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
769
770         struct flash_bank *bank;
771         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 2, &bank);
772         if (ERROR_OK != retval)
773                 return retval;
774
775         if (address < bank->base || address >= (bank->base + bank->size)) {
776                 command_print(CMD_CTX, "flash address '%s' is out of bounds", CMD_ARGV[0]);
777                 return ERROR_OK;
778         }
779
780         res = ERROR_OK;
781         status = pic32mx_write_word(bank, address, value);
782         if (status & NVMCON_NVMERR)
783                 res = ERROR_FLASH_OPERATION_FAILED;
784         if (status & NVMCON_LVDERR)
785                 res = ERROR_FLASH_OPERATION_FAILED;
786
787         if (res == ERROR_OK)
788                 command_print(CMD_CTX, "pic32mx pgm word complete");
789         else
790                 command_print(CMD_CTX, "pic32mx pgm word failed (status = 0x%x)", status);
791
792         return ERROR_OK;
793 }
794
795 COMMAND_HANDLER(pic32mx_handle_unlock_command)
796 {
797         uint32_t mchip_cmd;
798         struct target *target = NULL;
799         struct mips_m4k_common *mips_m4k;
800         struct mips_ejtag *ejtag_info;
801         int timeout = 10;
802
803         if (CMD_ARGC < 1) {
804                 command_print(CMD_CTX, "pic32mx unlock <bank>");
805                 return ERROR_COMMAND_SYNTAX_ERROR;
806         }
807
808         struct flash_bank *bank;
809         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
810         if (ERROR_OK != retval)
811                 return retval;
812
813         target = bank->target;
814         mips_m4k = target_to_m4k(target);
815         ejtag_info = &mips_m4k->mips32.ejtag_info;
816
817         /* we have to use the MTAP to perform a full erase */
818         mips_ejtag_set_instr(ejtag_info, MTAP_SW_MTAP);
819         mips_ejtag_set_instr(ejtag_info, MTAP_COMMAND);
820
821         /* first check status of device */
822         mchip_cmd = MCHP_STATUS;
823         mips_ejtag_drscan_8(ejtag_info, &mchip_cmd);
824         if (mchip_cmd & (1 << 7)) {
825                 /* device is not locked */
826                 command_print(CMD_CTX, "pic32mx is already unlocked, erasing anyway");
827         }
828
829         /* unlock/erase device */
830         mips_ejtag_drscan_8_out(ejtag_info, MCHP_ASERT_RST);
831
832         mips_ejtag_drscan_8_out(ejtag_info, MCHP_ERASE);
833
834         do {
835                 mchip_cmd = MCHP_STATUS;
836                 mips_ejtag_drscan_8(ejtag_info, &mchip_cmd);
837                 if (timeout-- == 0) {
838                         LOG_DEBUG("timeout waiting for unlock: 0x%" PRIx32 "", mchip_cmd);
839                         break;
840                 }
841                 alive_sleep(1);
842         } while ((mchip_cmd & (1 << 2)) || (!(mchip_cmd & (1 << 3))));
843
844         mips_ejtag_drscan_8_out(ejtag_info, MCHP_DE_ASSERT_RST);
845
846         /* select ejtag tap */
847         mips_ejtag_set_instr(ejtag_info, MTAP_SW_ETAP);
848
849         command_print(CMD_CTX, "pic32mx unlocked.\n"
850                         "INFO: a reset or power cycle is required "
851                         "for the new settings to take effect.");
852
853         return ERROR_OK;
854 }
855
856 static const struct command_registration pic32mx_exec_command_handlers[] = {
857         {
858                 .name = "pgm_word",
859                 .usage = "<addr> <value> <bank>",
860                 .handler = pic32mx_handle_pgm_word_command,
861                 .mode = COMMAND_EXEC,
862                 .help = "program a word",
863         },
864         {
865                 .name = "unlock",
866                 .handler = pic32mx_handle_unlock_command,
867                 .mode = COMMAND_EXEC,
868                 .usage = "[bank_id]",
869                 .help = "Unlock/Erase entire device.",
870         },
871         COMMAND_REGISTRATION_DONE
872 };
873
874 static const struct command_registration pic32mx_command_handlers[] = {
875         {
876                 .name = "pic32mx",
877                 .mode = COMMAND_ANY,
878                 .help = "pic32mx flash command group",
879                 .usage = "",
880                 .chain = pic32mx_exec_command_handlers,
881         },
882         COMMAND_REGISTRATION_DONE
883 };
884
885 struct flash_driver pic32mx_flash = {
886         .name = "pic32mx",
887         .commands = pic32mx_command_handlers,
888         .flash_bank_command = pic32mx_flash_bank_command,
889         .erase = pic32mx_erase,
890         .protect = pic32mx_protect,
891         .write = pic32mx_write,
892         .read = default_flash_read,
893         .probe = pic32mx_probe,
894         .auto_probe = pic32mx_auto_probe,
895         .erase_check = default_flash_mem_blank_check,
896         .protect_check = pic32mx_protect_check,
897         .info = pic32mx_info,
898 };