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