f7bc3c61b5b39c8aed9c2c5edf0de310c6a2ec09
[fw/openocd] / src / flash / str9x.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 Oyvind Harboe                                   *
9  *   oyvind.harboe@zylin.com                                               *
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 "str9x.h"
31 #include "arm966e.h"
32
33
34 static uint32_t bank1start = 0x00080000;
35
36 static int str9x_build_block_list(struct flash_bank_s *bank)
37 {
38         struct str9x_flash_bank *str9x_info = bank->driver_priv;
39
40         int i;
41         int num_sectors;
42         int b0_sectors = 0, b1_sectors = 0;
43         uint32_t offset = 0;
44
45         /* set if we have large flash str9 */
46         str9x_info->variant = 0;
47         str9x_info->bank1 = 0;
48
49         switch (bank->size)
50         {
51                 case (256 * 1024):
52                         b0_sectors = 4;
53                         break;
54                 case (512 * 1024):
55                         b0_sectors = 8;
56                         break;
57                 case (1024 * 1024):
58                         bank1start = 0x00100000;
59                         str9x_info->variant = 1;
60                         b0_sectors = 16;
61                         break;
62                 case (2048 * 1024):
63                         bank1start = 0x00200000;
64                         str9x_info->variant = 1;
65                         b0_sectors = 32;
66                         break;
67                 case (128 * 1024):
68                         str9x_info->variant = 1;
69                         str9x_info->bank1 = 1;
70                         b1_sectors = 8;
71                         bank1start = bank->base;
72                         break;
73                 case (32 * 1024):
74                         str9x_info->bank1 = 1;
75                         b1_sectors = 4;
76                         bank1start = bank->base;
77                         break;
78                 default:
79                         LOG_ERROR("BUG: unknown bank->size encountered");
80                         exit(-1);
81         }
82
83         num_sectors = b0_sectors + b1_sectors;
84
85         bank->num_sectors = num_sectors;
86         bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
87         str9x_info->sector_bits = malloc(sizeof(uint32_t) * num_sectors);
88
89         num_sectors = 0;
90
91         for (i = 0; i < b0_sectors; i++)
92         {
93                 bank->sectors[num_sectors].offset = offset;
94                 bank->sectors[num_sectors].size = 0x10000;
95                 offset += bank->sectors[i].size;
96                 bank->sectors[num_sectors].is_erased = -1;
97                 bank->sectors[num_sectors].is_protected = 1;
98                 str9x_info->sector_bits[num_sectors++] = (1 << i);
99         }
100
101         for (i = 0; i < b1_sectors; i++)
102         {
103                 bank->sectors[num_sectors].offset = offset;
104                 bank->sectors[num_sectors].size = str9x_info->variant == 0 ? 0x2000 : 0x4000;
105                 offset += bank->sectors[i].size;
106                 bank->sectors[num_sectors].is_erased = -1;
107                 bank->sectors[num_sectors].is_protected = 1;
108                 if (str9x_info->variant)
109                         str9x_info->sector_bits[num_sectors++] = (1 << i);
110                 else
111                         str9x_info->sector_bits[num_sectors++] = (1 << (i + 8));
112         }
113
114         return ERROR_OK;
115 }
116
117 /* flash bank str9x <base> <size> 0 0 <target#>
118  */
119 FLASH_BANK_COMMAND_HANDLER(str9x_flash_bank_command)
120 {
121         struct str9x_flash_bank *str9x_info;
122
123         if (argc < 6)
124         {
125                 LOG_WARNING("incomplete flash_bank str9x configuration");
126                 return ERROR_FLASH_BANK_INVALID;
127         }
128
129         str9x_info = malloc(sizeof(struct str9x_flash_bank));
130         bank->driver_priv = str9x_info;
131
132         str9x_build_block_list(bank);
133
134         str9x_info->write_algorithm = NULL;
135
136         return ERROR_OK;
137 }
138
139 static int str9x_protect_check(struct flash_bank_s *bank)
140 {
141         int retval;
142         struct str9x_flash_bank *str9x_info = bank->driver_priv;
143         struct target *target = bank->target;
144
145         int i;
146         uint32_t adr;
147         uint32_t status = 0;
148         uint16_t hstatus = 0;
149
150         if (bank->target->state != TARGET_HALTED)
151         {
152                 LOG_ERROR("Target not halted");
153                 return ERROR_TARGET_NOT_HALTED;
154         }
155
156         /* read level one protection */
157
158         if (str9x_info->variant)
159         {
160                 if (str9x_info->bank1)
161                 {
162                         adr = bank1start + 0x18;
163                         if ((retval = target_write_u16(target, adr, 0x90)) != ERROR_OK)
164                         {
165                                 return retval;
166                         }
167                         if ((retval = target_read_u16(target, adr, &hstatus)) != ERROR_OK)
168                         {
169                                 return retval;
170                         }
171                         status = hstatus;
172                 }
173                 else
174                 {
175                         adr = bank1start + 0x14;
176                         if ((retval = target_write_u16(target, adr, 0x90)) != ERROR_OK)
177                         {
178                                 return retval;
179                         }
180                         if ((retval = target_read_u32(target, adr, &status)) != ERROR_OK)
181                         {
182                                 return retval;
183                         }
184                 }
185         }
186         else
187         {
188                 adr = bank1start + 0x10;
189                 if ((retval = target_write_u16(target, adr, 0x90)) != ERROR_OK)
190                 {
191                         return retval;
192                 }
193                 if ((retval = target_read_u16(target, adr, &hstatus)) != ERROR_OK)
194                 {
195                         return retval;
196                 }
197                 status = hstatus;
198         }
199
200         /* read array command */
201         if ((retval = target_write_u16(target, adr, 0xFF)) != ERROR_OK)
202         {
203                 return retval;
204         }
205
206         for (i = 0; i < bank->num_sectors; i++)
207         {
208                 if (status & str9x_info->sector_bits[i])
209                         bank->sectors[i].is_protected = 1;
210                 else
211                         bank->sectors[i].is_protected = 0;
212         }
213
214         return ERROR_OK;
215 }
216
217 static int str9x_erase(struct flash_bank_s *bank, int first, int last)
218 {
219         struct target *target = bank->target;
220         int i;
221         uint32_t adr;
222         uint8_t status;
223         uint8_t erase_cmd;
224
225         if (bank->target->state != TARGET_HALTED)
226         {
227                 LOG_ERROR("Target not halted");
228                 return ERROR_TARGET_NOT_HALTED;
229         }
230
231         /* Check if we erase whole bank */
232         if ((first == 0) && (last == (bank->num_sectors - 1)))
233         {
234                 /* Optimize to run erase bank command instead of sector */
235                 erase_cmd = 0x80;
236         }
237         else
238         {
239                 /* Erase sector command */
240                 erase_cmd = 0x20;
241         }
242
243         for (i = first; i <= last; i++)
244         {
245                 int retval;
246                 adr = bank->base + bank->sectors[i].offset;
247
248                 /* erase sectors */
249                 if ((retval = target_write_u16(target, adr, erase_cmd)) != ERROR_OK)
250                 {
251                         return retval;
252                 }
253                 if ((retval = target_write_u16(target, adr, 0xD0)) != ERROR_OK)
254                 {
255                         return retval;
256                 }
257
258                 /* get status */
259                 if ((retval = target_write_u16(target, adr, 0x70)) != ERROR_OK)
260                 {
261                         return retval;
262                 }
263
264                 int timeout;
265                 for (timeout = 0; timeout < 1000; timeout++) {
266                         if ((retval = target_read_u8(target, adr, &status)) != ERROR_OK)
267                         {
268                                 return retval;
269                         }
270                         if (status & 0x80)
271                                 break;
272                         alive_sleep(1);
273                 }
274                 if (timeout == 1000)
275                 {
276                         LOG_ERROR("erase timed out");
277                         return ERROR_FAIL;
278                 }
279
280                 /* clear status, also clear read array */
281                 if ((retval = target_write_u16(target, adr, 0x50)) != ERROR_OK)
282                 {
283                         return retval;
284                 }
285
286                 /* read array command */
287                 if ((retval = target_write_u16(target, adr, 0xFF)) != ERROR_OK)
288                 {
289                         return retval;
290                 }
291
292                 if (status & 0x22)
293                 {
294                         LOG_ERROR("error erasing flash bank, status: 0x%x", status);
295                         return ERROR_FLASH_OPERATION_FAILED;
296                 }
297
298                 /* If we ran erase bank command, we are finished */
299                 if (erase_cmd == 0x80)
300                         break;
301         }
302
303         for (i = first; i <= last; i++)
304                 bank->sectors[i].is_erased = 1;
305
306         return ERROR_OK;
307 }
308
309 static int str9x_protect(struct flash_bank_s *bank,
310                 int set, int first, int last)
311 {
312         struct target *target = bank->target;
313         int i;
314         uint32_t adr;
315         uint8_t status;
316
317         if (bank->target->state != TARGET_HALTED)
318         {
319                 LOG_ERROR("Target not halted");
320                 return ERROR_TARGET_NOT_HALTED;
321         }
322
323         for (i = first; i <= last; i++)
324         {
325                 /* Level One Protection */
326
327                 adr = bank->base + bank->sectors[i].offset;
328
329                 target_write_u16(target, adr, 0x60);
330                 if (set)
331                         target_write_u16(target, adr, 0x01);
332                 else
333                         target_write_u16(target, adr, 0xD0);
334
335                 /* query status */
336                 target_read_u8(target, adr, &status);
337
338                 /* clear status, also clear read array */
339                 target_write_u16(target, adr, 0x50);
340
341                 /* read array command */
342                 target_write_u16(target, adr, 0xFF);
343         }
344
345         return ERROR_OK;
346 }
347
348 static int str9x_write_block(struct flash_bank_s *bank,
349                 uint8_t *buffer, uint32_t offset, uint32_t count)
350 {
351         struct str9x_flash_bank *str9x_info = bank->driver_priv;
352         struct target *target = bank->target;
353         uint32_t buffer_size = 8192;
354         struct working_area *source;
355         uint32_t address = bank->base + offset;
356         struct reg_param reg_params[4];
357         struct armv4_5_algorithm armv4_5_info;
358         int retval = ERROR_OK;
359
360         uint32_t str9x_flash_write_code[] = {
361                                         /* write:                               */
362                 0xe3c14003,     /*      bic     r4, r1, #3              */
363                 0xe3a03040,     /*      mov     r3, #0x40               */
364                 0xe1c430b0,     /*      strh r3, [r4, #0]       */
365                 0xe0d030b2,     /*      ldrh r3, [r0], #2       */
366                 0xe0c130b2,     /*      strh r3, [r1], #2       */
367                 0xe3a03070,     /*      mov r3, #0x70           */
368                 0xe1c430b0,     /*      strh r3, [r4, #0]       */
369                                         /* busy:                                */
370                 0xe5d43000,     /*      ldrb r3, [r4, #0]       */
371                 0xe3130080,     /*      tst r3, #0x80           */
372                 0x0afffffc,     /*      beq busy                        */
373                 0xe3a05050,     /*      mov     r5, #0x50               */
374                 0xe1c450b0,     /*      strh r5, [r4, #0]       */
375                 0xe3a050ff,     /*      mov     r5, #0xFF               */
376                 0xe1c450b0,     /*      strh r5, [r4, #0]       */
377                 0xe3130012,     /*      tst     r3, #0x12               */
378                 0x1a000001,     /*      bne exit                        */
379                 0xe2522001,     /*      subs r2, r2, #1         */
380                 0x1affffed,     /*      bne write                       */
381                                         /* exit:                                */
382                 0xeafffffe,     /*      b exit                          */
383         };
384
385         /* flash write code */
386         if (target_alloc_working_area(target, 4 * 19, &str9x_info->write_algorithm) != ERROR_OK)
387         {
388                 LOG_WARNING("no working area available, can't do block memory writes");
389                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
390         };
391
392         target_write_buffer(target, str9x_info->write_algorithm->address, 19 * 4, (uint8_t*)str9x_flash_write_code);
393
394         /* memory buffer */
395         while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
396         {
397                 buffer_size /= 2;
398                 if (buffer_size <= 256)
399                 {
400                         /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
401                         if (str9x_info->write_algorithm)
402                                 target_free_working_area(target, str9x_info->write_algorithm);
403
404                         LOG_WARNING("no large enough working area available, can't do block memory writes");
405                         return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
406                 }
407         }
408
409         armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
410         armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
411         armv4_5_info.core_state = ARMV4_5_STATE_ARM;
412
413         init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
414         init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
415         init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
416         init_reg_param(&reg_params[3], "r3", 32, PARAM_IN);
417
418         while (count > 0)
419         {
420                 uint32_t thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count;
421
422                 target_write_buffer(target, source->address, thisrun_count * 2, buffer);
423
424                 buf_set_u32(reg_params[0].value, 0, 32, source->address);
425                 buf_set_u32(reg_params[1].value, 0, 32, address);
426                 buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
427
428                 if ((retval = target_run_algorithm(target, 0, NULL, 4, reg_params, str9x_info->write_algorithm->address, str9x_info->write_algorithm->address + (18 * 4), 10000, &armv4_5_info)) != ERROR_OK)
429                 {
430                         LOG_ERROR("error executing str9x flash write algorithm");
431                         retval = ERROR_FLASH_OPERATION_FAILED;
432                         break;
433                 }
434
435                 if (buf_get_u32(reg_params[3].value, 0, 32) != 0x80)
436                 {
437                         retval = ERROR_FLASH_OPERATION_FAILED;
438                         break;
439                 }
440
441                 buffer += thisrun_count * 2;
442                 address += thisrun_count * 2;
443                 count -= thisrun_count;
444         }
445
446         target_free_working_area(target, source);
447         target_free_working_area(target, str9x_info->write_algorithm);
448
449         destroy_reg_param(&reg_params[0]);
450         destroy_reg_param(&reg_params[1]);
451         destroy_reg_param(&reg_params[2]);
452         destroy_reg_param(&reg_params[3]);
453
454         return retval;
455 }
456
457 static int str9x_write(struct flash_bank_s *bank,
458                 uint8_t *buffer, uint32_t offset, uint32_t count)
459 {
460         struct target *target = bank->target;
461         uint32_t words_remaining = (count / 2);
462         uint32_t bytes_remaining = (count & 0x00000001);
463         uint32_t address = bank->base + offset;
464         uint32_t bytes_written = 0;
465         uint8_t status;
466         int retval;
467         uint32_t check_address = offset;
468         uint32_t bank_adr;
469         int i;
470
471         if (bank->target->state != TARGET_HALTED)
472         {
473                 LOG_ERROR("Target not halted");
474                 return ERROR_TARGET_NOT_HALTED;
475         }
476
477         if (offset & 0x1)
478         {
479                 LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
480                 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
481         }
482
483         for (i = 0; i < bank->num_sectors; i++)
484         {
485                 uint32_t sec_start = bank->sectors[i].offset;
486                 uint32_t sec_end = sec_start + bank->sectors[i].size;
487
488                 /* check if destination falls within the current sector */
489                 if ((check_address >= sec_start) && (check_address < sec_end))
490                 {
491                         /* check if destination ends in the current sector */
492                         if (offset + count < sec_end)
493                                 check_address = offset + count;
494                         else
495                                 check_address = sec_end;
496                 }
497         }
498
499         if (check_address != offset + count)
500                 return ERROR_FLASH_DST_OUT_OF_BANK;
501
502         /* multiple half words (2-byte) to be programmed? */
503         if (words_remaining > 0)
504         {
505                 /* try using a block write */
506                 if ((retval = str9x_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK)
507                 {
508                         if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
509                         {
510                                 /* if block write failed (no sufficient working area),
511                                  * we use normal (slow) single dword accesses */
512                                 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
513                         }
514                         else if (retval == ERROR_FLASH_OPERATION_FAILED)
515                         {
516                                 LOG_ERROR("flash writing failed with error code: 0x%x", retval);
517                                 return ERROR_FLASH_OPERATION_FAILED;
518                         }
519                 }
520                 else
521                 {
522                         buffer += words_remaining * 2;
523                         address += words_remaining * 2;
524                         words_remaining = 0;
525                 }
526         }
527
528         while (words_remaining > 0)
529         {
530                 bank_adr = address & ~0x03;
531
532                 /* write data command */
533                 target_write_u16(target, bank_adr, 0x40);
534                 target_write_memory(target, address, 2, 1, buffer + bytes_written);
535
536                 /* get status command */
537                 target_write_u16(target, bank_adr, 0x70);
538
539                 int timeout;
540                 for (timeout = 0; timeout < 1000; timeout++)
541                 {
542                         target_read_u8(target, bank_adr, &status);
543                         if (status & 0x80)
544                                 break;
545                         alive_sleep(1);
546                 }
547                 if (timeout == 1000)
548                 {
549                         LOG_ERROR("write timed out");
550                         return ERROR_FAIL;
551                 }
552
553                 /* clear status reg and read array */
554                 target_write_u16(target, bank_adr, 0x50);
555                 target_write_u16(target, bank_adr, 0xFF);
556
557                 if (status & 0x10)
558                         return ERROR_FLASH_OPERATION_FAILED;
559                 else if (status & 0x02)
560                         return ERROR_FLASH_OPERATION_FAILED;
561
562                 bytes_written += 2;
563                 words_remaining--;
564                 address += 2;
565         }
566
567         if (bytes_remaining)
568         {
569                 uint8_t last_halfword[2] = {0xff, 0xff};
570                 int i = 0;
571
572                 while (bytes_remaining > 0)
573                 {
574                         last_halfword[i++] = *(buffer + bytes_written);
575                         bytes_remaining--;
576                         bytes_written++;
577                 }
578
579                 bank_adr = address & ~0x03;
580
581                 /* write data command */
582                 target_write_u16(target, bank_adr, 0x40);
583                 target_write_memory(target, address, 2, 1, last_halfword);
584
585                 /* query status command */
586                 target_write_u16(target, bank_adr, 0x70);
587
588                 int timeout;
589                 for (timeout = 0; timeout < 1000; timeout++)
590                 {
591                         target_read_u8(target, bank_adr, &status);
592                         if (status & 0x80)
593                                 break;
594                         alive_sleep(1);
595                 }
596                 if (timeout == 1000)
597                 {
598                         LOG_ERROR("write timed out");
599                         return ERROR_FAIL;
600                 }
601
602                 /* clear status reg and read array */
603                 target_write_u16(target, bank_adr, 0x50);
604                 target_write_u16(target, bank_adr, 0xFF);
605
606                 if (status & 0x10)
607                         return ERROR_FLASH_OPERATION_FAILED;
608                 else if (status & 0x02)
609                         return ERROR_FLASH_OPERATION_FAILED;
610         }
611
612         return ERROR_OK;
613 }
614
615 static int str9x_probe(struct flash_bank_s *bank)
616 {
617         return ERROR_OK;
618 }
619
620 #if 0
621 COMMAND_HANDLER(str9x_handle_part_id_command)
622 {
623         return ERROR_OK;
624 }
625 #endif
626
627 static int str9x_info(struct flash_bank_s *bank, char *buf, int buf_size)
628 {
629         snprintf(buf, buf_size, "str9x flash driver info");
630         return ERROR_OK;
631 }
632
633 COMMAND_HANDLER(str9x_handle_flash_config_command)
634 {
635         struct str9x_flash_bank *str9x_info;
636         struct target *target = NULL;
637
638         if (argc < 5)
639         {
640                 return ERROR_COMMAND_SYNTAX_ERROR;
641         }
642
643         flash_bank_t *bank;
644         int retval = flash_command_get_bank_by_num(cmd_ctx, args[0], &bank);
645         if (ERROR_OK != retval)
646                 return retval;
647
648         uint32_t bbsr, nbbsr, bbadr, nbbadr;
649         COMMAND_PARSE_NUMBER(u32, args[1], bbsr);
650         COMMAND_PARSE_NUMBER(u32, args[2], nbbsr);
651         COMMAND_PARSE_NUMBER(u32, args[3], bbadr);
652         COMMAND_PARSE_NUMBER(u32, args[4], nbbadr);
653
654         str9x_info = bank->driver_priv;
655
656         target = bank->target;
657
658         if (bank->target->state != TARGET_HALTED)
659         {
660                 LOG_ERROR("Target not halted");
661                 return ERROR_TARGET_NOT_HALTED;
662         }
663
664         /* config flash controller */
665         target_write_u32(target, FLASH_BBSR, bbsr);
666         target_write_u32(target, FLASH_NBBSR, nbbsr);
667         target_write_u32(target, FLASH_BBADR, bbadr >> 2);
668         target_write_u32(target, FLASH_NBBADR, nbbadr >> 2);
669
670         /* set bit 18 instruction TCM order as per flash programming manual */
671         arm966e_write_cp15(target, 62, 0x40000);
672
673         /* enable flash bank 1 */
674         target_write_u32(target, FLASH_CR, 0x18);
675         return ERROR_OK;
676 }
677
678 static int str9x_register_commands(struct command_context_s *cmd_ctx)
679 {
680         command_t *str9x_cmd = register_command(cmd_ctx, NULL, "str9x",
681                         NULL, COMMAND_ANY, "str9x flash commands");
682
683         register_command(cmd_ctx, str9x_cmd, "flash_config",
684                         str9x_handle_flash_config_command, COMMAND_EXEC,
685                         "configure str9 flash controller");
686
687         return ERROR_OK;
688 }
689
690 struct flash_driver str9x_flash = {
691                 .name = "str9x",
692                 .register_commands = &str9x_register_commands,
693                 .flash_bank_command = &str9x_flash_bank_command,
694                 .erase = &str9x_erase,
695                 .protect = &str9x_protect,
696                 .write = &str9x_write,
697                 .probe = &str9x_probe,
698                 .auto_probe = &str9x_probe,
699                 .erase_check = &default_flash_blank_check,
700                 .protect_check = &str9x_protect_check,
701                 .info = &str9x_info,
702         };