]> git.sur5r.net Git - openocd/blob - src/flash/stellaris.c
- added stellaris.[ch] missing from Cortex-M3 merge
[openocd] / src / flash / stellaris.c
1 /***************************************************************************
2  *   Copyright (C) 2006 by Magnus Lundin                                   *
3  *   lundin@mlu.mine.nu                                                        *
4  *                                                                                                             *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20
21 /***************************************************************************
22 * STELLARIS is tested on LM3S811
23
24 *
25 *
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 int stellaris_register_commands(struct command_context_s *cmd_ctx);
47 int stellaris_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
48 int stellaris_erase(struct flash_bank_s *bank, int first, int last);
49 int stellaris_protect(struct flash_bank_s *bank, int set, int first, int last);
50 int stellaris_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
51 int stellaris_probe(struct flash_bank_s *bank);
52 int stellaris_erase_check(struct flash_bank_s *bank);
53 int stellaris_protect_check(struct flash_bank_s *bank);
54 int stellaris_info(struct flash_bank_s *bank, char *buf, int buf_size);
55
56 u32 stellaris_get_flash_status(flash_bank_t *bank);
57 void stellaris_set_flash_mode(flash_bank_t *bank,int mode);
58 u32 stellaris_wait_status_busy(flash_bank_t *bank, u32 waitbits, int timeout);
59
60 flash_driver_t stellaris_flash =
61 {
62         .name = "stellaris",
63         .register_commands = stellaris_register_commands,
64         .flash_bank_command = stellaris_flash_bank_command,
65         .erase = stellaris_erase,
66         .protect = stellaris_protect,
67         .write = stellaris_write,
68         .probe = stellaris_probe,
69         .erase_check = stellaris_erase_check,
70         .protect_check = stellaris_protect_check,
71         .info = stellaris_info
72 };
73
74
75 struct {
76         u32 partno;
77         char partname[];
78 }       StellarisParts[] =
79 {
80         {0x01,"LM3S101"},
81         {0x02,"LM3S102"},
82         {0x11,"LM3S301"},
83         {0x12,"LM3S310"},
84         {0x13,"LM3S315"},
85         {0x14,"LM3S316"},
86         {0x15,"LM3S328"},
87         {0x21,"LM3S601"},
88         {0x22,"LM3S610"},
89         {0x23,"LM3S611"},
90         {0x24,"LM3S612"},
91         {0x25,"LM3S613"},
92         {0x26,"LM3S615"},
93         {0x27,"LM3S628"},
94         {0x31,"LM3S801"},
95         {0x32,"LM3S811"},
96         {0x33,"LM3S812"},
97         {0x34,"LM3S815"},
98         {0x35,"LM3S828"},
99         {0,"Unknown part"}
100 };
101
102 /***************************************************************************
103 *       openocd command interface                                              *
104 ***************************************************************************/
105
106 int stellaris_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
107 {
108         stellaris_flash_bank_t *stellaris_info;
109         
110         if (argc < 6)
111         {
112                 WARNING("incomplete flash_bank stellaris configuration");
113                 return ERROR_FLASH_BANK_INVALID;
114         }
115         
116         stellaris_info = calloc(sizeof(stellaris_flash_bank_t),1);
117         bank->base = 0x0;
118         bank->driver_priv = stellaris_info;
119         
120         stellaris_info->target_name ="Unknown target";
121         stellaris_info->target = get_target_by_num(strtoul(args[5], NULL, 0));
122         if (!stellaris_info->target)
123         {
124                 ERROR("no target '%i' configured", args[5]);
125                 exit(-1);
126         }
127         
128         /* part wasn't probed for info yet */
129         stellaris_info->did1 = 0;
130         
131         /* TODO Use an optional main oscillator clock rate in kHz from arg[6] */ 
132         return ERROR_OK;
133 }
134
135 int stellaris_register_commands(struct command_context_s *cmd_ctx)
136 {
137 /*
138         command_t *stellaris_cmd = register_command(cmd_ctx, NULL, "stellaris", NULL, COMMAND_ANY, NULL);
139         register_command(cmd_ctx, stellaris_cmd, "gpnvm", stellaris_handle_gpnvm_command, COMMAND_EXEC,
140                         "stellaris gpnvm <num> <bit> set|clear, set or clear stellaris gpnvm bit");
141 */
142         return ERROR_OK;
143 }
144
145 int stellaris_info(struct flash_bank_s *bank, char *buf, int buf_size)
146 {
147         int printed;
148         stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
149         
150         stellaris_read_part_info(bank);
151
152         if (stellaris_info->did1 == 0)
153         {
154                 printed = snprintf(buf, buf_size, "Cannot identify target as a Stellaris\n");
155                 buf += printed;
156                 buf_size -= printed;
157                 return ERROR_FLASH_OPERATION_FAILED;
158         }
159         
160         printed = snprintf(buf, buf_size, "\nLMI Stellaris information: Chip is %s v%i.%02i\n",stellaris_info->target_name, (stellaris_info->did0>>8)&0xFF, (stellaris_info->did0)&0xFF);
161         buf += printed;
162         buf_size -= printed;
163
164         printed = snprintf(buf, buf_size, "did1: 0x%8.8x, arch: 0x%4.4x, eproc: %s, ramsize:%ik,  flashsize: %ik\n", 
165          stellaris_info->did1, stellaris_info->did1, "ARMV7M", (1+(stellaris_info->dc0>>16)&0xFFFF)/4, (1+stellaris_info->dc0&0xFFFF)*2);
166         buf += printed;
167         buf_size -= printed;
168
169         printed = snprintf(buf, buf_size, "master clock(estimated): %ikHz,  rcc is 0x%x \n", stellaris_info->mck_freq / 1000, stellaris_info->rcc);
170         buf += printed;
171         buf_size -= printed;
172
173         if (stellaris_info->num_lockbits>0) {           
174                 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);
175                 buf += printed;
176                 buf_size -= printed;
177         }
178         return ERROR_OK;
179 }
180
181 /***************************************************************************
182 *       chip identification and status                                         *
183 ***************************************************************************/
184
185 u32 stellaris_get_flash_status(flash_bank_t *bank)
186 {
187         stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
188         target_t *target = stellaris_info->target;
189         u32 fmc;
190         
191         target_read_u32(target, FLASH_CONTROL_BASE|FLASH_FMC, &fmc);
192         
193         return fmc;
194 }
195
196 /** Read clock configuration and set stellaris_info->usec_clocks*/
197  
198 void stellaris_read_clock_info(flash_bank_t *bank)
199 {
200         stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
201         target_t *target = stellaris_info->target;
202         u32 rcc, pllcfg, sysdiv, usesysdiv, bypass, oscsrc;
203         unsigned long tmp, mainfreq;
204
205         target_read_u32(target, SCB_BASE|RCC, &rcc);
206         DEBUG("Stellaris RCC %x",rcc);
207         target_read_u32(target, SCB_BASE|PLLCFG, &pllcfg);
208         DEBUG("Stellaris PLLCFG %x",pllcfg);
209         stellaris_info->rcc = rcc;
210         
211         sysdiv = (rcc>>23)&0xF;
212         usesysdiv = (rcc>>22)&0x1;
213         bypass = (rcc>>11)&0x1;
214         oscsrc = (rcc>>4)&0x3;
215         /* xtal = (rcc>>6)&0xF; */
216         switch (oscsrc)
217         {
218                 case 0:
219                         mainfreq = 6000000;  /* Default xtal */
220                         break;
221                 case 1:
222                         mainfreq = 22500000; /* Internal osc. 15 MHz +- 50% */
223                         break;
224                 case 2:
225                         mainfreq = 5625000;  /* Internal osc. / 4 */
226                         break;
227                 case 3:
228                         WARNING("Invalid oscsrc (3) in rcc register");
229                         mainfreq = 6000000;
230                         break;
231         }
232         
233         if (!bypass)
234                 mainfreq = 200000000; /* PLL out frec */
235                 
236         if (usesysdiv)
237                 stellaris_info->mck_freq = mainfreq/(1+sysdiv);
238         else
239                 stellaris_info->mck_freq = mainfreq;
240         
241         /* Forget old flash timing */
242        stellaris_set_flash_mode(bank,0);
243 }
244
245 /* Setup the timimg registers */
246 void stellaris_set_flash_mode(flash_bank_t *bank,int mode)
247 {
248         stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
249         target_t *target = stellaris_info->target;
250
251         u32 usecrl = (stellaris_info->mck_freq/1000000ul-1);
252         DEBUG("usecrl = %i",usecrl);    
253         target_write_u32(target, SCB_BASE|USECRL , usecrl);
254         
255 }
256
257 u32 stellaris_wait_status_busy(flash_bank_t *bank, u32 waitbits, int timeout)
258 {
259         u32 status;
260         
261         /* Stellaris waits for cmdbit to clear */
262         while (((status = stellaris_get_flash_status(bank)) & waitbits) && (timeout-- > 0))
263         {
264                 DEBUG("status: 0x%x", status);
265                 usleep(1000);
266         }
267         
268         /* Flash errors are reflected in the FLASH_CRIS register */
269
270         return status;
271 }
272
273
274 /* Send one command to the flash controller */
275 int stellaris_flash_command(struct flash_bank_s *bank,u8 cmd,u16 pagen) 
276 {
277         u32 fmc;
278         stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
279         target_t *target = stellaris_info->target;
280
281         fmc = FMC_WRKEY | cmd; 
282         target_write_u32(target, FLASH_CONTROL_BASE|FLASH_FMC, fmc);
283         DEBUG("Flash command: 0x%x", fmc);
284
285         if (stellaris_wait_status_busy(bank, cmd, 100)) 
286         {
287                 return ERROR_FLASH_OPERATION_FAILED;
288         }               
289
290         return ERROR_OK;
291 }
292
293 /* Read device id register, main clock frequency register and fill in driver info structure */
294 int stellaris_read_part_info(struct flash_bank_s *bank)
295 {
296         stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
297         target_t *target = stellaris_info->target;
298         u32 did0,did1, status;
299         int i;
300         
301         /* Read and parse chip identification register */
302         target_read_u32(target, SCB_BASE|DID0, &did0);
303         target_read_u32(target, SCB_BASE|DID1, &did1);
304         target_read_u32(target, SCB_BASE|DC0, &stellaris_info->dc0);
305         target_read_u32(target, SCB_BASE|DC1, &stellaris_info->dc1);
306         DEBUG("did0 0x%x, did1 0x%x, dc0 0x%x, dc1 0x%x",did0, did1, stellaris_info->dc0,stellaris_info->dc1);
307
308         if (((did0>>27)&0x7)) 
309         {
310                 WARNING("Unkown did0 version, cannot identify target");
311                 return ERROR_FLASH_OPERATION_FAILED;
312         
313         }
314
315         if (did1>>24) 
316         {
317                 WARNING("Unkown did1 version/family, cannot positively identify target as a Stellaris");
318         }
319
320         if (did1 == 0)
321         {
322                 WARNING("Cannot identify target as a Stellaris");
323                 return ERROR_FLASH_OPERATION_FAILED;
324         }
325         
326         for (i=0;StellarisParts[i].partno;i++)
327         {
328                 if (StellarisParts[i].partno==((did1>>16)&0xFF))
329                         break;
330         }
331         
332         stellaris_info->target_name = StellarisParts[i].partname;
333         
334         stellaris_info->did0 = did0;
335         stellaris_info->did1 = did1;
336         
337         stellaris_info->num_lockbits = 1+stellaris_info->dc0&0xFFFF;
338         stellaris_info->num_pages = 2*(1+stellaris_info->dc0&0xFFFF);
339         stellaris_info->pagesize = 1024;
340         bank->size = 1024*stellaris_info->num_pages;
341         stellaris_info->pages_in_lockregion = 2;
342         target_read_u32(target, SCB_BASE|FMPPE, &stellaris_info->lockbits);
343
344         // Read main and master clock freqency register 
345         stellaris_read_clock_info(bank);
346         
347         status = stellaris_get_flash_status(bank);
348         
349         WARNING("stellaris flash only tested for LM3S811 series");
350         
351         return ERROR_OK;
352 }
353
354 /***************************************************************************
355 *       flash operations                                         *
356 ***************************************************************************/
357
358 int stellaris_erase_check(struct flash_bank_s *bank)
359 {
360         stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
361         target_t *target = stellaris_info->target;
362         int i;
363         
364         /* */
365         
366         return ERROR_OK;
367 }
368
369 int stellaris_protect_check(struct flash_bank_s *bank)
370 {
371         u32 status;
372         
373         stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
374         target_t *target = stellaris_info->target;
375
376         if (stellaris_info->did1 == 0)
377         {
378                 stellaris_read_part_info(bank);
379         }
380
381         if (stellaris_info->did1 == 0)
382         {
383                 WARNING("Cannot identify target as an AT91SAM");
384                 return ERROR_FLASH_OPERATION_FAILED;
385         }
386                 
387         status = stellaris_get_flash_status(bank);
388         stellaris_info->lockbits = status >> 16;
389         
390         return ERROR_OK;
391 }
392
393 int stellaris_erase(struct flash_bank_s *bank, int first, int last)
394 {
395         int banknr;
396         u32 flash_fmc, flash_cris;
397         stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
398         target_t *target = stellaris_info->target;
399         
400         if (stellaris_info->target->state != TARGET_HALTED)
401         {
402                 return ERROR_TARGET_NOT_HALTED;
403         }
404         
405         if (stellaris_info->did1 == 0)
406         {
407                 stellaris_read_part_info(bank);
408         }
409
410         if (stellaris_info->did1 == 0)
411         {
412                 WARNING("Cannot identify target as an AT91SAM");
413                 return ERROR_FLASH_OPERATION_FAILED;
414         }       
415         
416         if ((first < 0) || (last < first) || (last >= stellaris_info->num_pages))
417         {
418                 return ERROR_FLASH_SECTOR_INVALID;
419         }
420
421         /* Configure the flash controller timing */
422         stellaris_read_clock_info(bank);        
423         stellaris_set_flash_mode(bank,0);
424
425         /* Clear and disable flash programming interrupts */
426         target_write_u32(target, FLASH_CIM, 0);
427         target_write_u32(target, FLASH_MISC, PMISC|AMISC);
428
429         if ((first == 0) && (last == (stellaris_info->num_pages-1)))
430         {
431                 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE);
432                 /* Wait until erase complete */
433                 do
434                 {
435                         target_read_u32(target, FLASH_FMC, &flash_fmc);
436                 }
437                 while(flash_fmc & FMC_MERASE);
438                 
439                 return ERROR_OK;
440         }
441
442         for (banknr=first;banknr<=last;banknr++)
443         {
444                 /* Address is first word in page */
445                 target_write_u32(target, FLASH_FMA, banknr*stellaris_info->pagesize);
446                 /* Write erase command */
447                 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_ERASE);
448                 /* Wait until erase complete */
449                 do
450                 {
451                         target_read_u32(target, FLASH_FMC, &flash_fmc);
452                 }
453                 while(flash_fmc & FMC_ERASE);
454
455                 /* Check acess violations */
456                 target_read_u32(target, FLASH_CRIS, &flash_cris);
457                 if(flash_cris & (AMASK))
458                 {
459                         WARNING("Error erasing flash page %i,  flash_cris 0x%x", banknr, flash_cris);
460                         target_write_u32(target, FLASH_CRIS, 0);
461                         return ERROR_FLASH_OPERATION_FAILED;
462                 }
463         }
464
465         return ERROR_OK;
466 }
467
468 int stellaris_protect(struct flash_bank_s *bank, int set, int first, int last)
469 {
470         u32 cmd, fmppe, flash_fmc, flash_cris;
471         int lockregion;
472         
473         stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
474         target_t *target = stellaris_info->target;
475         
476         if (stellaris_info->target->state != TARGET_HALTED)
477         {
478                 return ERROR_TARGET_NOT_HALTED;
479         }
480         
481         if ((first < 0) || (last < first) || (last >= stellaris_info->num_lockbits))
482         {
483                 return ERROR_FLASH_SECTOR_INVALID;
484         }
485         
486         if (stellaris_info->did1 == 0)
487         {
488                 stellaris_read_part_info(bank);
489         }
490
491         if (stellaris_info->did1 == 0)
492         {
493                 WARNING("Cannot identify target as an Stellaris MCU");
494                 return ERROR_FLASH_OPERATION_FAILED;
495         }
496         
497         /* Configure the flash controller timing */
498         stellaris_read_clock_info(bank);        
499         stellaris_set_flash_mode(bank,0);
500
501         fmppe = stellaris_info->lockbits;       
502         for (lockregion=first;lockregion<=last;lockregion++) 
503         {
504                 if (set)
505                          fmppe &= ~(1<<lockregion); 
506                 else
507                          fmppe |= (1<<lockregion); 
508         }
509
510         /* Clear and disable flash programming interrupts */
511         target_write_u32(target, FLASH_CIM, 0);
512         target_write_u32(target, FLASH_MISC, PMISC|AMISC);
513         
514         DEBUG("fmppe 0x%x",fmppe);
515         target_write_u32(target, SCB_BASE|FMPPE, fmppe);
516         /* Commit FMPPE */
517         target_write_u32(target, FLASH_FMA, 1);
518         /* Write commit command */
519         /* TODO safety check, sice this cannot be undone */
520         WARNING("Flash protection cannot be removed once commited, commit is NOT executed !");
521         /* target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_COMT); */
522         /* Wait until erase complete */
523         do
524         {
525                 target_read_u32(target, FLASH_FMC, &flash_fmc);
526         }
527         while(flash_fmc & FMC_COMT);
528
529         /* Check acess violations */
530         target_read_u32(target, FLASH_CRIS, &flash_cris);
531         if(flash_cris & (AMASK))
532         {
533                 WARNING("Error setting flash page protection,  flash_cris 0x%x", flash_cris);
534                 target_write_u32(target, FLASH_CRIS, 0);
535                 return ERROR_FLASH_OPERATION_FAILED;
536         }
537         
538         target_read_u32(target, SCB_BASE|FMPPE, &stellaris_info->lockbits);
539                 
540         return ERROR_OK;
541 }
542
543 u8 stellaris_write_code[] = 
544 {
545 /* Call with :  
546         r0 = buffer address
547         r1 = destination address
548         r2 = bytecount (in) - endaddr (work) 
549         r3 = pFLASH_CTRL_BASE
550         r4 = FLASHWRITECMD
551         r5 = #1
552         r6 = scratch
553         r7
554 */
555         0x07,0x4B,              /* ldr r3,pFLASH_CTRL_BASE */
556         0x08,0x4C,              /* ldr r4,FLASHWRITECMD */
557         0x01,0x25,              /* movs r5, 1 */
558         0x00,0x26,              /* movs r6, #0 */
559 /* mainloop: */
560         0x19,0x60,              /* str  r1, [r3, #0] */
561         0x87,0x59,              /* ldr  r7, [r0, r6] */
562         0x5F,0x60,              /* str  r7, [r3, #4] */
563         0x9C,0x60,              /* str  r4, [r3, #8] */
564 /* waitloop: */
565         0x9F,0x68,              /* ldr  r7, [r3, #8] */
566         0x2F,0x42,              /* tst  r7, r5 */
567         0xFC,0xD1,              /* bne  waitloop */
568         0x04,0x31,              /* adds r1, r1, #4 */
569         0x04,0x36,              /* adds r6, r6, #4 */
570         0x96,0x42,              /* cmp  r6, r2 */
571         0xF4,0xD1,              /* bne  mainloop */
572         0x00,0xBE,              /* bkpt #0 */
573 /* pFLASH_CTRL_BASE: */
574         0x00,0xD0,0x0F,0x40,    /* .word        0x400FD000 */
575 /* FLASHWRITECMD: */
576         0x01,0x00,0x42,0xA4     /* .word        0xA4420001 */
577 };
578
579 int stellaris_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 wcount)
580 {
581         stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
582         target_t *target = stellaris_info->target;
583         u32 buffer_size = 8192;
584         working_area_t *source;
585         working_area_t *write_algorithm;
586         u32 address = bank->base + offset;
587         reg_param_t reg_params[8];
588         armv7m_algorithm_t armv7m_info;
589         int retval;
590         
591
592         /* flash write code */
593         if (target_alloc_working_area(target, sizeof(stellaris_write_code), &write_algorithm) != ERROR_OK)
594                 {
595                         WARNING("no working area available, can't do block memory writes");
596                         return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
597                 };
598
599         target_write_buffer(target, write_algorithm->address, sizeof(stellaris_write_code), stellaris_write_code);
600
601         /* memory buffer */
602         while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
603         {
604                 buffer_size /= 2;
605                 if (buffer_size <= 256)
606                 {
607                         /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
608                         if (write_algorithm)
609                                 target_free_working_area(target, write_algorithm);
610                         
611                         WARNING("no large enough working area available, can't do block memory writes");
612                         return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
613                 }
614         };
615         
616         armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
617         armv7m_info.core_mode = ARMV7M_MODE_ANY;
618         armv7m_info.core_state = ARMV7M_STATE_THUMB;
619         
620         init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
621         init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
622         init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
623         init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
624         init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT);
625         init_reg_param(&reg_params[5], "r5", 32, PARAM_OUT);
626         init_reg_param(&reg_params[6], "r6", 32, PARAM_OUT);
627         init_reg_param(&reg_params[7], "r7", 32, PARAM_OUT);
628
629         while (wcount > 0)
630         {
631                 u32 thisrun_count = (wcount > (buffer_size / 4)) ? (buffer_size / 4) : wcount;
632                 
633                 target_write_buffer(target, source->address, thisrun_count * 4, buffer);
634                 
635                 buf_set_u32(reg_params[0].value, 0, 32, source->address);
636                 buf_set_u32(reg_params[1].value, 0, 32, address);
637                 buf_set_u32(reg_params[2].value, 0, 32, 4*thisrun_count);
638                 WARNING("Algorithm flash write  %i words to 0x%x, %i remaining",thisrun_count,address, wcount);
639                 DEBUG("Algorithm flash write  %i words to 0x%x, %i remaining",thisrun_count,address, wcount);
640                 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)
641                 {
642                         ERROR("error executing stellaris flash write algorithm");
643                         target_free_working_area(target, source);
644                         destroy_reg_param(&reg_params[0]);
645                         destroy_reg_param(&reg_params[1]);
646                         destroy_reg_param(&reg_params[2]);
647                         return ERROR_FLASH_OPERATION_FAILED;
648                 }
649         
650                 buffer += thisrun_count * 4;
651                 address += thisrun_count * 4;
652                 wcount -= thisrun_count;
653         }
654         
655
656         target_free_working_area(target, write_algorithm);
657         target_free_working_area(target, source);
658         
659         destroy_reg_param(&reg_params[0]);
660         destroy_reg_param(&reg_params[1]);
661         destroy_reg_param(&reg_params[2]);
662         destroy_reg_param(&reg_params[3]);
663         destroy_reg_param(&reg_params[4]);
664         destroy_reg_param(&reg_params[5]);
665         destroy_reg_param(&reg_params[6]);
666         destroy_reg_param(&reg_params[7]);
667         
668         return ERROR_OK;
669 }
670
671 int stellaris_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
672 {
673         stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
674         target_t *target = stellaris_info->target;
675         u32 dst_min_alignment, wcount, bytes_remaining = count;
676         u32 address = offset;
677         u32 fcr,flash_cris,flash_fmc;
678         u32 retval;
679         
680         if (stellaris_info->target->state != TARGET_HALTED)
681         {
682                 return ERROR_TARGET_NOT_HALTED;
683         }
684         
685         if (stellaris_info->did1 == 0)
686         {
687                 stellaris_read_part_info(bank);
688         }
689
690         if (stellaris_info->did1 == 0)
691         {
692                 WARNING("Cannot identify target as a Stellaris processor");
693                 return ERROR_FLASH_OPERATION_FAILED;
694         }
695         
696         if((offset & 3) || (count & 3))
697         {
698                 WARNING("offset size must be word aligned");
699                 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
700         }
701         
702         if (offset + count > bank->size)
703                 return ERROR_FLASH_DST_OUT_OF_BANK;
704
705         /* Configure the flash controller timing */     
706         stellaris_read_clock_info(bank);        
707         stellaris_set_flash_mode(bank,0);
708
709         
710         /* Clear and disable flash programming interrupts */
711         target_write_u32(target, FLASH_CIM, 0);
712         target_write_u32(target, FLASH_MISC, PMISC|AMISC);
713
714         /* multiple words to be programmed? */
715         if (count > 0) 
716         {
717                 /* try using a block write */
718                 if ((retval = stellaris_write_block(bank, buffer, offset, count/4)) != ERROR_OK)
719                 {
720                         if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
721                         {
722                                 /* if block write failed (no sufficient working area),
723                                  * we use normal (slow) single dword accesses */ 
724                                 WARNING("couldn't use block writes, falling back to single memory accesses");
725                         }
726                         else if (retval == ERROR_FLASH_OPERATION_FAILED)
727                         {
728                                 /* if an error occured, we examine the reason, and quit */
729                                 target_read_u32(target, FLASH_CRIS, &flash_cris);
730                                 
731                                 ERROR("flash writing failed with CRIS: 0x%x", flash_cris);
732                                 return ERROR_FLASH_OPERATION_FAILED;
733                         }
734                 }
735                 else
736                 {
737                         buffer += count * 4;
738                         address += count * 4;
739                         count = 0;
740                 }
741         }
742
743
744
745         while(count>0)
746         {
747                 if (!(address&0xff)) DEBUG("0x%x",address);
748                 /* Program one word */
749                 target_write_u32(target, FLASH_FMA, address);
750                 target_write_buffer(target, FLASH_FMD, 4, buffer);
751                 target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE);
752                 //DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE);
753                 /* Wait until write complete */
754                 do
755                 {
756                         target_read_u32(target, FLASH_FMC, &flash_fmc);
757                 }
758                 while(flash_fmc & FMC_WRITE);
759                 buffer += 4;
760                 address += 4;
761                 count -= 4;
762         }
763         /* Check acess violations */
764         target_read_u32(target, FLASH_CRIS, &flash_cris);
765         if(flash_cris & (AMASK))
766         {
767                 DEBUG("flash_cris 0x%x", flash_cris);
768                 return ERROR_FLASH_OPERATION_FAILED;
769         }
770         return ERROR_OK;
771 }
772
773
774 int stellaris_probe(struct flash_bank_s *bank)
775 {
776         /* we can't probe on an stellaris
777          * if this is an stellaris, it has the configured flash
778          */
779         stellaris_flash_bank_t *stellaris_info = bank->driver_priv;
780         
781         if (stellaris_info->did1 == 0)
782         {
783                 stellaris_read_part_info(bank);
784         }
785
786         if (stellaris_info->did1 == 0)
787         {
788                 WARNING("Cannot identify target as a LMI Stellaris");
789                 return ERROR_FLASH_OPERATION_FAILED;
790         }
791         
792         return ERROR_OK;
793 }