]> git.sur5r.net Git - openocd/blob - src/flash/nor/pic32mx.c
remove target.h from flash.h
[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 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include "imp.h"
31 #include "pic32mx.h"
32 #include <target/mips32.h>
33
34
35 static
36 struct pic32mx_devs_s {
37         uint8_t devid;
38         char    *name;
39         uint32_t        pfm_size;
40 } pic32mx_devs[] = {
41         { 0x78, "460F512L USB", 512 },
42         { 0x74, "460F256L USB", 256 },
43         { 0x6D, "440F128L USB", 128 },
44         { 0x56, "440F512H USB", 512 },
45         { 0x52, "440F256H USB", 256 },
46         { 0x4D, "440F128H USB", 128 },
47         { 0x42, "420F032H USB",  32 },
48         { 0x38, "360F512L",     512 },
49         { 0x34, "360F256L",     256 },
50         { 0x2D, "340F128L",     128 },
51         { 0x2A, "320F128L",     128 },
52         { 0x16, "340F512H",     512 },
53         { 0x12, "340F256H",     256 },
54         { 0x0D, "340F128H",     128 },
55         { 0x0A, "320F128H",     128 },
56         { 0x06, "320F064H",      64 },
57         { 0x02, "320F032H",      32 },
58         { 0x00, NULL, 0 }
59 };
60
61 static int pic32mx_write_row(struct flash_bank *bank, uint32_t address, uint32_t srcaddr);
62 static int pic32mx_write_word(struct flash_bank *bank, uint32_t address, uint32_t word);
63
64 /* flash bank pic32mx <base> <size> 0 0 <target#>
65  */
66 FLASH_BANK_COMMAND_HANDLER(pic32mx_flash_bank_command)
67 {
68         struct pic32mx_flash_bank *pic32mx_info;
69
70         if (CMD_ARGC < 6)
71         {
72                 LOG_WARNING("incomplete flash_bank pic32mx configuration");
73                 return ERROR_FLASH_BANK_INVALID;
74         }
75
76         pic32mx_info = malloc(sizeof(struct pic32mx_flash_bank));
77         bank->driver_priv = pic32mx_info;
78
79         pic32mx_info->write_algorithm = NULL;
80         pic32mx_info->probed = 0;
81
82         return ERROR_OK;
83 }
84
85 static uint32_t pic32mx_get_flash_status(struct flash_bank *bank)
86 {
87         struct target *target = bank->target;
88         uint32_t status;
89
90         target_read_u32(target, PIC32MX_NVMCON, &status);
91
92         return status;
93 }
94
95 static uint32_t pic32mx_wait_status_busy(struct flash_bank *bank, int timeout)
96 {
97         uint32_t status;
98
99         /* wait for busy to clear */
100         while (((status = pic32mx_get_flash_status(bank)) & NVMCON_NVMWR) && (timeout-- > 0))
101         {
102                 LOG_DEBUG("status: 0x%" PRIx32, status);
103                 alive_sleep(1);
104         }
105         if (timeout <= 0)
106                 LOG_DEBUG("timeout: status: 0x%" PRIx32, status);
107
108         return status;
109 }
110
111 static int pic32mx_nvm_exec(struct flash_bank *bank, uint32_t op, uint32_t timeout)
112 {
113         struct target *target = bank->target;
114         uint32_t status;
115
116         target_write_u32(target, PIC32MX_NVMCON, NVMCON_NVMWREN | op);
117
118         /* unlock flash registers */
119         target_write_u32(target, PIC32MX_NVMKEY, NVMKEY1);
120         target_write_u32(target, PIC32MX_NVMKEY, NVMKEY2);
121
122         /* start operation */
123         target_write_u32(target, PIC32MX_NVMCONSET, NVMCON_NVMWR);
124
125         status = pic32mx_wait_status_busy(bank, timeout);
126
127         /* lock flash registers */
128         target_write_u32(target, PIC32MX_NVMCONCLR, NVMCON_NVMWREN);
129
130         return status;
131 }
132
133 static int pic32mx_protect_check(struct flash_bank *bank)
134 {
135         struct target *target = bank->target;
136
137         uint32_t devcfg0;
138         int s;
139         int num_pages;
140
141         if (target->state != TARGET_HALTED)
142         {
143                 LOG_ERROR("Target not halted");
144                 return ERROR_TARGET_NOT_HALTED;
145         }
146
147         target_read_u32(target, PIC32MX_DEVCFG0, &devcfg0);
148         if ((devcfg0 & (1 << 28)) == 0) /* code protect bit */
149                 num_pages = 0xffff;  /* All pages protected */
150         else if (bank->base == PIC32MX_KSEG1_BOOT_FLASH)
151         {
152                 if (devcfg0 & (1 << 24))
153                         num_pages = 0;       /* All pages unprotected */
154                 else
155                         num_pages = 0xffff;  /* All pages protected */
156         }
157         else /* pgm flash */
158                 num_pages = (~devcfg0 >> 12) & 0xff;
159         for (s = 0; s < bank->num_sectors && s < num_pages; s++)
160                 bank->sectors[s].is_protected = 1;
161         for (; s < bank->num_sectors; s++)
162                 bank->sectors[s].is_protected = 0;
163
164         return ERROR_OK;
165 }
166
167 static int pic32mx_erase(struct flash_bank *bank, int first, int last)
168 {
169         struct target *target = bank->target;
170         int i;
171         uint32_t status;
172
173         if (bank->target->state != TARGET_HALTED)
174         {
175                 LOG_ERROR("Target not halted");
176                 return ERROR_TARGET_NOT_HALTED;
177         }
178
179         if ((first == 0) && (last == (bank->num_sectors - 1)) && (bank->base == PIC32MX_KSEG0_PGM_FLASH || bank->base == PIC32MX_KSEG1_PGM_FLASH))
180         {
181                 LOG_DEBUG("Erasing entire program flash");
182                 status = pic32mx_nvm_exec(bank, NVMCON_OP_PFM_ERASE, 50);
183                 if (status & NVMCON_NVMERR)
184                         return ERROR_FLASH_OPERATION_FAILED;
185                 if (status & NVMCON_LVDERR)
186                         return ERROR_FLASH_OPERATION_FAILED;
187                 return ERROR_OK;
188         }
189
190         for (i = first; i <= last; i++)
191         {
192                 if (bank->base >= PIC32MX_KSEG1_PGM_FLASH)
193                         target_write_u32(target, PIC32MX_NVMADDR, KS1Virt2Phys(bank->base + bank->sectors[i].offset));
194                 else
195                         target_write_u32(target, PIC32MX_NVMADDR, KS0Virt2Phys(bank->base + bank->sectors[i].offset));
196
197                 status = pic32mx_nvm_exec(bank, NVMCON_OP_PAGE_ERASE, 10);
198
199                 if (status & NVMCON_NVMERR)
200                         return ERROR_FLASH_OPERATION_FAILED;
201                 if (status & NVMCON_LVDERR)
202                         return ERROR_FLASH_OPERATION_FAILED;
203                 bank->sectors[i].is_erased = 1;
204         }
205
206         return ERROR_OK;
207 }
208
209 static int pic32mx_protect(struct flash_bank *bank, int set, int first, int last)
210 {
211         struct pic32mx_flash_bank *pic32mx_info = NULL;
212         struct target *target = bank->target;
213 #if 0
214         uint16_t prot_reg[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
215         int i, reg, bit;
216         int status;
217         uint32_t protection;
218 #endif
219
220         pic32mx_info = bank->driver_priv;
221
222         if (target->state != TARGET_HALTED)
223         {
224                 LOG_ERROR("Target not halted");
225                 return ERROR_TARGET_NOT_HALTED;
226         }
227
228 #if 0
229         if ((first && (first % pic32mx_info->ppage_size)) || ((last + 1) && (last + 1) % pic32mx_info->ppage_size))
230         {
231                 LOG_WARNING("sector start/end incorrect - stm32 has %dK sector protection", pic32mx_info->ppage_size);
232                 return ERROR_FLASH_SECTOR_INVALID;
233         }
234
235         /* medium density - each bit refers to a 4bank protection
236          * high density - each bit refers to a 2bank protection */
237         target_read_u32(target, PIC32MX_FLASH_WRPR, &protection);
238
239         prot_reg[0] = (uint16_t)protection;
240         prot_reg[1] = (uint16_t)(protection >> 8);
241         prot_reg[2] = (uint16_t)(protection >> 16);
242         prot_reg[3] = (uint16_t)(protection >> 24);
243
244         if (pic32mx_info->ppage_size == 2)
245         {
246                 /* high density flash */
247
248                 /* bit 7 controls sector 62 - 255 protection */
249                 if (last > 61)
250                 {
251                         if (set)
252                                 prot_reg[3] &= ~(1 << 7);
253                         else
254                                 prot_reg[3] |= (1 << 7);
255                 }
256
257                 if (first > 61)
258                         first = 62;
259                 if (last > 61)
260                         last = 61;
261
262                 for (i = first; i <= last; i++)
263                 {
264                         reg = (i / pic32mx_info->ppage_size) / 8;
265                         bit = (i / pic32mx_info->ppage_size) - (reg * 8);
266
267                         if (set)
268                                 prot_reg[reg] &= ~(1 << bit);
269                         else
270                                 prot_reg[reg] |= (1 << bit);
271                 }
272         }
273         else
274         {
275                 /* medium density flash */
276                 for (i = first; i <= last; i++)
277                 {
278                         reg = (i / pic32mx_info->ppage_size) / 8;
279                         bit = (i / pic32mx_info->ppage_size) - (reg * 8);
280
281                         if (set)
282                                 prot_reg[reg] &= ~(1 << bit);
283                         else
284                                 prot_reg[reg] |= (1 << bit);
285                 }
286         }
287
288         if ((status = pic32mx_erase_options(bank)) != ERROR_OK)
289                 return status;
290
291         pic32mx_info->option_bytes.protection[0] = prot_reg[0];
292         pic32mx_info->option_bytes.protection[1] = prot_reg[1];
293         pic32mx_info->option_bytes.protection[2] = prot_reg[2];
294         pic32mx_info->option_bytes.protection[3] = prot_reg[3];
295
296         return pic32mx_write_options(bank);
297 #else
298         return ERROR_OK;
299 #endif
300 }
301
302 static int pic32mx_write_block(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
303 {
304         struct target *target = bank->target;
305         uint32_t buffer_size = 512;
306         struct working_area *source;
307         uint32_t address = bank->base + offset;
308         int retval = ERROR_OK;
309 #if 0
310         struct pic32mx_flash_bank *pic32mx_info = bank->driver_priv;
311         struct armv7m_algorithm armv7m_info;
312
313         uint8_t pic32mx_flash_write_code[] = {
314                                                                         /* write: */
315                 0xDF, 0xF8, 0x24, 0x40,         /* ldr  r4, PIC32MX_FLASH_CR */
316                 0x09, 0x4D,                                     /* ldr  r5, PIC32MX_FLASH_SR */
317                 0x4F, 0xF0, 0x01, 0x03,         /* mov  r3, #1 */
318                 0x23, 0x60,                                     /* str  r3, [r4, #0] */
319                 0x30, 0xF8, 0x02, 0x3B,         /* ldrh r3, [r0], #2 */
320                 0x21, 0xF8, 0x02, 0x3B,         /* strh r3, [r1], #2 */
321                                                                         /* busy: */
322                 0x2B, 0x68,                                     /* ldr  r3, [r5, #0] */
323                 0x13, 0xF0, 0x01, 0x0F,         /* tst  r3, #0x01 */
324                 0xFB, 0xD0,                                     /* beq  busy */
325                 0x13, 0xF0, 0x14, 0x0F,         /* tst  r3, #0x14 */
326                 0x01, 0xD1,                                     /* bne  exit */
327                 0x01, 0x3A,                                     /* subs r2, r2, #1 */
328                 0xED, 0xD1,                                     /* bne  write */
329                                                                         /* exit: */
330                 0xFE, 0xE7,                                     /* b exit */
331                 0x10, 0x20, 0x02, 0x40,         /* PIC32MX_FLASH_CR:    .word 0x40022010 */
332                 0x0C, 0x20, 0x02, 0x40          /* PIC32MX_FLASH_SR:    .word 0x4002200C */
333         };
334
335         /* flash write code */
336         if (target_alloc_working_area(target, sizeof(pic32mx_flash_write_code), &pic32mx_info->write_algorithm) != ERROR_OK)
337         {
338                 LOG_WARNING("no working area available, can't do block memory writes");
339                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
340         };
341
342         if ((retval = target_write_buffer(target, pic32mx_info->write_algorithm->address, sizeof(pic32mx_flash_write_code), pic32mx_flash_write_code)) != ERROR_OK)
343                 return retval;
344 #endif
345
346         /* memory buffer */
347         if (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
348         {
349 #if 0
350                 /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
351                 if (pic32mx_info->write_algorithm)
352                         target_free_working_area(target, pic32mx_info->write_algorithm);
353 #endif
354
355                 LOG_WARNING("no large enough working area available, can't do block memory writes");
356                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
357         }
358
359         while (count >= buffer_size/4)
360         {
361                 uint32_t status;
362
363                 if ((retval = target_write_buffer(target, source->address, buffer_size, buffer)) != ERROR_OK) {
364                         LOG_ERROR("Failed to write row buffer (%d words) to RAM", (int)(buffer_size/4));
365                         break;
366                 }
367
368 #if 0
369                 buf_set_u32(reg_params[0].value, 0, 32, source->address);
370                 buf_set_u32(reg_params[1].value, 0, 32, address);
371                 buf_set_u32(reg_params[2].value, 0, 32, buffer_size/4);
372
373                 if ((retval = target_run_algorithm(target, 0, NULL, 4, reg_params, pic32mx_info->write_algorithm->address, \
374                                 pic32mx_info->write_algorithm->address + (sizeof(pic32mx_flash_write_code) - 10), 10000, &armv7m_info)) != ERROR_OK)
375                 {
376                         LOG_ERROR("error executing pic32mx flash write algorithm");
377                         retval = ERROR_FLASH_OPERATION_FAILED;
378                         break;
379                 }
380
381                 if (buf_get_u32(reg_params[3].value, 0, 32) & 0x14)
382                 {
383                         retval = ERROR_FLASH_OPERATION_FAILED;
384                         break;
385                 }
386 #endif
387                 status = pic32mx_write_row(bank, address, source->address);
388                 if (status & NVMCON_NVMERR) {
389                         LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status);
390                         retval = ERROR_FLASH_OPERATION_FAILED;
391                         break;
392                 }
393                 if (status & NVMCON_LVDERR) {
394                         LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status);
395                         retval = ERROR_FLASH_OPERATION_FAILED;
396                         break;
397                 }
398
399                 buffer  += buffer_size;
400                 address += buffer_size;
401                 count   -= buffer_size/4;
402         }
403
404         target_free_working_area(target, source);
405
406         while (count > 0)
407         {
408                 uint32_t value;
409                 memcpy(&value, buffer, sizeof(uint32_t));
410
411                 uint32_t status = pic32mx_write_word(bank, address, value);
412                 if (status & NVMCON_NVMERR) {
413                         LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status);
414                         retval = ERROR_FLASH_OPERATION_FAILED;
415                         break;
416                 }
417                 if (status & NVMCON_LVDERR) {
418                         LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status);
419                         retval = ERROR_FLASH_OPERATION_FAILED;
420                         break;
421                 }
422
423                 buffer  += 4;
424                 address += 4;
425                 count--;
426         }
427
428         return retval;
429 }
430
431 static int pic32mx_write_word(struct flash_bank *bank, uint32_t address, uint32_t word)
432 {
433         struct target *target = bank->target;
434
435         if (bank->base >= PIC32MX_KSEG1_PGM_FLASH)
436                 target_write_u32(target, PIC32MX_NVMADDR, KS1Virt2Phys(address));
437         else
438                 target_write_u32(target, PIC32MX_NVMADDR, KS0Virt2Phys(address));
439         target_write_u32(target, PIC32MX_NVMDATA, word);
440
441         return pic32mx_nvm_exec(bank, NVMCON_OP_WORD_PROG, 5);
442 }
443
444 /*
445  * Write a 128 word (512 byte) row to flash address from RAM srcaddr.
446  */
447 static int pic32mx_write_row(struct flash_bank *bank, uint32_t address, uint32_t srcaddr)
448 {
449         struct target *target = bank->target;
450
451         LOG_DEBUG("addr: 0x%08" PRIx32 " srcaddr: 0x%08" PRIx32 "", address, srcaddr);
452
453         if (address >= PIC32MX_KSEG1_PGM_FLASH)
454                 target_write_u32(target, PIC32MX_NVMADDR,    KS1Virt2Phys(address));
455         else
456                 target_write_u32(target, PIC32MX_NVMADDR,    KS0Virt2Phys(address));
457         if (srcaddr >= PIC32MX_KSEG1_RAM)
458                 target_write_u32(target, PIC32MX_NVMSRCADDR, KS1Virt2Phys(srcaddr));
459         else
460                 target_write_u32(target, PIC32MX_NVMSRCADDR, KS0Virt2Phys(srcaddr));
461
462         return pic32mx_nvm_exec(bank, NVMCON_OP_ROW_PROG, 100);
463 }
464
465 static int pic32mx_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
466 {
467         uint32_t words_remaining = (count / 4);
468         uint32_t bytes_remaining = (count & 0x00000003);
469         uint32_t address = bank->base + offset;
470         uint32_t bytes_written = 0;
471         uint32_t status;
472         int retval;
473
474         if (bank->target->state != TARGET_HALTED)
475         {
476                 LOG_ERROR("Target not halted");
477                 return ERROR_TARGET_NOT_HALTED;
478         }
479
480         if (offset & 0x3)
481         {
482                 LOG_WARNING("offset 0x%" PRIx32 "breaks required 4-byte alignment", offset);
483                 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
484         }
485
486         /* multiple words (4-byte) to be programmed? */
487         if (words_remaining > 0)
488         {
489                 /* try using a block write */
490                 if ((retval = pic32mx_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK)
491                 {
492                         if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
493                         {
494                                 /* if block write failed (no sufficient working area),
495                                  * we use normal (slow) single dword accesses */
496                                 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
497                         }
498                         else if (retval == ERROR_FLASH_OPERATION_FAILED)
499                         {
500                                 LOG_ERROR("flash writing failed with error code: 0x%x", retval);
501                                 return ERROR_FLASH_OPERATION_FAILED;
502                         }
503                 }
504                 else
505                 {
506                         buffer += words_remaining * 4;
507                         address += words_remaining * 4;
508                         words_remaining = 0;
509                 }
510         }
511
512         while (words_remaining > 0)
513         {
514                 uint32_t value;
515                 memcpy(&value, buffer + bytes_written, sizeof(uint32_t));
516
517                 status = pic32mx_write_word(bank, address, value);
518                 if (status & NVMCON_NVMERR)
519                         return ERROR_FLASH_OPERATION_FAILED;
520                 if (status & NVMCON_LVDERR)
521                         return ERROR_FLASH_OPERATION_FAILED;
522
523                 bytes_written += 4;
524                 words_remaining--;
525                 address += 4;
526         }
527
528         if (bytes_remaining)
529         {
530                 uint32_t value = 0xffffffff;
531                 memcpy(&value, buffer + bytes_written, bytes_remaining);
532
533                 status = pic32mx_write_word(bank, address, value);
534                 if (status & NVMCON_NVMERR)
535                         return ERROR_FLASH_OPERATION_FAILED;
536                 if (status & NVMCON_LVDERR)
537                         return ERROR_FLASH_OPERATION_FAILED;
538         }
539
540         return ERROR_OK;
541 }
542
543 static int pic32mx_probe(struct flash_bank *bank)
544 {
545         struct target *target = bank->target;
546         struct pic32mx_flash_bank *pic32mx_info = bank->driver_priv;
547         struct mips32_common *mips32 = target->arch_info;
548         struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
549         int i;
550         uint16_t num_pages = 0;
551         uint32_t device_id;
552         int page_size;
553
554         pic32mx_info->probed = 0;
555
556         device_id = ejtag_info->idcode;
557         LOG_INFO("device id = 0x%08" PRIx32 " (manuf 0x%03x dev 0x%02x, ver 0x%03x)",
558                           device_id,
559                           (unsigned)((device_id >> 1)&0x7ff),
560                           (unsigned)((device_id >> 12)&0xff),
561                           (unsigned)((device_id >> 20)&0xfff));
562
563         if (((device_id >> 1)&0x7ff) != PIC32MX_MANUF_ID) {
564                 LOG_WARNING("Cannot identify target as a PIC32MX family.");
565                 return ERROR_FLASH_OPERATION_FAILED;
566         }
567
568         page_size = 4096;
569         if (bank->base == PIC32MX_KSEG1_BOOT_FLASH || bank->base == 1) {
570                 /* 0xBFC00000: Boot flash size fixed at 12k */
571                 num_pages = 12;
572         } else {
573                 /* 0xBD000000: Program flash size varies with device */
574                 for (i = 0; pic32mx_devs[i].name != NULL; i++)
575                         if (pic32mx_devs[i].devid == ((device_id >> 12) & 0xff)) {
576                                 num_pages = pic32mx_devs[i].pfm_size;
577                                 break;
578                         }
579                 if (pic32mx_devs[i].name == NULL) {
580                         LOG_WARNING("Cannot identify target as a PIC32MX family.");
581                         return ERROR_FLASH_OPERATION_FAILED;
582                 }
583         }
584
585 #if 0
586         if (bank->target->state != TARGET_HALTED)
587         {
588                 LOG_ERROR("Target not halted");
589                 return ERROR_TARGET_NOT_HALTED;
590         }
591
592         /* get flash size from target */
593         if (target_read_u16(target, 0x1FFFF7E0, &num_pages) != ERROR_OK)
594         {
595                 /* failed reading flash size, default to max target family */
596                 num_pages = 0xffff;
597         }
598 #endif
599
600         LOG_INFO("flash size = %dkbytes", num_pages);
601
602         /* calculate numbers of pages */
603         num_pages /= (page_size / 1024);
604
605         if (bank->base == 0) bank->base = PIC32MX_KSEG1_PGM_FLASH;
606         if (bank->base == 1) bank->base = PIC32MX_KSEG1_BOOT_FLASH;
607         bank->size = (num_pages * page_size);
608         bank->num_sectors = num_pages;
609         bank->chip_width = 4;
610         bank->bus_width  = 4;
611         bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
612
613         for (i = 0; i < num_pages; i++)
614         {
615                 bank->sectors[i].offset = i * page_size;
616                 bank->sectors[i].size = page_size;
617                 bank->sectors[i].is_erased = -1;
618                 bank->sectors[i].is_protected = 1;
619         }
620
621         pic32mx_info->probed = 1;
622
623         return ERROR_OK;
624 }
625
626 static int pic32mx_auto_probe(struct flash_bank *bank)
627 {
628         struct pic32mx_flash_bank *pic32mx_info = bank->driver_priv;
629         if (pic32mx_info->probed)
630                 return ERROR_OK;
631         return pic32mx_probe(bank);
632 }
633
634 #if 0
635 COMMAND_HANDLER(pic32mx_handle_part_id_command)
636 {
637         return ERROR_OK;
638 }
639 #endif
640
641 static int pic32mx_info(struct flash_bank *bank, char *buf, int buf_size)
642 {
643         struct target *target = bank->target;
644         struct mips32_common *mips32 = target->arch_info;
645         struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
646         uint32_t device_id;
647         int printed = 0, i;
648
649         device_id = ejtag_info->idcode;
650
651         if (((device_id >> 1)&0x7ff) != PIC32MX_MANUF_ID) {
652                 snprintf(buf, buf_size,
653                                  "Cannot identify target as a PIC32MX family (manufacturer 0x%03d != 0x%03d)\n",
654                                  (unsigned)((device_id >> 1)&0x7ff),
655                                  PIC32MX_MANUF_ID);
656                 return ERROR_FLASH_OPERATION_FAILED;
657         }
658         for (i = 0; pic32mx_devs[i].name != NULL; i++)
659                 if (pic32mx_devs[i].devid == ((device_id >> 12) & 0xff)) {
660                         printed = snprintf(buf, buf_size, "PIC32MX%s", pic32mx_devs[i].name);
661                         break;
662                 }
663         if (pic32mx_devs[i].name == NULL) {
664                 snprintf(buf, buf_size, "Cannot identify target as a PIC32MX family\n");
665                 return ERROR_FLASH_OPERATION_FAILED;
666         }
667         buf += printed;
668         buf_size -= printed;
669         printed = snprintf(buf, buf_size, "  Ver: 0x%03x",
670                                            (unsigned)((device_id >> 20)&0xfff));
671
672         return ERROR_OK;
673 }
674
675 #if 0
676 COMMAND_HANDLER(pic32mx_handle_lock_command)
677 {
678         struct target *target = NULL;
679         struct pic32mx_flash_bank *pic32mx_info = NULL;
680
681         if (CMD_ARGC < 1)
682         {
683                 command_print(CMD_CTX, "pic32mx lock <bank>");
684                 return ERROR_OK;
685         }
686
687         struct flash_bank *bank;
688         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
689         if (ERROR_OK != retval)
690                 return retval;
691
692         pic32mx_info = bank->driver_priv;
693
694         target = bank->target;
695
696         if (target->state != TARGET_HALTED)
697         {
698                 LOG_ERROR("Target not halted");
699                 return ERROR_TARGET_NOT_HALTED;
700         }
701
702         if (pic32mx_erase_options(bank) != ERROR_OK)
703         {
704                 command_print(CMD_CTX, "pic32mx failed to erase options");
705                 return ERROR_OK;
706         }
707
708         /* set readout protection */
709         pic32mx_info->option_bytes.RDP = 0;
710
711         if (pic32mx_write_options(bank) != ERROR_OK)
712         {
713                 command_print(CMD_CTX, "pic32mx failed to lock device");
714                 return ERROR_OK;
715         }
716
717         command_print(CMD_CTX, "pic32mx locked");
718
719         return ERROR_OK;
720 }
721
722 COMMAND_HANDLER(pic32mx_handle_unlock_command)
723 {
724         struct target *target = NULL;
725         struct pic32mx_flash_bank *pic32mx_info = NULL;
726
727         if (CMD_ARGC < 1)
728         {
729                 command_print(CMD_CTX, "pic32mx unlock <bank>");
730                 return ERROR_OK;
731         }
732
733         struct flash_bank *bank;
734         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
735         if (ERROR_OK != retval)
736                 return retval;
737
738         pic32mx_info = bank->driver_priv;
739
740         target = bank->target;
741
742         if (target->state != TARGET_HALTED)
743         {
744                 LOG_ERROR("Target not halted");
745                 return ERROR_TARGET_NOT_HALTED;
746         }
747
748         if (pic32mx_erase_options(bank) != ERROR_OK)
749         {
750                 command_print(CMD_CTX, "pic32mx failed to unlock device");
751                 return ERROR_OK;
752         }
753
754         if (pic32mx_write_options(bank) != ERROR_OK)
755         {
756                 command_print(CMD_CTX, "pic32mx failed to lock device");
757                 return ERROR_OK;
758         }
759
760         command_print(CMD_CTX, "pic32mx unlocked");
761
762         return ERROR_OK;
763 }
764 #endif
765
766 #if 0
767 static int pic32mx_chip_erase(struct flash_bank *bank)
768 {
769         struct target *target = bank->target;
770 #if 0
771         uint32_t status;
772 #endif
773
774         if (target->state != TARGET_HALTED)
775         {
776                 LOG_ERROR("Target not halted");
777                 return ERROR_TARGET_NOT_HALTED;
778         }
779
780         LOG_INFO("PIC32MX chip erase called");
781
782 #if 0
783         /* unlock option flash registers */
784         target_write_u32(target, PIC32MX_FLASH_KEYR, KEY1);
785         target_write_u32(target, PIC32MX_FLASH_KEYR, KEY2);
786
787         /* chip erase flash memory */
788         target_write_u32(target, PIC32MX_FLASH_CR, FLASH_MER);
789         target_write_u32(target, PIC32MX_FLASH_CR, FLASH_MER | FLASH_STRT);
790
791         status = pic32mx_wait_status_busy(bank, 10);
792
793         target_write_u32(target, PIC32MX_FLASH_CR, FLASH_LOCK);
794
795         if (status & FLASH_WRPRTERR)
796         {
797                 LOG_ERROR("pic32mx device protected");
798                 return ERROR_OK;
799         }
800
801         if (status & FLASH_PGERR)
802         {
803                 LOG_ERROR("pic32mx device programming failed");
804                 return ERROR_OK;
805         }
806 #endif
807
808         return ERROR_OK;
809 }
810 #endif
811
812 COMMAND_HANDLER(pic32mx_handle_chip_erase_command)
813 {
814 #if 0
815         int i;
816
817         if (CMD_ARGC != 0)
818         {
819                 command_print(CMD_CTX, "pic32mx chip_erase");
820                 return ERROR_OK;
821         }
822
823         struct flash_bank *bank;
824         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
825         if (ERROR_OK != retval)
826                 return retval;
827
828         if (pic32mx_chip_erase(bank) == ERROR_OK)
829         {
830                 /* set all sectors as erased */
831                 for (i = 0; i < bank->num_sectors; i++)
832                 {
833                         bank->sectors[i].is_erased = 1;
834                 }
835
836                 command_print(CMD_CTX, "pic32mx chip erase complete");
837         }
838         else
839         {
840                 command_print(CMD_CTX, "pic32mx chip erase failed");
841         }
842 #endif
843
844         return ERROR_OK;
845 }
846
847 COMMAND_HANDLER(pic32mx_handle_pgm_word_command)
848 {
849         uint32_t address, value;
850         int status, res;
851
852         if (CMD_ARGC != 3)
853         {
854                 command_print(CMD_CTX, "pic32mx pgm_word <addr> <value> <bank>");
855                 return ERROR_OK;
856         }
857
858         COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
859         COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
860
861         struct flash_bank *bank;
862         int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 2, &bank);
863         if (ERROR_OK != retval)
864                 return retval;
865
866         if (address < bank->base || address >= (bank->base + bank->size))
867         {
868                 command_print(CMD_CTX, "flash address '%s' is out of bounds", CMD_ARGV[0]);
869                 return ERROR_OK;
870         }
871
872         res = ERROR_OK;
873         status = pic32mx_write_word(bank, address, value);
874         if (status & NVMCON_NVMERR)
875                 res = ERROR_FLASH_OPERATION_FAILED;
876         if (status & NVMCON_LVDERR)
877                 res = ERROR_FLASH_OPERATION_FAILED;
878
879         if (res == ERROR_OK)
880                 command_print(CMD_CTX, "pic32mx pgm word complete");
881         else
882                 command_print(CMD_CTX, "pic32mx pgm word failed (status = 0x%x)", status);
883
884         return ERROR_OK;
885 }
886 static const struct command_registration pic32mx_exec_command_handlers[] = {
887         {
888                 .name = "chip_erase",
889                 .handler = &pic32mx_handle_chip_erase_command,
890                 .mode = COMMAND_EXEC,
891                 .help = "erase device",
892         },
893         {
894                 .name = "pgm_word",
895                 .handler = &pic32mx_handle_pgm_word_command,
896                 .mode = COMMAND_EXEC,
897                 .help = "program a word",
898         },
899         COMMAND_REGISTRATION_DONE
900 };
901 static const struct command_registration pic32mx_command_handlers[] = {
902         {
903                 .name = "pic32mx",
904                 .mode = COMMAND_ANY,
905                 .help = "pic32mx flash command group",
906                 .chain = pic32mx_exec_command_handlers,
907         },
908         COMMAND_REGISTRATION_DONE
909 };
910
911 struct flash_driver pic32mx_flash = {
912                 .name = "pic32mx",
913                 .commands = pic32mx_command_handlers,
914                 .flash_bank_command = &pic32mx_flash_bank_command,
915                 .erase = &pic32mx_erase,
916                 .protect = &pic32mx_protect,
917                 .write = &pic32mx_write,
918                 .probe = &pic32mx_probe,
919                 .auto_probe = &pic32mx_auto_probe,
920                 .erase_check = &default_flash_mem_blank_check,
921                 .protect_check = &pic32mx_protect_check,
922                 .info = &pic32mx_info,
923         };