- Added support for native MinGW builds (thanks to Spencer Oliver and Michael Fischer...
[fw/openocd] / src / flash / lpc2000.c
1 /***************************************************************************
2  *   Copyright (C) 2005 by Dominic Rath                                    *
3  *   Dominic.Rath@gmx.de                                                   *
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  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "lpc2000.h"
25
26 #include "flash.h"
27 #include "target.h"
28 #include "log.h"
29 #include "armv4_5.h"
30 #include "algorithm.h"
31 #include "binarybuffer.h"
32
33 #include <stdlib.h>
34 #include <string.h>
35
36 /* flash programming support for Philips LPC2xxx devices
37  * currently supported devices:
38  * variant 1 (lpc2000_v1):
39  * - 2104|5|6
40  * - 2114|9
41  * - 2124|9
42  * - 2194
43  * - 2212|4
44  * - 2292|4
45  *
46  * variant 2 (lpc2000_v2):
47  * - 213x
48  * - 214x
49  */
50
51 int lpc2000_register_commands(struct command_context_s *cmd_ctx);
52 int lpc2000_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
53 int lpc2000_erase(struct flash_bank_s *bank, int first, int last);
54 int lpc2000_protect(struct flash_bank_s *bank, int set, int first, int last);
55 int lpc2000_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
56 int lpc2000_probe(struct flash_bank_s *bank);
57 int lpc2000_erase_check(struct flash_bank_s *bank);
58 int lpc2000_protect_check(struct flash_bank_s *bank);
59 int lpc2000_info(struct flash_bank_s *bank, char *buf, int buf_size);
60         
61 int lpc2000_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
62
63 flash_driver_t lpc2000_flash =
64 {
65         .name = "lpc2000",
66         .register_commands = lpc2000_register_commands,
67         .flash_bank_command = lpc2000_flash_bank_command,
68         .erase = lpc2000_erase,
69         .protect = lpc2000_protect,
70         .write = lpc2000_write,
71         .probe = lpc2000_probe,
72         .erase_check = lpc2000_erase_check,
73         .protect_check = lpc2000_protect_check,
74         .info = lpc2000_info
75 };
76
77 int lpc2000_register_commands(struct command_context_s *cmd_ctx)
78 {
79         command_t *lpc2000_cmd = register_command(cmd_ctx, NULL, "lpc2000", NULL, COMMAND_ANY, NULL);
80         
81         register_command(cmd_ctx, lpc2000_cmd, "part_id", lpc2000_handle_part_id_command, COMMAND_EXEC,
82                                          "print part id of lpc2000 flash bank <num>");
83         
84         return ERROR_OK;
85 }
86
87 int lpc2000_build_sector_list(struct flash_bank_s *bank)
88 {
89         lpc2000_flash_bank_t *lpc2000_info = bank->driver_priv;
90
91         if (lpc2000_info->variant == 1)
92         {
93                 int i = 0;
94                 u32 offset = 0;
95                 
96                 /* variant 1 has different layout for 128kb and 256kb flashes */
97                 if (bank->size == 128 * 1024)
98                 {
99                         bank->num_sectors = 16;
100                         bank->sectors = malloc(sizeof(flash_sector_t) * 16);
101                         for (i = 0; i < 16; i++)
102                         {
103                                 bank->sectors[i].offset = offset;
104                                 bank->sectors[i].size = 8 * 1024;
105                                 offset += bank->sectors[i].size;
106                                 bank->sectors[i].is_erased = -1;
107                                 bank->sectors[i].is_protected = 1;
108                         }
109                 }
110                 else if (bank->size == 256 * 1024)
111                 {
112                         bank->num_sectors = 18;
113                         bank->sectors = malloc(sizeof(flash_sector_t) * 18);
114                         
115                         for (i = 0; i < 8; i++)
116                         {
117                                 bank->sectors[i].offset = offset;
118                                 bank->sectors[i].size = 8 * 1024;
119                                 offset += bank->sectors[i].size;
120                                 bank->sectors[i].is_erased = -1;
121                                 bank->sectors[i].is_protected = 1;
122                         }
123                         for (i = 8; i < 10; i++)
124                         {
125                                 bank->sectors[i].offset = offset;
126                                 bank->sectors[i].size = 64 * 1024;
127                                 offset += bank->sectors[i].size;
128                                 bank->sectors[i].is_erased = -1;
129                                 bank->sectors[i].is_protected = 1;
130                         }
131                         for (i = 10; i < 18; i++)
132                         {
133                                 bank->sectors[i].offset = offset;
134                                 bank->sectors[i].size = 8 * 1024;
135                                 offset += bank->sectors[i].size;
136                                 bank->sectors[i].is_erased = -1;
137                                 bank->sectors[i].is_protected = 1;
138                         }
139                 }
140                 else
141                 {
142                         ERROR("BUG: unknown bank->size encountered");
143                         exit(-1);
144                 }
145         }
146         else if (lpc2000_info->variant == 2)
147         {
148                 int num_sectors;
149                 int i;
150                 u32 offset = 0;
151         
152                 /* variant 2 has a uniform layout, only number of sectors differs */
153                 switch (bank->size)
154                 {
155                         case 32 * 1024:
156                                 num_sectors = 8;
157                                 break;
158                         case 64 * 1024:
159                                 num_sectors = 9;
160                                 break;
161                         case 128 * 1024:
162                                 num_sectors = 11;
163                                 break;
164                         case 256 * 1024:
165                                 num_sectors = 15;
166                                 break;
167                         case 500 * 1024:
168                                 num_sectors = 27;
169                                 break;
170                         default:
171                                 ERROR("BUG: unknown bank->size encountered");
172                                 exit(-1);
173                                 break;
174                 }
175                 
176                 bank->num_sectors = num_sectors;
177                 bank->sectors = malloc(sizeof(flash_sector_t) * num_sectors);
178
179                 for (i = 0; i < num_sectors; i++)
180                 {
181                         if ((i >= 0) && (i < 8))
182                         {
183                                 bank->sectors[i].offset = offset;
184                                 bank->sectors[i].size = 4 * 1024;
185                                 offset += bank->sectors[i].size;
186                                 bank->sectors[i].is_erased = -1;
187                                 bank->sectors[i].is_protected = 1;
188                         }
189                         if ((i >= 8) && (i < 22))
190                         {
191                                 bank->sectors[i].offset = offset;
192                                 bank->sectors[i].size = 32 * 1024;
193                                 offset += bank->sectors[i].size;
194                                 bank->sectors[i].is_erased = -1;
195                                 bank->sectors[i].is_protected = 1;
196                         }
197                         if ((i >= 22) && (i < 27))
198                         {
199                                 bank->sectors[i].offset = offset;
200                                 bank->sectors[i].size = 4 * 1024;
201                                 offset += bank->sectors[i].size;
202                                 bank->sectors[i].is_erased = -1;
203                                 bank->sectors[i].is_protected = 1;
204                         }
205                 }
206         }
207         else
208         {
209                 ERROR("BUG: unknown lpc2000_info->variant encountered");
210                 exit(-1);
211         }
212         
213         return ERROR_OK;
214 }
215
216 /* call LPC2000 IAP function
217  * uses 172 bytes working area
218  * 0x0 to 0x7: jump gate (BX to thumb state, b -2 to wait)
219  * 0x8 to 0x1f: command parameter table
220  * 0x20 to 0x2b: command result table
221  * 0x2c to 0xac: stack (only 128b needed)
222  */
223 int lpc2000_iap_call(flash_bank_t *bank, int code, u32 param_table[5], u32 result_table[2])
224 {
225         lpc2000_flash_bank_t *lpc2000_info = bank->driver_priv;
226         target_t *target = lpc2000_info->target;
227         mem_param_t mem_params[2];
228         reg_param_t reg_params[5];
229         armv4_5_algorithm_t armv4_5_info;
230         u32 status_code;
231         
232         /* regrab previously allocated working_area, or allocate a new one */
233         if (!lpc2000_info->iap_working_area)
234         {
235                 u8 jump_gate[8];
236                 
237                 /* make sure we have a working area */
238                 if (target_alloc_working_area(target, 172, &lpc2000_info->iap_working_area) != ERROR_OK)
239                 {
240                         ERROR("no working area specified, can't write LPC2000 internal flash");
241                         return ERROR_FLASH_OPERATION_FAILED;
242                 }
243                 
244                 /* write IAP code to working area */
245                 buf_set_u32(jump_gate, 0, 32, ARMV4_5_BX(12));
246                 buf_set_u32(jump_gate, 32, 32, 0xeafffffe);
247                 target->type->write_memory(target, lpc2000_info->iap_working_area->address, 4, 2, (u8*)jump_gate);
248         }
249         
250         armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
251         armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
252         armv4_5_info.core_state = ARMV4_5_STATE_ARM;
253         
254         /* command parameter table */
255         init_mem_param(&mem_params[0], lpc2000_info->iap_working_area->address + 8, 4 * 6, PARAM_OUT);
256         buf_set_u32(mem_params[0].value, 0, 32, code);
257         buf_set_u32(mem_params[0].value, 32, 32, param_table[0]);
258         buf_set_u32(mem_params[0].value, 64, 32, param_table[1]);
259         buf_set_u32(mem_params[0].value, 96, 32, param_table[2]);
260         buf_set_u32(mem_params[0].value, 128, 32, param_table[3]);
261         buf_set_u32(mem_params[0].value, 160, 32, param_table[4]);
262         
263         init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
264         buf_set_u32(reg_params[0].value, 0, 32, lpc2000_info->iap_working_area->address + 0x8);
265         
266         /* command result table */
267         init_mem_param(&mem_params[1], lpc2000_info->iap_working_area->address + 0x20, 4 * 3, PARAM_IN);
268         
269         init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
270         buf_set_u32(reg_params[1].value, 0, 32, lpc2000_info->iap_working_area->address + 0x20);
271         
272         /* IAP entry point */
273         init_reg_param(&reg_params[2], "r12", 32, PARAM_OUT);
274         buf_set_u32(reg_params[2].value, 0, 32, 0x7ffffff1);
275         
276         /* IAP stack */
277         init_reg_param(&reg_params[3], "r13_svc", 32, PARAM_OUT);
278         buf_set_u32(reg_params[3].value, 0, 32, lpc2000_info->iap_working_area->address + 0xac);
279
280         /* return address */
281         init_reg_param(&reg_params[4], "lr_svc", 32, PARAM_OUT);
282         buf_set_u32(reg_params[4].value, 0, 32, lpc2000_info->iap_working_area->address + 0x4);
283         
284         target->type->run_algorithm(target, 2, mem_params, 5, reg_params, lpc2000_info->iap_working_area->address, lpc2000_info->iap_working_area->address + 0x4, 10000, &armv4_5_info);
285         
286         status_code = buf_get_u32(mem_params[1].value, 0, 32);
287         result_table[0] = buf_get_u32(mem_params[1].value, 32, 32);
288         result_table[1] = buf_get_u32(mem_params[1].value, 64, 32);
289         
290         destroy_mem_param(&mem_params[0]);
291         destroy_mem_param(&mem_params[1]);
292         
293         destroy_reg_param(&reg_params[0]);
294         destroy_reg_param(&reg_params[1]);
295         destroy_reg_param(&reg_params[2]);
296         destroy_reg_param(&reg_params[3]);
297         destroy_reg_param(&reg_params[4]);
298         
299         return status_code;
300 }
301
302 int lpc2000_iap_blank_check(struct flash_bank_s *bank, int first, int last)
303 {
304         u32 param_table[5];
305         u32 result_table[2];
306         int status_code;
307         int i;
308         
309         if ((first < 0) || (last > bank->num_sectors))
310                 return ERROR_FLASH_SECTOR_INVALID;
311         
312         for (i = first; i <= last; i++)
313         {
314                 /* check single sector */
315                 param_table[0] = param_table[1] = i;
316                 status_code = lpc2000_iap_call(bank, 53, param_table, result_table);
317                 
318                 switch (status_code)
319                 {
320                         case ERROR_FLASH_OPERATION_FAILED:
321                                 return ERROR_FLASH_OPERATION_FAILED;
322                         case LPC2000_CMD_SUCCESS:
323                                 bank->sectors[i].is_erased = 1;
324                                 break;
325                         case LPC2000_SECTOR_NOT_BLANK:
326                                 bank->sectors[i].is_erased = 0;
327                                 break;
328                         case LPC2000_INVALID_SECTOR:
329                                 bank->sectors[i].is_erased = 0;
330                                 break;
331                         case LPC2000_BUSY:
332                                 return ERROR_FLASH_BUSY;
333                                 break;
334                         default:
335                                 ERROR("BUG: unknown LPC2000 status code");
336                                 exit(-1);
337                 }
338         }
339         
340         return ERROR_OK;
341 }
342
343 /* flash_bank lpc2000 <base> <size> 0 0 <lpc_variant> <target#> <cclk> [calc_checksum]
344  */
345 int lpc2000_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
346 {
347         lpc2000_flash_bank_t *lpc2000_info;
348         
349         if (argc < 8)
350         {
351                 WARNING("incomplete flash_bank lpc2000 configuration");
352                 return ERROR_FLASH_BANK_INVALID;
353         }
354         
355         lpc2000_info = malloc(sizeof(lpc2000_flash_bank_t));
356         bank->driver_priv = lpc2000_info;
357         
358         if (strcmp(args[5], "lpc2000_v1") == 0)
359         {
360                 lpc2000_info->variant = 1;
361                 lpc2000_info->cmd51_dst_boundary = 512;
362                 lpc2000_info->cmd51_can_256b = 0;
363                 lpc2000_info->cmd51_can_8192b = 1;
364         }
365         else if (strcmp(args[5], "lpc2000_v2") == 0)
366         {
367                 lpc2000_info->variant = 2;
368                 lpc2000_info->cmd51_dst_boundary = 256;
369                 lpc2000_info->cmd51_can_256b = 1;
370                 lpc2000_info->cmd51_can_8192b = 0;
371         }
372         else
373         {
374                 ERROR("unknown LPC2000 variant");
375                 free(lpc2000_info);
376                 return ERROR_FLASH_BANK_INVALID;
377         }
378         
379         lpc2000_info->target = get_target_by_num(strtoul(args[6], NULL, 0));
380         if (!lpc2000_info->target)
381         {
382                 ERROR("no target '%s' configured", args[6]);
383                 exit(-1);
384         }
385         lpc2000_info->iap_working_area = NULL;
386         lpc2000_info->cclk = strtoul(args[7], NULL, 0);
387         lpc2000_info->calc_checksum = 0;
388         lpc2000_build_sector_list(bank);
389         
390         
391         if (argc >= 9)
392         {
393                 if (strcmp(args[8], "calc_checksum") == 0)
394                         lpc2000_info->calc_checksum = 1;
395         }
396         
397         return ERROR_OK;
398 }
399
400 int lpc2000_erase(struct flash_bank_s *bank, int first, int last)
401 {
402         lpc2000_flash_bank_t *lpc2000_info = bank->driver_priv;
403         u32 param_table[5];
404         u32 result_table[2];
405         int status_code;
406         
407         if (lpc2000_info->target->state != TARGET_HALTED)
408         {
409                 return ERROR_TARGET_NOT_HALTED;
410         }
411         
412         if ((first < 0) || (last < first) || (last >= bank->num_sectors))
413         {
414                 return ERROR_FLASH_SECTOR_INVALID;
415         }
416         
417         param_table[0] = first;
418         param_table[1] = last;
419         param_table[2] = lpc2000_info->cclk;
420         
421         /* Prepare sectors */
422         status_code = lpc2000_iap_call(bank, 50, param_table, result_table);
423         switch (status_code)
424         {
425                 case ERROR_FLASH_OPERATION_FAILED:
426                         return ERROR_FLASH_OPERATION_FAILED;
427                 case LPC2000_CMD_SUCCESS:
428                         break;
429                 case LPC2000_INVALID_SECTOR:
430                         return ERROR_FLASH_SECTOR_INVALID;
431                         break;
432                 default:
433                         WARNING("lpc2000 prepare sectors returned %i", status_code);
434                         return ERROR_FLASH_OPERATION_FAILED;
435         }
436         
437         /* Erase sectors */
438         status_code = lpc2000_iap_call(bank, 52, param_table, result_table);
439         switch (status_code)
440         {
441                 case ERROR_FLASH_OPERATION_FAILED:
442                         return ERROR_FLASH_OPERATION_FAILED;
443                 case LPC2000_CMD_SUCCESS:
444                         break;
445                 case LPC2000_INVALID_SECTOR:
446                         return ERROR_FLASH_SECTOR_INVALID;
447                         break;
448                 default:
449                         WARNING("lpc2000 erase sectors returned %i", status_code);
450                         return ERROR_FLASH_OPERATION_FAILED;
451         }
452         
453         return ERROR_OK;
454 }
455
456 int lpc2000_protect(struct flash_bank_s *bank, int set, int first, int last)
457 {
458         /* can't protect/unprotect on the lpc2000 */
459         return ERROR_OK;
460 }
461
462 int lpc2000_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
463 {
464         lpc2000_flash_bank_t *lpc2000_info = bank->driver_priv;
465         target_t *target = lpc2000_info->target;
466         u32 dst_min_alignment;
467         u32 bytes_remaining = count;
468         u32 bytes_written = 0;
469         int first_sector = 0;
470         int last_sector = 0;
471         u32 param_table[5];
472         u32 result_table[2];
473         int status_code;
474         int i;
475         working_area_t *download_area;
476                  
477         if (lpc2000_info->target->state != TARGET_HALTED)
478         {
479                 return ERROR_TARGET_NOT_HALTED;
480         }
481         
482         /* allocate a working area */
483         if (target_alloc_working_area(target, 4096, &download_area) != ERROR_OK)
484         {
485                 ERROR("no working area specified, can't write LPC2000 internal flash");
486                 return ERROR_FLASH_OPERATION_FAILED;
487         }
488         
489         if (offset + count > bank->size)
490                 return ERROR_FLASH_DST_OUT_OF_BANK;
491         
492         if (lpc2000_info->cmd51_can_256b)
493                 dst_min_alignment = 256;
494         else
495                 dst_min_alignment = 512;
496         
497         if (offset % dst_min_alignment)
498         {
499                 WARNING("offset 0x%x breaks required alignment 0x%x", offset, dst_min_alignment);
500                 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
501         }
502         
503         for (i = 0; i < bank->num_sectors; i++)
504         {
505                 if (offset >= bank->sectors[i].offset)
506                         first_sector = i;
507                 if (offset + CEIL(count, dst_min_alignment) * dst_min_alignment > bank->sectors[i].offset)
508                         last_sector = i;
509         }
510         
511         DEBUG("first_sector: %i, last_sector: %i", first_sector, last_sector);
512
513         /* check if exception vectors should be flashed */
514         if ((offset == 0) && (count >= 0x20) && lpc2000_info->calc_checksum)
515         {
516                 u32 checksum = 0;
517                 int i = 0;
518                 for (i = 0; i < 8; i++)
519                 {
520                         DEBUG("0x%2.2x: 0x%8.8x", i * 4, buf_get_u32(buffer + (i * 4), 0, 32));
521                         if (i != 5)
522                                 checksum += buf_get_u32(buffer + (i * 4), 0, 32);
523                 }
524                 checksum = 0 - checksum;
525                 DEBUG("checksum: 0x%8.8x", checksum);
526                 buf_set_u32(buffer + 0x14, 0, 32, checksum);
527         }
528         
529         while (bytes_remaining > 0)
530         {
531                 u32 thisrun_bytes;
532                 if (bytes_remaining >= 4096)
533                         thisrun_bytes = 4096;
534                 else if (bytes_remaining >= 1024)
535                         thisrun_bytes = 1024;
536                 else if ((bytes_remaining >= 512) || (!lpc2000_info->cmd51_can_256b))
537                         thisrun_bytes = 512;
538                 else
539                         thisrun_bytes = 256;
540                 
541                 /* Prepare sectors */
542                 param_table[0] = first_sector;
543                 param_table[1] = last_sector;
544                 status_code = lpc2000_iap_call(bank, 50, param_table, result_table);
545                 switch (status_code)
546                 {
547                         case ERROR_FLASH_OPERATION_FAILED:
548                                 return ERROR_FLASH_OPERATION_FAILED;
549                         case LPC2000_CMD_SUCCESS:
550                                 break;
551                         case LPC2000_INVALID_SECTOR:
552                                 return ERROR_FLASH_SECTOR_INVALID;
553                                 break;
554                         default:
555                                 WARNING("lpc2000 prepare sectors returned %i", status_code);
556                                 return ERROR_FLASH_OPERATION_FAILED;
557                 }
558                 
559                 if (bytes_remaining >= thisrun_bytes)
560                 {
561                         if (target_write_buffer(lpc2000_info->target, download_area->address, thisrun_bytes, buffer + bytes_written) != ERROR_OK)
562                         {
563                                 target_free_working_area(target, download_area);
564                                 return ERROR_FLASH_OPERATION_FAILED;
565                         }
566                 }
567                 else
568                 {
569                         u8 *last_buffer = malloc(thisrun_bytes);
570                         int i;
571                         memcpy(last_buffer, buffer + bytes_written, bytes_remaining);
572                         for (i = bytes_remaining; i < thisrun_bytes; i++)
573                                 last_buffer[i] = 0xff;
574                         target_write_buffer(lpc2000_info->target, download_area->address, thisrun_bytes, last_buffer);
575                         free(last_buffer);
576                 }
577                 
578                 DEBUG("writing 0x%x bytes to address 0x%x", thisrun_bytes, bank->base + offset + bytes_written);
579                 
580                 /* Write data */
581                 param_table[0] = bank->base + offset + bytes_written;
582                 param_table[1] = download_area->address;
583                 param_table[2] = thisrun_bytes;
584                 param_table[3] = lpc2000_info->cclk;
585                 status_code = lpc2000_iap_call(bank, 51, param_table, result_table);
586                 switch (status_code)
587                 {
588                         case ERROR_FLASH_OPERATION_FAILED:
589                                 return ERROR_FLASH_OPERATION_FAILED;
590                         case LPC2000_CMD_SUCCESS:
591                                 break;
592                         case LPC2000_INVALID_SECTOR:
593                                 return ERROR_FLASH_SECTOR_INVALID;
594                                 break;
595                         default:
596                                 WARNING("lpc2000 returned %i", status_code);
597                                 return ERROR_FLASH_OPERATION_FAILED;
598                 }
599                 
600                 if (bytes_remaining > thisrun_bytes)
601                         bytes_remaining -= thisrun_bytes;
602                 else
603                         bytes_remaining = 0;
604                 bytes_written += thisrun_bytes;
605         }
606         
607         target_free_working_area(target, download_area);
608         
609         return ERROR_OK;
610 }
611
612 int lpc2000_probe(struct flash_bank_s *bank)
613 {
614         /* we can't probe on an lpc2000 
615          * if this is an lpc2xxx, it has the configured flash
616          */
617         return ERROR_OK;
618 }
619
620 int lpc2000_erase_check(struct flash_bank_s *bank)
621 {
622         lpc2000_flash_bank_t *lpc2000_info = bank->driver_priv;
623         
624         if (lpc2000_info->target->state != TARGET_HALTED)
625         {
626                 return ERROR_TARGET_NOT_HALTED;
627         }
628         
629         return lpc2000_iap_blank_check(bank, 0, bank->num_sectors - 1);
630 }
631
632 int lpc2000_protect_check(struct flash_bank_s *bank)
633 {
634         /* sectors are always protected */
635         return ERROR_OK;
636 }
637
638 int lpc2000_info(struct flash_bank_s *bank, char *buf, int buf_size)
639 {
640         lpc2000_flash_bank_t *lpc2000_info = bank->driver_priv;
641
642         snprintf(buf, buf_size, "lpc2000 flash driver variant: %i, clk: %i", lpc2000_info->variant, lpc2000_info->cclk);
643         
644         return ERROR_OK;
645 }
646
647 int lpc2000_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
648 {
649         flash_bank_t *bank;
650         u32 param_table[5];
651         u32 result_table[2];
652         int status_code;
653         lpc2000_flash_bank_t *lpc2000_info;
654
655         if (argc < 1)
656         {
657                 command_print(cmd_ctx, "usage: lpc2000 part_id <num>");
658                 return ERROR_OK;
659         }
660         
661         bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
662         if (!bank)
663         {
664                 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
665                 return ERROR_OK;
666         }
667
668         lpc2000_info = bank->driver_priv;
669         if (lpc2000_info->target->state != TARGET_HALTED)
670         {
671                 return ERROR_TARGET_NOT_HALTED;
672         }
673         
674         if ((status_code = lpc2000_iap_call(bank, 54, param_table, result_table)) != 0x0)
675         {
676                 if (status_code == ERROR_FLASH_OPERATION_FAILED)
677                 {
678                         command_print(cmd_ctx, "no sufficient working area specified, can't access LPC2000 IAP interface");
679                         return ERROR_OK;
680                 }
681                 command_print(cmd_ctx, "lpc2000 IAP returned status code %i", status_code);
682         }
683         else
684         {
685                 command_print(cmd_ctx, "lpc2000 part id: 0x%8.8x", result_table[0]);
686         }
687         
688         return ERROR_OK;
689 }