450bd5b70a79c5183e9c37b09bcf6aca0504d8bf
[fw/openocd] / src / flash / ecos.c
1 /***************************************************************************
2  *   Copyright (C) 2007,2008 Ã˜yvind Harboe                                 *
3  *   oyvind.harboe@zylin.com                                               *
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 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "flash.h"
25 #include "embeddedice.h"
26 #include "image.h"
27
28
29 #if 0
30 static uint32_t ecosflash_get_flash_status(flash_bank_t *bank);
31 static void ecosflash_set_flash_mode(flash_bank_t *bank,int mode);
32 static uint32_t ecosflash_wait_status_busy(flash_bank_t *bank, uint32_t waitbits, int timeout);
33 static int ecosflash_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
34 #endif
35
36 struct ecosflash_flash_bank
37 {
38         struct target_s *target;
39         struct working_area *write_algorithm;
40         struct working_area *erase_check_algorithm;
41         char *driverPath;
42         uint32_t start_address;
43 };
44
45 static const int sectorSize = 0x10000;
46
47 char *
48 flash_errmsg(int err);
49
50 #ifndef __ECOS
51 #define FLASH_ERR_OK              0x00  /* No error - operation complete */
52 #define FLASH_ERR_INVALID         0x01  /* Invalid FLASH address */
53 #define FLASH_ERR_ERASE           0x02  /* Error trying to erase */
54 #define FLASH_ERR_LOCK            0x03  /* Error trying to lock/unlock */
55 #define FLASH_ERR_PROGRAM         0x04  /* Error trying to program */
56 #define FLASH_ERR_PROTOCOL        0x05  /* Generic error */
57 #define FLASH_ERR_PROTECT         0x06  /* Device/region is write-protected */
58 #define FLASH_ERR_NOT_INIT        0x07  /* FLASH info not yet initialized */
59 #define FLASH_ERR_HWR             0x08  /* Hardware (configuration?) problem */
60 #define FLASH_ERR_ERASE_SUSPEND   0x09  /* Device is in erase suspend mode */
61 #define FLASH_ERR_PROGRAM_SUSPEND 0x0a  /* Device is in in program suspend mode */
62 #define FLASH_ERR_DRV_VERIFY      0x0b  /* Driver failed to verify data */
63 #define FLASH_ERR_DRV_TIMEOUT     0x0c  /* Driver timed out waiting for device */
64 #define FLASH_ERR_DRV_WRONG_PART  0x0d  /* Driver does not support device */
65 #define FLASH_ERR_LOW_VOLTAGE     0x0e  /* Not enough juice to complete job */
66
67 char *
68 flash_errmsg(int err)
69 {
70         switch (err) {
71         case FLASH_ERR_OK:
72                 return "No error - operation complete";
73         case FLASH_ERR_ERASE_SUSPEND:
74                 return "Device is in erase suspend state";
75         case FLASH_ERR_PROGRAM_SUSPEND:
76                 return "Device is in program suspend state";
77         case FLASH_ERR_INVALID:
78                 return "Invalid FLASH address";
79         case FLASH_ERR_ERASE:
80                 return "Error trying to erase";
81         case FLASH_ERR_LOCK:
82                 return "Error trying to lock/unlock";
83         case FLASH_ERR_PROGRAM:
84                 return "Error trying to program";
85         case FLASH_ERR_PROTOCOL:
86                 return "Generic error";
87         case FLASH_ERR_PROTECT:
88                 return "Device/region is write-protected";
89         case FLASH_ERR_NOT_INIT:
90                 return "FLASH sub-system not initialized";
91         case FLASH_ERR_DRV_VERIFY:
92                 return "Data verify failed after operation";
93         case FLASH_ERR_DRV_TIMEOUT:
94                 return "Driver timed out waiting for device";
95         case FLASH_ERR_DRV_WRONG_PART:
96                 return "Driver does not support device";
97         case FLASH_ERR_LOW_VOLTAGE:
98                 return "Device reports low voltage";
99         default:
100                 return "Unknown error";
101         }
102 }
103 #endif
104
105 /* flash bank ecosflash <base> <size> <chip_width> <bus_width> <target#> <driverPath>
106  */
107 FLASH_BANK_COMMAND_HANDLER(ecosflash_flash_bank_command)
108 {
109         struct ecosflash_flash_bank *info;
110
111         if (argc < 7)
112         {
113                 LOG_WARNING("incomplete flash_bank ecosflash configuration");
114                 return ERROR_FLASH_BANK_INVALID;
115         }
116
117         info = malloc(sizeof(struct ecosflash_flash_bank));
118         if (info == NULL)
119         {
120                 LOG_ERROR("no memory for flash bank info");
121                 exit(-1);
122         }
123         bank->driver_priv = info;
124         info->driverPath = strdup(args[6]);
125
126         /* eCos flash sector sizes are not exposed to OpenOCD, use 0x10000 as
127          * a way to improve impedance match between OpenOCD and eCos flash
128          * driver.
129          */
130         int i = 0;
131         uint32_t offset = 0;
132         bank->num_sectors = bank->size/sectorSize;
133         bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
134         for (i = 0; i < bank->num_sectors; i++)
135         {
136                 bank->sectors[i].offset = offset;
137                 bank->sectors[i].size = sectorSize;
138                 offset += bank->sectors[i].size;
139                 bank->sectors[i].is_erased = -1;
140                 bank->sectors[i].is_protected = 0;
141         }
142
143         info->target = get_target(args[5]);
144         if (info->target == NULL)
145         {
146                 LOG_ERROR("target '%s' not defined", args[5]);
147                 return ERROR_FAIL;
148         }
149         return ERROR_OK;
150 }
151
152 static int loadDriver(struct ecosflash_flash_bank *info)
153 {
154         uint32_t buf_cnt;
155         uint32_t image_size;
156         image_t image;
157
158         image.base_address_set = 0;
159         image.start_address_set = 0;
160         target_t *target = info->target;
161         int retval;
162
163         if ((retval = image_open(&image, info->driverPath, NULL)) != ERROR_OK)
164         {
165                 return retval;
166         }
167
168         info->start_address = image.start_address;
169
170         image_size = 0x0;
171         int i;
172         for (i = 0; i < image.num_sections; i++)
173         {
174                 void *buffer = malloc(image.sections[i].size);
175                 int retval;
176                 if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
177                 {
178                         free(buffer);
179                         image_close(&image);
180                         return retval;
181                 }
182                 target_write_buffer(target, image.sections[i].base_address, buf_cnt, buffer);
183                 image_size += buf_cnt;
184                 LOG_DEBUG("%" PRIu32 " byte written at address 0x%8.8" PRIx32 "", buf_cnt, image.sections[i].base_address);
185
186                 free(buffer);
187         }
188
189         image_close(&image);
190
191         return ERROR_OK;
192 }
193
194 static int const OFFSET_ERASE = 0x0;
195 static int const OFFSET_ERASE_SIZE = 0x8;
196 static int const OFFSET_FLASH = 0xc;
197 static int const OFFSET_FLASH_SIZE = 0x8;
198 static int const OFFSET_GET_WORKAREA = 0x18;
199 static int const OFFSET_GET_WORKAREA_SIZE = 0x4;
200
201 static int runCode(struct ecosflash_flash_bank *info,
202                 uint32_t codeStart, uint32_t codeStop, uint32_t r0, uint32_t r1, uint32_t r2,
203                 uint32_t *result,
204                 /* timeout in ms */
205                 int timeout)
206 {
207         target_t *target = info->target;
208
209         struct reg_param reg_params[3];
210         struct armv4_5_algorithm armv4_5_info;
211         armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
212         armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
213         armv4_5_info.core_state = ARMV4_5_STATE_ARM;
214
215         init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
216         init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
217         init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
218
219         buf_set_u32(reg_params[0].value, 0, 32, r0);
220         buf_set_u32(reg_params[1].value, 0, 32, r1);
221         buf_set_u32(reg_params[2].value, 0, 32, r2);
222
223         int retval;
224         if ((retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
225                         codeStart,
226                         codeStop, timeout,
227                         &armv4_5_info)) != ERROR_OK)
228         {
229                 LOG_ERROR("error executing eCos flash algorithm");
230                 return retval;
231         }
232
233         *result = buf_get_u32(reg_params[0].value, 0, 32);
234
235         destroy_reg_param(&reg_params[0]);
236         destroy_reg_param(&reg_params[1]);
237         destroy_reg_param(&reg_params[2]);
238
239         return ERROR_OK;
240 }
241
242 static int eCosBoard_erase(struct ecosflash_flash_bank *info, uint32_t address, uint32_t len)
243 {
244         int retval;
245         int timeout = (len / 20480 + 1) * 1000; /*asume 20 KB/s*/
246
247         retval = loadDriver(info);
248         if (retval != ERROR_OK)
249                 return retval;
250
251         uint32_t flashErr;
252         retval = runCode(info,
253                         info->start_address + OFFSET_ERASE,
254                         info->start_address + OFFSET_ERASE + OFFSET_ERASE_SIZE,
255                         address,
256                         len,
257                         0,
258                         &flashErr,
259                         timeout
260 );
261         if (retval != ERROR_OK)
262                 return retval;
263
264         if (flashErr != 0x0)
265         {
266                 LOG_ERROR("Flash erase failed with %d (%s)\n", (int)flashErr, flash_errmsg(flashErr));
267                 return ERROR_FAIL;
268         }
269
270         return ERROR_OK;
271 }
272
273 static int eCosBoard_flash(struct ecosflash_flash_bank *info, void *data, uint32_t address, uint32_t len)
274 {
275         target_t *target = info->target;
276         const int chunk = 8192;
277         int retval = ERROR_OK;
278         int timeout = (chunk / 20480 + 1) * 1000; /*asume 20 KB/s + 1 second*/
279
280         retval = loadDriver(info);
281         if (retval != ERROR_OK)
282                 return retval;
283
284         uint32_t buffer;
285         retval = runCode(info,
286                         info->start_address + OFFSET_GET_WORKAREA,
287                         info->start_address + OFFSET_GET_WORKAREA + OFFSET_GET_WORKAREA_SIZE,
288                         0,
289                         0,
290                         0,
291                         &buffer,
292                         1000);
293         if (retval != ERROR_OK)
294                 return retval;
295
296
297         uint32_t i;
298         for (i = 0; i < len; i += chunk)
299         {
300                 int t = len-i;
301                 if (t > chunk)
302                 {
303                         t = chunk;
304                 }
305
306                 int retval;
307                 retval = target_write_buffer(target, buffer, t, ((uint8_t *)data) + i);
308                 if (retval != ERROR_OK)
309                         return retval;
310
311                 uint32_t flashErr;
312                 retval = runCode(info,
313                                 info->start_address + OFFSET_FLASH,
314                                 info->start_address + OFFSET_FLASH + OFFSET_FLASH_SIZE,
315                                 buffer,
316                                 address + i,
317                                 t,
318                                 &flashErr,
319                                 timeout);
320                 if (retval != ERROR_OK)
321                         return retval;
322
323                 if (flashErr != 0x0)
324                 {
325                         LOG_ERROR("Flash prog failed with %d (%s)\n", (int)flashErr, flash_errmsg(flashErr));
326                         return ERROR_FAIL;
327                 }
328         }
329         return ERROR_OK;
330 }
331
332 static int ecosflash_probe(struct flash_bank_s *bank)
333 {
334         return ERROR_OK;
335 }
336
337 static int ecosflash_register_commands(struct command_context_s *cmd_ctx)
338 {
339         register_command(cmd_ctx, NULL, "ecosflash", NULL, COMMAND_ANY, NULL);
340
341         return ERROR_OK;
342 }
343
344 #if 0
345 static void command(flash_bank_t *bank, uint8_t cmd, uint8_t *cmd_buf)
346 {
347         struct ecosflash_flash_bank *info = bank->driver_priv;
348         int i;
349
350         if (info->target->endianness == TARGET_LITTLE_ENDIAN)
351         {
352                 for (i = bank->bus_width; i > 0; i--)
353                 {
354                         *cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;
355                 }
356         }
357         else
358         {
359                 for (i = 1; i <= bank->bus_width; i++)
360                 {
361                         *cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd;
362                 }
363         }
364 }
365 #endif
366
367 #if 0
368 static uint32_t ecosflash_address(struct flash_bank_s *bank, uint32_t address)
369 {
370         uint32_t retval = 0;
371         switch (bank->bus_width)
372         {
373                 case 4:
374                         retval = address & 0xfffffffc;
375                 case 2:
376                         retval = address & 0xfffffffe;
377                 case 1:
378                         retval = address;
379         }
380
381         return retval + bank->base;
382 }
383 #endif
384
385 static int ecosflash_erase(struct flash_bank_s *bank, int first, int last)
386 {
387         struct flash_bank_s *c = bank;
388         struct ecosflash_flash_bank *info = bank->driver_priv;
389         return eCosBoard_erase(info, c->base + first*sectorSize, sectorSize*(last-first + 1));
390 }
391
392 static int ecosflash_protect(struct flash_bank_s *bank, int set, int first, int last)
393 {
394         return ERROR_OK;
395 }
396
397 static int ecosflash_write(struct flash_bank_s *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
398 {
399         struct ecosflash_flash_bank *info = bank->driver_priv;
400         struct flash_bank_s *c = bank;
401         return eCosBoard_flash(info, buffer, c->base + offset, count);
402 }
403
404 static int ecosflash_protect_check(struct flash_bank_s *bank)
405 {
406         return ERROR_OK;
407 }
408
409 static int ecosflash_info(struct flash_bank_s *bank, char *buf, int buf_size)
410 {
411         struct ecosflash_flash_bank *info = bank->driver_priv;
412         snprintf(buf, buf_size, "eCos flash driver: %s", info->driverPath);
413         return ERROR_OK;
414 }
415
416 #if 0
417 static uint32_t ecosflash_get_flash_status(flash_bank_t *bank)
418 {
419         return ERROR_OK;
420 }
421
422 static void ecosflash_set_flash_mode(flash_bank_t *bank,int mode)
423 {
424
425 }
426
427 static uint32_t ecosflash_wait_status_busy(flash_bank_t *bank, uint32_t waitbits, int timeout)
428 {
429         return ERROR_OK;
430 }
431
432 static int ecosflash_handle_gpnvm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
433 {
434         return ERROR_OK;
435 }
436 #endif
437
438 struct flash_driver ecosflash_flash = {
439                 .name = "ecosflash",
440                 .register_commands = &ecosflash_register_commands,
441                 .flash_bank_command = &ecosflash_flash_bank_command,
442                 .erase = &ecosflash_erase,
443                 .protect = &ecosflash_protect,
444                 .write = &ecosflash_write,
445                 .probe = &ecosflash_probe,
446                 .auto_probe = &ecosflash_probe,
447                 .erase_check = &default_flash_blank_check,
448                 .protect_check = &ecosflash_protect_check,
449                 .info = &ecosflash_info
450         };