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