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

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)