Remove redundant declarations to allow building with -Wredundant-decls.
[fw/openocd] / src / flash / stellaris.c
1 /***************************************************************************
2  *   Copyright (C) 2006 by Magnus Lundin                                   *
3  *   lundin@mlu.mine.nu                                                    *
4  *                                                                         *
5  *   Copyright (C) 2008 by Spencer Oliver                                  *
6  *   spen@spen-soft.co.uk                                                  *
7  *                                                                         *
8  *   This program is free software; you can redistribute it and/or modify  *
9  *   it under the terms of the GNU General Public License as published by  *
10  *   the Free Software Foundation; either version 2 of the License, or     *
11  *   (at your option) any later version.                                   *
12  *                                                                         *
13  *   This program is distributed in the hope that it will be useful,       *
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
16  *   GNU General Public License for more details.                          *
17  *                                                                         *
18  *   You should have received a copy of the GNU General Public License     *
19  *   along with this program; if not, write to the                         *
20  *   Free Software Foundation, Inc.,                                       *
21  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
22  ***************************************************************************/
23
24 /***************************************************************************
25 * STELLARIS is tested on LM3S811, LM3S6965
26 ***************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include "replacements.h"
32
33 #include "stellaris.h"
34 #include "cortex_m3.h"
35
36 #include "flash.h"
37 #include "target.h"
38 #include "log.h"
39 #include "binarybuffer.h"
40 #include "types.h"
41
42 #include <stdlib.h>
43 #include <string.h>
44 #include <unistd.h>
45
46 #define DID0_VER(did0) ((did0>>28)&0x07)
47 static int stellaris_register_commands(struct command_context_s *cmd_ctx);
48 static int stellaris_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
49 static int stellaris_erase(struct flash_bank_s *bank, int first, int last);
50 static int stellaris_protect(struct flash_bank_s *bank, int set, int first, int last);
51 static int stellaris_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
52 static int stellaris_auto_probe(struct flash_bank_s *bank);
53 static int stellaris_probe(struct flash_bank_s *bank);
54 static int stellaris_protect_check(struct flash_bank_s *bank);
55 static int stellaris_info(struct flash_bank_s *bank, char *buf, int buf_size);
56
57 static int stellaris_read_part_info(struct flash_bank_s *bank);
58 static u32 stellaris_get_flash_status(flash_bank_t *bank);
59 static void stellaris_set_flash_mode(flash_bank_t *bank,int mode);
60 //static u32 stellaris_wait_status_busy(flash_bank_t *bank, u32 waitbits, int timeout);
61
62 static int stellaris_handle_mass_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
63 static int stellaris_mass_erase(struct flash_bank_s *bank);
64
65 flash_driver_t stellaris_flash =
66 {
67         .name = "stellaris",
68         .register_commands = stellaris_register_commands,
69         .flash_bank_command = stellaris_flash_bank_command,
70         .erase = stellaris_erase,
71         .protect = stellaris_protect,
72         .write = stellaris_write,
73         .probe = stellaris_probe,
74         .auto_probe = stellaris_auto_probe,
75         .erase_check = default_flash_mem_blank_check,
76         .protect_check = stellaris_protect_check,
77         .info = stellaris_info
78 };
79
80 static struct {
81         u32 partno;
82         char *partname;
83 }       StellarisParts[] =
84 {
85         {0x01,"LM3S101"},
86         {0x02,"LM3S102"},
87         {0x03,"LM3S1625"},
88         {0x04,"LM3S1626"},
89         {0x05,"LM3S1627"},
90         {0x06,"LM3S1607"},
91         {0x10,"LM3S1776"},
92         {0x19,"LM3S300"},
93         {0x11,"LM3S301"},
94         {0x12,"LM3S310"},
95         {0x1A,"LM3S308"},
96         {0x13,"LM3S315"},
97         {0x14,"LM3S316"},
98         {0x17,"LM3S317"},
99         {0x18,"LM3S318"},
100         {0x15,"LM3S328"},
101         {0x2A,"LM3S600"},
102         {0x21,"LM3S601"},
103         {0x2B,"LM3S608"},
104         {0x22,"LM3S610"},
105         {0x23,"LM3S611"},
106         {0x24,"LM3S612"},
107         {0x25,"LM3S613"},
108         {0x26,"LM3S615"},
109         {0x28,"LM3S617"},
110         {0x29,"LM3S618"},
111         {0x27,"LM3S628"},
112         {0x38,"LM3S800"},
113         {0x31,"LM3S801"},
114         {0x39,"LM3S808"},
115         {0x32,"LM3S811"},
116         {0x33,"LM3S812"},
117         /*{0x33,"LM3S2616"},*/
118         {0x34,"LM3S815"},
119         {0x36,"LM3S817"},
120         {0x37,"LM3S818"},
121         {0x35,"LM3S828"},
122         {0x39,"LM3S2276"},
123         {0x3A,"LM3S2776"},
124         {0x43,"LM3S3651"},
125         {0x44,"LM3S3739"},
126         {0x45,"LM3S3749"},
127         {0x46,"LM3S3759"},
128         {0x48,"LM3S3768"},
129         {0x49,"LM3S3748"},
130         {0x50,"LM3S2678"},
131         {0x51,"LM3S2110"},
132         {0x52,"LM3S2739"},
133         {0x53,"LM3S2651"},
134         {0x54,"LM3S2939"},
135         {0x55,"LM3S2965"},
136         {0x56,"LM3S2432"},
137         {0x57,"LM3S2620"},
138         {0x58,"LM3S2950"},
139         {0x59,"LM3S2412"},
140         {0x5A,"LM3S2533"},
141         {0x61,"LM3S8630"},
142         {0x62,"LM3S8970"},
143         {0x63,"LM3S8730"},
144         {0x64,"LM3S8530"},
145         {0x65,"LM3S8930"},
146         {0x71,"LM3S6610"},
147         {0x72,"LM3S6950"},
148         {0x73,"LM3S6965"},
149         {0x74,"LM3S6110"},
150         {0x75,"LM3S6432"},
151         {0x76,"LM3S6537"},
152         {0x77,"LM3S6753"},
153         {0x78,"LM3S6952"},
154         {0x80,"LM3S2671"},
155         {0x81,"LM3S5632"},
156         {0x82,"LM3S6422"},
157         {0x83,"LM3S6633"},
158         {0x84,"LM3S2139"},
159         {0x85,"LM3S2637"},
160         {0x86,"LM3S8738"},
161         {0x88,"LM3S8938"},
162         {0x89,"LM3S6938"},
163         {0x8A,"LM3S5652"},
164         {0x8B,"LM3S6637"},
165         {0x8C,"LM3S8933"},
166         {0x8D,"LM3S8733"},
167         {0x8E,"LM3S8538"},
168         {0x8F,"LM3S2948"},
169         {0x91,"LM3S5662"},
170         {0x96,"LM3S5732"},
171         {0x97,"LM3S5737"},
172         {0x99,"LM3S5747"},
173         {0x9A,"LM3S5752"},
174         {0x9B,"LM3S5757"},
175         {0x9C,"LM3S5762"},
176         {0x9D,"LM3S5767"},
177         {0xA0,"LM3S5739"},
178         {0xA1,"LM3S6100"},
179         {0xA2,"LM3S2410"},
180         {0xA3,"LM3S6730"},
181         {0xA4,"LM3S2730"},
182         {0xA5,"LM3S6420"},
183         {0xA6,"LM3S8962"},
184         {0xA7,"LM3S5749"},
185         {0xA8,"LM3S5769"},
186         {0xA9,"LM3S5768"},
187         {0xB3,"LM3S1635"},
188         {0xB4,"LM3S1850"},
189         {0xB5,"LM3S1960"},
190         {0xB7,"LM3S1937"},
191         {0xB8,"LM3S1968"},
192         {0xB9,"LM3S1751"},
193         {0xBA,"LM3S1439"},
194         {0xBB,"LM3S1512"},
195         {0xBC,"LM3S1435"},
196         {0xBD,"LM3S1637"},
197         {0xBE,"LM3S1958"},
198         {0xBF,"LM3S1110"},
199         {0xC0,"LM3S1620"},
200         {0xC1,"LM3S1150"},
201         {0xC2,"LM3S1165"},
202         {0xC3,"LM3S1133"},
203         {0xC4,"LM3S1162"},
204         {0xC5,"LM3S1138"},
205         {0xC6,"LM3S1332"},
206         {0xC7,"LM3S1538"},
207         {0xD0,"LM3S6815"},
208         {0xD1,"LM3S6816"},
209         {0xD2,"LM3S6915"},
210         {0xD3,"LM3S6916"},
211         {0xD4,"LM3S2016"},
212         {0xD5,"LM3S1615"},
213         {0xD6,"LM3S1616"},
214         {0xD7,"LM3S8971"},
215         {0xD8,"LM3S1108"},
216         {0xD9,"LM3S1101"},
217         {0xDA,"LM3S1608"},
218         {0xDB,"LM3S1601"},
219         {0xDC,"LM3S1918"},
220         {0xDD,"LM3S1911"},
221         {0xDE,"LM3S2108"},
222         {0xDF,"LM3S2101"},
223         {0xE0,"LM3S2608"},
224         {0xE1,"LM3S2601"},
225         {0xE2,"LM3S2918"},
226         {0xE3,"LM3S2911"},
227         {0xE4,"LM3S6118"},
228         {0xE5,"LM3S6111"},
229         {0xE6,"LM3S6618"},
230         {0xE7,"LM3S6611"},
231         {0xE8,"LM3S6918"},
232         {0xE9,"LM3S6911"},
233         {0,"Unknown part"}
234 };
235
236 static char * StellarisClassname[5] =
237 {
238         "Sandstorm",
239         "Fury",
240         "Unknown",
241         "DustDevil",
242         "Tempest"
243 };
244
245 /***************************************************************************
246 *       openocd command interface                                              *
247 ***************************************************************************/
248
249 /* flash_bank stellaris <base> <size> 0 0 <target#>
250  */
251 static int stellaris_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
252 {
253         stellaris_flash_bank_t *stellaris_info;
254         
255         if (argc < 6)
256         {
257                 LOG_WARNING("incomplete flash_bank stellaris configuration");
258                 return ERROR_FLASH_BANK_INVALID;
259         }
260         
261         stellaris_info = calloc(sizeof(stellaris_flash_bank_t), 1);
262         bank->base = 0x0;
263         bank->driver_priv = stellaris_info;
264         
265         stellaris_info->target_name = "Unknown target";
266         
267         /* part wasn't probed for info yet */
268         stellaris_info->did1 = 0;
269         
270         /* TODO Use an optional main oscillator clock rate in kHz from arg[6] */ 
271         return ERROR_OK;
272 }
273
274 static int stellaris_register_commands(struct command_context_s *cmd_ctx)
275 {
276         command_t *stm32x_cmd = register_command(cmd_ctx, NULL, "stellaris", NULL, COMMAND_ANY, "stellaris flash specific commands");
277         
278         register_command(cmd_ctx, stm32x_cmd, "mass_erase", stellaris_handle_mass_erase_command, COMMAND_EXEC, "mass erase device");
279         return ERROR_OK;
280 }
281
282 static int stellaris_info(struct flash_bank_s *bank, char *buf, int buf_size)
283 {
284         int printed, device_class;
285         stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
286         
287         stellaris_read_part_info(bank);
288
289         if (stellaris_info->did1 == 0)
290         {
291                 printed = snprintf(buf, buf_size, "Cannot identify target as a Stellaris\n");
292                 buf += printed;
293                 buf_size -= printed;
294                 return ERROR_FLASH_OPERATION_FAILED;
295         }
296         
297         if (DID0_VER(stellaris_info->did0) > 0)
298         {
299                 device_class = (stellaris_info->did0>>16) & 0xFF;
300         }
301         else
302         {
303                 device_class = 0;
304         }       
305         printed = snprintf(buf, buf_size, "\nLMI Stellaris information: Chip is class %i(%s) %s v%c.%i\n",
306           device_class, StellarisClassname[device_class], stellaris_info->target_name,
307           'A' + ((stellaris_info->did0>>8) & 0xFF), (stellaris_info->did0) & 0xFF);
308         buf += printed;
309         buf_size -= printed;
310
311         printed = snprintf(buf, buf_size, "did1: 0x%8.8x, arch: 0x%4.4x, eproc: %s, ramsize:%ik, flashsize: %ik\n", 
312          stellaris_info->did1, stellaris_info->did1, "ARMV7M", (1+((stellaris_info->dc0>>16) & 0xFFFF))/4, (1+(stellaris_info->dc0 & 0xFFFF))*2);
313         buf += printed;
314         buf_size -= printed;
315
316         printed = snprintf(buf, buf_size, "master clock(estimated): %ikHz, rcc is 0x%x \n", stellaris_info->mck_freq / 1000, stellaris_info->rcc);
317         buf += printed;
318         buf_size -= printed;
319
320         if (stellaris_info->num_lockbits>0)
321         {
322                 printed = snprintf(buf, buf_size, "pagesize: %i, lockbits: %i 0x%4.4x, pages in lock region: %i \n", stellaris_info->pagesize, stellaris_info->num_lockbits, stellaris_info->lockbits,stellaris_info->num_pages/stellaris_info->num_lockbits);
323                 buf += printed;
324                 buf_size -= printed;
325         }
326         return ERROR_OK;
327 }
328
329 /***************************************************************************
330 *       chip identification and status                                         *
331 ***************************************************************************/
332
333 static u32 stellaris_get_flash_status(flash_bank_t *bank)
334 {
335         target_t *target = bank->target;
336         u32 fmc;
337         
338         target_read_u32(target, FLASH_CONTROL_BASE|FLASH_FMC, &fmc);
339         
340         return fmc;
341 }
342
343 /** Read clock configuration and set stellaris_info->usec_clocks*/
344  
345 static void stellaris_read_clock_info(flash_bank_t *bank)
346 {
347         stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
348         target_t *target = bank->target;
349         u32 rcc, pllcfg, sysdiv, usesysdiv, bypass, oscsrc;
350         unsigned long mainfreq;
351
352         target_read_u32(target, SCB_BASE|RCC, &rcc);
353         LOG_DEBUG("Stellaris RCC %x", rcc);
354         target_read_u32(target, SCB_BASE|PLLCFG, &pllcfg);
355         LOG_DEBUG("Stellaris PLLCFG %x", pllcfg);
356         stellaris_info->rcc = rcc;
357         
358         sysdiv = (rcc>>23) & 0xF;
359         usesysdiv = (rcc>>22) & 0x1;
360         bypass = (rcc>>11) & 0x1;
361         oscsrc = (rcc>>4) & 0x3;
362         /* xtal = (rcc>>6)&0xF; */
363         switch (oscsrc)
364         {
365                 case 0:
366                         mainfreq = 6000000;  /* Default xtal */
367                         break;
368                 case 1:
369                         mainfreq = 22500000; /* Internal osc. 15 MHz +- 50% */
370                         break;
371                 case 2:
372                         mainfreq = 5625000;  /* Internal osc. / 4 */
373                         break;
374                 case 3:
375                         LOG_WARNING("Invalid oscsrc (3) in rcc register");
376                         mainfreq = 6000000;
377                         break;
378
379                 default: /* NOTREACHED */
380                         mainfreq = 0;
381                         break;
382         }
383         
384         if (!bypass)
385                 mainfreq = 200000000; /* PLL out frec */
386                 
387         if (usesysdiv)
388                 stellaris_info->mck_freq = mainfreq/(1+sysdiv);
389         else
390                 stellaris_info->mck_freq = mainfreq;
391         
392         /* Forget old flash timing */
393         stellaris_set_flash_mode(bank, 0);
394 }
395
396 /* Setup the timimg registers */
397 static void stellaris_set_flash_mode(flash_bank_t *bank,int mode)
398 {
399         stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
400         target_t *target = bank->target;
401
402         u32 usecrl = (stellaris_info->mck_freq/1000000ul-1);
403         LOG_DEBUG("usecrl = %i",usecrl);        
404         target_write_u32(target, SCB_BASE|USECRL, usecrl);
405 }
406
407 #if 0
408 static u32 stellaris_wait_status_busy(flash_bank_t *bank, u32 waitbits, int timeout)
409 {
410         u32 status;
411         
412         /* Stellaris waits for cmdbit to clear */
413         while (((status = stellaris_get_flash_status(bank)) & waitbits) && (timeout-- > 0))
414         {
415                 LOG_DEBUG("status: 0x%x", status);
416                 alive_sleep(1);
417         }
418         
419         /* Flash errors are reflected in the FLASH_CRIS register */
420
421         return status;
422 }
423
424 /* Send one command to the flash controller */
425 static int stellaris_flash_command(struct flash_bank_s *bank,u8 cmd,u16 pagen) 
426 {
427         u32 fmc;
428         target_t *target = bank->target;
429
430         fmc = FMC_WRKEY | cmd; 
431         target_write_u32(target, FLASH_CONTROL_BASE|FLASH_FMC, fmc);
432         LOG_DEBUG("Flash command: 0x%x", fmc);
433
434         if (stellaris_wait_status_busy(bank, cmd, 100)) 
435         {
436                 return ERROR_FLASH_OPERATION_FAILED;
437         }               
438
439         return ERROR_OK;
440 }
441 #endif
442
443 /* Read device id register, main clock frequency register and fill in driver info structure */
444 static int stellaris_read_part_info(struct flash_bank_s *bank)
445 {
446         stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
447         target_t *target = bank->target;
448         u32 did0, did1, ver, fam, status;
449         int i;
450         
451         /* Read and parse chip identification register */
452         target_read_u32(target, SCB_BASE|DID0, &did0);
453         target_read_u32(target, SCB_BASE|DID1, &did1);
454         target_read_u32(target, SCB_BASE|DC0, &stellaris_info->dc0);
455         target_read_u32(target, SCB_BASE|DC1, &stellaris_info->dc1);
456         LOG_DEBUG("did0 0x%x, did1 0x%x, dc0 0x%x, dc1 0x%x", did0, did1, stellaris_info->dc0, stellaris_info->dc1);
457
458         ver = did0 >> 28;
459         if((ver != 0) && (ver != 1))
460         {
461                 LOG_WARNING("Unknown did0 version, cannot identify target");
462                 return ERROR_FLASH_OPERATION_FAILED;
463         }
464
465         if (did1 == 0)
466         {
467                 LOG_WARNING("Cannot identify target as a Stellaris");
468                 return ERROR_FLASH_OPERATION_FAILED;
469         }
470
471         ver = did1 >> 28;
472         fam = (did1 >> 24) & 0xF;
473         if(((ver != 0) && (ver != 1)) || (fam != 0))
474         {
475                 LOG_WARNING("Unknown did1 version/family, cannot positively identify target as a Stellaris");
476         }
477
478         for (i = 0; StellarisParts[i].partno; i++)
479         {
480                 if (StellarisParts[i].partno == ((did1 >> 16) & 0xFF))
481                         break;
482         }
483         
484         stellaris_info->target_name = StellarisParts[i].partname;
485         
486         stellaris_info->did0 = did0;
487         stellaris_info->did1 = did1;
488
489         stellaris_info->num_lockbits = 1 + (stellaris_info->dc0 & 0xFFFF);
490         stellaris_info->num_pages = 2 *(1+(stellaris_info->dc0 & 0xFFFF));
491         stellaris_info->pagesize = 1024;
492         bank->size = 1024 * stellaris_info->num_pages;
493         stellaris_info->pages_in_lockregion = 2;
494         target_read_u32(target, SCB_BASE|FMPPE, &stellaris_info->lockbits);
495
496         /* provide this for the benefit of the higher flash driver layers */
497         bank->num_sectors = stellaris_info->num_pages;
498         bank->sectors = malloc(sizeof(flash_sector_t) * bank->num_sectors);
499         for (i = 0; i < bank->num_sectors; i++)
500         {
501                 bank->sectors[i].offset = i * stellaris_info->pagesize;
502                 bank->sectors[i].size = stellaris_info->pagesize;
503                 bank->sectors[i].is_erased = -1;
504                 bank->sectors[i].is_protected = -1;
505         }
506
507         /* Read main and master clock freqency register */
508         stellaris_read_clock_info(bank);
509         
510         status = stellaris_get_flash_status(bank);
511         
512         return ERROR_OK;
513 }
514
515 /***************************************************************************
516 *       flash operations                                                       *
517 ***************************************************************************/
518
519 static int stellaris_protect_check(struct flash_bank_s *bank)
520 {
521         u32 status;
522         
523         stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
524
525         if (bank->target->state != TARGET_HALTED)
526         {
527                 LOG_ERROR("Target not halted");
528                 return ERROR_TARGET_NOT_HALTED;
529         }
530
531         if (stellaris_info->did1 == 0)
532         {
533                 stellaris_read_part_info(bank);
534         }
535
536         if (stellaris_info->did1 == 0)
537         {
538                 LOG_WARNING("Cannot identify target as an AT91SAM");
539                 return ERROR_FLASH_OPERATION_FAILED;
540         }
541                 
542         status = stellaris_get_flash_status(bank);
543         stellaris_info->lockbits = status >> 16;
544         
545         return ERROR_OK;
546 }
547
548 static int stellaris_erase(struct flash_bank_s *bank, int first, int last)
549 {
550         int banknr;
551         u32 flash_fmc, flash_cris;
552         stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
553         target_t *target = bank->target;
554         
555         if (bank->target->state != TARGET_HALTED)
556         {
557                 LOG_ERROR("Target not halted");
558                 return ERROR_TARGET_NOT_HALTED;
559         }
560
561         if (stellaris_info->did1 == 0)
562         {
563                 stellaris_read_part_info(bank);
564         }
565
566         if (stellaris_info->did1 == 0)
567         {
568                 LOG_WARNING("Cannot identify target as Stellaris");
569                 return ERROR_FLASH_OPERATION_FAILED;
570         }       
571         
572         if ((first < 0) || (last < first) || (last >= (int)stellaris_info->num_pages))
573         {
574                 return ERROR_FLASH_SECTOR_INVALID;
575         }
576         
577         if ((first == 0) && (last == ((int)stellaris_info->num_pages-1)))
578         {
579                 return stellaris_mass_erase(bank);
580         }
581         
582         /* Configure the flash controller timing */
583         stellaris_read_clock_info(bank);        
584         stellaris_set_flash_mode(bank,0);
585
586         /* Clear and disable flash programming interrupts */
587         target_write_u32(target, FLASH_CIM, 0);
588         target_write_u32(target, FLASH_MISC, PMISC|AMISC);
589         
590         for (banknr = first; banknr <= last; banknr++)
591         {
592                 /* Address is first word in page */
593                 target_write_u32(target, FLASH_FMA, banknr * stellaris_info->pagesize);
594                 /* Write erase command */
595                 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_ERASE);
596                 /* Wait until erase complete */
597                 do
598                 {
599                         target_read_u32(target, FLASH_FMC, &flash_fmc);
600                 }
601                 while(flash_fmc & FMC_ERASE);
602
603                 /* Check acess violations */
604                 target_read_u32(target, FLASH_CRIS, &flash_cris);
605                 if(flash_cris & (AMASK))
606                 {
607                         LOG_WARNING("Error erasing flash page %i,  flash_cris 0x%x", banknr, flash_cris);
608                         target_write_u32(target, FLASH_CRIS, 0);
609                         return ERROR_FLASH_OPERATION_FAILED;
610                 }
611                 
612                 bank->sectors[banknr].is_erased = 1;
613         }
614
615         return ERROR_OK;
616 }
617
618 static int stellaris_protect(struct flash_bank_s *bank, int set, int first, int last)
619 {
620         u32 fmppe, flash_fmc, flash_cris;
621         int lockregion;
622         
623         stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
624         target_t *target = bank->target;
625         
626         if (bank->target->state != TARGET_HALTED)
627         {
628                 LOG_ERROR("Target not halted");
629                 return ERROR_TARGET_NOT_HALTED;
630         }
631         
632         if ((first < 0) || (last < first) || (last >= stellaris_info->num_lockbits))
633         {
634                 return ERROR_FLASH_SECTOR_INVALID;
635         }
636         
637         if (stellaris_info->did1 == 0)
638         {
639                 stellaris_read_part_info(bank);
640         }
641
642         if (stellaris_info->did1 == 0)
643         {
644                 LOG_WARNING("Cannot identify target as an Stellaris MCU");
645                 return ERROR_FLASH_OPERATION_FAILED;
646         }
647         
648         /* Configure the flash controller timing */
649         stellaris_read_clock_info(bank);
650         stellaris_set_flash_mode(bank, 0);
651
652         fmppe = stellaris_info->lockbits;
653         for (lockregion = first; lockregion <= last; lockregion++)
654         {
655                 if (set)
656                         fmppe &= ~(1<<lockregion); 
657                 else
658                         fmppe |= (1<<lockregion); 
659         }
660
661         /* Clear and disable flash programming interrupts */
662         target_write_u32(target, FLASH_CIM, 0);
663         target_write_u32(target, FLASH_MISC, PMISC|AMISC);
664         
665         LOG_DEBUG("fmppe 0x%x",fmppe);
666         target_write_u32(target, SCB_BASE|FMPPE, fmppe);
667         /* Commit FMPPE */
668         target_write_u32(target, FLASH_FMA, 1);
669         /* Write commit command */
670         /* TODO safety check, sice this cannot be undone */
671         LOG_WARNING("Flash protection cannot be removed once commited, commit is NOT executed !");
672         /* target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_COMT); */
673         /* Wait until erase complete */
674         do
675         {
676                 target_read_u32(target, FLASH_FMC, &flash_fmc);
677         }
678         while(flash_fmc & FMC_COMT);
679
680         /* Check acess violations */
681         target_read_u32(target, FLASH_CRIS, &flash_cris);
682         if(flash_cris & (AMASK))
683         {
684                 LOG_WARNING("Error setting flash page protection,  flash_cris 0x%x", flash_cris);
685                 target_write_u32(target, FLASH_CRIS, 0);
686                 return ERROR_FLASH_OPERATION_FAILED;
687         }
688         
689         target_read_u32(target, SCB_BASE|FMPPE, &stellaris_info->lockbits);
690         
691         return ERROR_OK;
692 }
693
694 static u8 stellaris_write_code[] = 
695 {
696 /* 
697         Call with :     
698         r0 = buffer address
699         r1 = destination address
700         r2 = bytecount (in) - endaddr (work) 
701         
702         Used registers: 
703         r3 = pFLASH_CTRL_BASE
704         r4 = FLASHWRITECMD
705         r5 = #1
706         r6 = bytes written
707         r7 = temp reg
708 */
709         0x07,0x4B,                      /* ldr r3,pFLASH_CTRL_BASE */
710         0x08,0x4C,                      /* ldr r4,FLASHWRITECMD */
711         0x01,0x25,                      /* movs r5, 1 */
712         0x00,0x26,                      /* movs r6, #0 */
713 /* mainloop: */
714         0x19,0x60,                      /* str  r1, [r3, #0] */
715         0x87,0x59,                      /* ldr  r7, [r0, r6] */
716         0x5F,0x60,                      /* str  r7, [r3, #4] */
717         0x9C,0x60,                      /* str  r4, [r3, #8] */
718 /* waitloop: */
719         0x9F,0x68,                      /* ldr  r7, [r3, #8] */
720         0x2F,0x42,                      /* tst  r7, r5 */
721         0xFC,0xD1,                      /* bne  waitloop */
722         0x04,0x31,                      /* adds r1, r1, #4 */
723         0x04,0x36,                      /* adds r6, r6, #4 */
724         0x96,0x42,                      /* cmp  r6, r2 */
725         0xF4,0xD1,                      /* bne  mainloop */
726                                                 /* exit: */
727         0xFE,0xE7,                      /* b exit */
728 /* pFLASH_CTRL_BASE: */
729         0x00,0xD0,0x0F,0x40,    /* .word        0x400FD000 */
730 /* FLASHWRITECMD: */
731         0x01,0x00,0x42,0xA4     /* .word        0xA4420001 */
732 };
733
734 static int stellaris_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 wcount)
735 {
736         target_t *target = bank->target;
737         u32 buffer_size = 8192;
738         working_area_t *source;
739         working_area_t *write_algorithm;
740         u32 address = bank->base + offset;
741         reg_param_t reg_params[3];
742         armv7m_algorithm_t armv7m_info;
743         int retval = ERROR_OK;
744         
745         LOG_DEBUG("(bank=%p buffer=%p offset=%08X wcount=%08X)",
746                         bank, buffer, offset, wcount);
747
748         /* flash write code */
749         if (target_alloc_working_area(target, sizeof(stellaris_write_code), &write_algorithm) != ERROR_OK)
750         {
751                 LOG_WARNING("no working area available, can't do block memory writes");
752                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
753         };
754
755         target_write_buffer(target, write_algorithm->address, sizeof(stellaris_write_code), stellaris_write_code);
756
757         /* memory buffer */
758         while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
759         {
760                 LOG_DEBUG("called target_alloc_working_area(target=%p buffer_size=%08X source=%p)",
761                                 target, buffer_size, source); 
762                 buffer_size /= 2;
763                 if (buffer_size <= 256)
764                 {
765                         /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
766                         if (write_algorithm)
767                                 target_free_working_area(target, write_algorithm);
768                         
769                         LOG_WARNING("no large enough working area available, can't do block memory writes");
770                         return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
771                 }
772         };
773         
774         armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
775         armv7m_info.core_mode = ARMV7M_MODE_ANY;
776         
777         init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
778         init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
779         init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
780         
781         while (wcount > 0)
782         {
783                 u32 thisrun_count = (wcount > (buffer_size / 4)) ? (buffer_size / 4) : wcount;
784                 
785                 target_write_buffer(target, source->address, thisrun_count * 4, buffer);
786                 
787                 buf_set_u32(reg_params[0].value, 0, 32, source->address);
788                 buf_set_u32(reg_params[1].value, 0, 32, address);
789                 buf_set_u32(reg_params[2].value, 0, 32, 4*thisrun_count);
790                 LOG_INFO("Algorithm flash write %i words to 0x%x, %i remaining", thisrun_count, address, wcount);
791                 LOG_DEBUG("Algorithm flash write %i words to 0x%x, %i remaining", thisrun_count, address, wcount);
792                 if ((retval = target->type->run_algorithm(target, 0, NULL, 3, reg_params, write_algorithm->address, write_algorithm->address + sizeof(stellaris_write_code)-10, 10000, &armv7m_info)) != ERROR_OK)
793                 {
794                         LOG_ERROR("error executing stellaris flash write algorithm");
795                         retval = ERROR_FLASH_OPERATION_FAILED;
796                         break;
797                 }
798         
799                 buffer += thisrun_count * 4;
800                 address += thisrun_count * 4;
801                 wcount -= thisrun_count;
802         }
803         
804         target_free_working_area(target, write_algorithm);
805         target_free_working_area(target, source);
806         
807         destroy_reg_param(&reg_params[0]);
808         destroy_reg_param(&reg_params[1]);
809         destroy_reg_param(&reg_params[2]);
810         
811         return retval;
812 }
813
814 static int stellaris_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
815 {
816         stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
817         target_t *target = bank->target;
818         u32 address = offset;
819         u32 flash_cris, flash_fmc;
820         u32 words_remaining = (count / 4);
821         u32 bytes_remaining = (count & 0x00000003);
822         u32 bytes_written = 0;
823         int retval;
824         
825         if (bank->target->state != TARGET_HALTED)
826         {
827                 LOG_ERROR("Target not halted");
828                 return ERROR_TARGET_NOT_HALTED;
829         }
830
831         LOG_DEBUG("(bank=%p buffer=%p offset=%08X count=%08X)",
832                         bank, buffer, offset, count);
833
834         if (stellaris_info->did1 == 0)
835         {
836                 stellaris_read_part_info(bank);
837         }
838
839         if (stellaris_info->did1 == 0)
840         {
841                 LOG_WARNING("Cannot identify target as a Stellaris processor");
842                 return ERROR_FLASH_OPERATION_FAILED;
843         }
844         
845         if (offset & 0x3)
846         {
847                 LOG_WARNING("offset size must be word aligned");
848                 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
849         }
850         
851         if (offset + count > bank->size)
852                 return ERROR_FLASH_DST_OUT_OF_BANK;
853
854         /* Configure the flash controller timing */     
855         stellaris_read_clock_info(bank);        
856         stellaris_set_flash_mode(bank, 0);
857         
858         /* Clear and disable flash programming interrupts */
859         target_write_u32(target, FLASH_CIM, 0);
860         target_write_u32(target, FLASH_MISC, PMISC|AMISC);
861
862         /* multiple words to be programmed? */
863         if (words_remaining > 0) 
864         {
865                 /* try using a block write */
866                 if ((retval = stellaris_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK)
867                 {
868                         if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
869                         {
870                                 /* if block write failed (no sufficient working area),
871                                  * we use normal (slow) single dword accesses */ 
872                                 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
873                         }
874                         else if (retval == ERROR_FLASH_OPERATION_FAILED)
875                         {
876                                 /* if an error occured, we examine the reason, and quit */
877                                 target_read_u32(target, FLASH_CRIS, &flash_cris);
878                                 
879                                 LOG_ERROR("flash writing failed with CRIS: 0x%x", flash_cris);
880                                 return ERROR_FLASH_OPERATION_FAILED;
881                         }
882                 }
883                 else
884                 {
885                         buffer += words_remaining * 4;
886                         address += words_remaining * 4;
887                         words_remaining = 0;
888                 }
889         }
890         
891         while (words_remaining > 0)
892         {
893                 if (!(address & 0xff))
894                         LOG_DEBUG("0x%x", address);
895                 
896                 /* Program one word */
897                 target_write_u32(target, FLASH_FMA, address);
898                 target_write_buffer(target, FLASH_FMD, 4, buffer);
899                 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
900                 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
901                 /* Wait until write complete */
902                 do
903                 {
904                         target_read_u32(target, FLASH_FMC, &flash_fmc);
905                 } while (flash_fmc & FMC_WRITE);
906                 
907                 buffer += 4;
908                 address += 4;
909                 words_remaining--;
910         }
911         
912         if (bytes_remaining)
913         {
914                 u8 last_word[4] = {0xff, 0xff, 0xff, 0xff};
915                 int i = 0;
916                                 
917                 while(bytes_remaining > 0)
918                 {
919                         last_word[i++] = *(buffer + bytes_written); 
920                         bytes_remaining--;
921                         bytes_written++;
922                 }
923                 
924                 if (!(address & 0xff))
925                         LOG_DEBUG("0x%x", address);
926                 
927                 /* Program one word */
928                 target_write_u32(target, FLASH_FMA, address);
929                 target_write_buffer(target, FLASH_FMD, 4, last_word);
930                 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
931                 /* LOG_DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */
932                 /* Wait until write complete */
933                 do
934                 {
935                         target_read_u32(target, FLASH_FMC, &flash_fmc);
936                 } while (flash_fmc & FMC_WRITE);
937         }
938         
939         /* Check access violations */
940         target_read_u32(target, FLASH_CRIS, &flash_cris);
941         if (flash_cris & (AMASK))
942         {
943                 LOG_DEBUG("flash_cris 0x%x", flash_cris);
944                 return ERROR_FLASH_OPERATION_FAILED;
945         }
946         return ERROR_OK;
947 }
948
949 static int stellaris_probe(struct flash_bank_s *bank)
950 {
951         /* we can't probe on an stellaris
952          * if this is an stellaris, it has the configured flash
953          */
954         
955         if (bank->target->state != TARGET_HALTED)
956         {
957                 LOG_ERROR("Target not halted");
958                 return ERROR_TARGET_NOT_HALTED;
959         }
960
961         /* stellaris_read_part_info() already takes care about error checking and reporting */
962         return stellaris_read_part_info(bank);
963 }
964
965 static int stellaris_auto_probe(struct flash_bank_s *bank)
966 {
967         stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
968         if (stellaris_info->did1)
969                 return ERROR_OK;
970         return stellaris_probe(bank);
971 }
972
973 static int stellaris_mass_erase(struct flash_bank_s *bank)
974 {
975         target_t *target = NULL;
976         stellaris_flash_bank_t *stellaris_info = NULL;
977         u32 flash_fmc;
978         
979         stellaris_info = bank->driver_priv;
980         target = bank->target;
981         
982         if (target->state != TARGET_HALTED)
983         {
984                 LOG_ERROR("Target not halted");
985                 return ERROR_TARGET_NOT_HALTED;
986         }
987         
988         if (stellaris_info->did1 == 0)
989         {
990                 stellaris_read_part_info(bank);
991         }
992         
993         if (stellaris_info->did1 == 0)
994         {
995                 LOG_WARNING("Cannot identify target as Stellaris");
996                 return ERROR_FLASH_OPERATION_FAILED;
997         }
998         
999         /* Configure the flash controller timing */
1000         stellaris_read_clock_info(bank);        
1001         stellaris_set_flash_mode(bank, 0);
1002
1003         /* Clear and disable flash programming interrupts */
1004         target_write_u32(target, FLASH_CIM, 0);
1005         target_write_u32(target, FLASH_MISC, PMISC|AMISC);
1006         
1007         target_write_u32(target, FLASH_FMA, 0);
1008         target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
1009         /* Wait until erase complete */
1010         do
1011         {
1012                 target_read_u32(target, FLASH_FMC, &flash_fmc);
1013         }
1014         while (flash_fmc & FMC_MERASE);
1015         
1016         /* if device has > 128k, then second erase cycle is needed
1017          * this is only valid for older devices, but will not hurt */
1018         if (stellaris_info->num_pages * stellaris_info->pagesize > 0x20000)
1019         {
1020                 target_write_u32(target, FLASH_FMA, 0x20000);
1021                 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
1022                 /* Wait until erase complete */
1023                 do
1024                 {
1025                         target_read_u32(target, FLASH_FMC, &flash_fmc);
1026                 }
1027                 while (flash_fmc & FMC_MERASE);
1028         }
1029         
1030         return ERROR_OK;
1031 }
1032
1033 static int stellaris_handle_mass_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
1034 {
1035         flash_bank_t *bank;
1036         int i;
1037         
1038         if (argc < 1)
1039         {
1040                 command_print(cmd_ctx, "stellaris mass_erase <bank>");
1041                 return ERROR_OK;        
1042         }
1043         
1044         bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
1045         if (!bank)
1046         {
1047                 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
1048                 return ERROR_OK;
1049         }
1050         
1051         if (stellaris_mass_erase(bank) == ERROR_OK)
1052         {
1053                 /* set all sectors as erased */
1054                 for (i = 0; i < bank->num_sectors; i++)
1055                 {
1056                         bank->sectors[i].is_erased = 1;
1057                 }
1058                 
1059                 command_print(cmd_ctx, "stellaris mass erase complete");
1060         }
1061         else
1062         {
1063                 command_print(cmd_ctx, "stellaris mass erase failed");
1064         }
1065         
1066         return ERROR_OK;
1067 }