af846c2b46b37b580ad3d5f0cf0eb6bfa5f4d3ea
[fw/openocd] / src / flash / nor / aduc702x.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 /***************************************************************************
4  *   Copyright (C) 2008 by Kevin McGuire                                   *
5  *   Copyright (C) 2008 by Marcel Wijlaars                                 *
6  *   Copyright (C) 2009 by Michael Ashton                                  *
7  ***************************************************************************/
8
9 #ifdef HAVE_CONFIG_H
10 #include "config.h"
11 #endif
12
13 #include "imp.h"
14 #include <helper/binarybuffer.h>
15 #include <helper/time_support.h>
16 #include <target/algorithm.h>
17 #include <target/arm.h>
18
19 static int aduc702x_build_sector_list(struct flash_bank *bank);
20 static int aduc702x_check_flash_completion(struct target *target, unsigned int timeout_ms);
21 static int aduc702x_set_write_enable(struct target *target, int enable);
22
23 #define ADUC702X_FLASH                          0xfffff800
24 #define ADUC702X_FLASH_FEESTA           (0*4)
25 #define ADUC702X_FLASH_FEEMOD           (1*4)
26 #define ADUC702X_FLASH_FEECON           (2*4)
27 #define ADUC702X_FLASH_FEEDAT           (3*4)
28 #define ADUC702X_FLASH_FEEADR           (4*4)
29 #define ADUC702X_FLASH_FEESIGN          (5*4)
30 #define ADUC702X_FLASH_FEEPRO           (6*4)
31 #define ADUC702X_FLASH_FEEHIDE          (7*4)
32
33 /* flash bank aduc702x 0 0 0 0 <target#>
34  * The ADC7019-28 devices all have the same flash layout */
35 FLASH_BANK_COMMAND_HANDLER(aduc702x_flash_bank_command)
36 {
37         bank->base = 0x80000;
38         bank->size = 0xF800;    /* top 4k not accessible */
39
40         aduc702x_build_sector_list(bank);
41
42         return ERROR_OK;
43 }
44
45 static int aduc702x_build_sector_list(struct flash_bank *bank)
46 {
47         /* aduc7026_struct flash_bank *aduc7026_info = bank->driver_priv; */
48
49         uint32_t offset = 0;
50
51         /* sector size is 512 */
52         bank->num_sectors = bank->size / 512;
53         bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
54         for (unsigned int i = 0; i < bank->num_sectors; ++i) {
55                 bank->sectors[i].offset = offset;
56                 bank->sectors[i].size = 512;
57                 offset += bank->sectors[i].size;
58                 bank->sectors[i].is_erased = -1;
59                 bank->sectors[i].is_protected = 0;
60         }
61
62         return ERROR_OK;
63 }
64
65 static int aduc702x_erase(struct flash_bank *bank, unsigned int first,
66                 unsigned int last)
67 {
68         /* int res; */
69         int x;
70         int count;
71         /* uint32_t v; */
72         struct target *target = bank->target;
73
74         aduc702x_set_write_enable(target, 1);
75
76         /* mass erase */
77         if (((first | last) == 0) || ((first == 0) && (last >= bank->num_sectors))) {
78                 LOG_DEBUG("performing mass erase.");
79                 target_write_u16(target, ADUC702X_FLASH + ADUC702X_FLASH_FEEDAT, 0x3cff);
80                 target_write_u16(target, ADUC702X_FLASH + ADUC702X_FLASH_FEEADR, 0xffc3);
81                 target_write_u8(target, ADUC702X_FLASH + ADUC702X_FLASH_FEECON, 0x06);
82
83                 if (aduc702x_check_flash_completion(target, 3500) != ERROR_OK) {
84                         LOG_ERROR("mass erase failed");
85                         aduc702x_set_write_enable(target, 0);
86                         return ERROR_FLASH_OPERATION_FAILED;
87                 }
88
89                 LOG_DEBUG("mass erase successful.");
90                 return ERROR_OK;
91         } else {
92                 unsigned long adr;
93
94                 count = last - first + 1;
95                 for (x = 0; x < count; ++x) {
96                         adr = bank->base + ((first + x) * 512);
97
98                         target_write_u16(target, ADUC702X_FLASH + ADUC702X_FLASH_FEEADR, adr);
99                         target_write_u8(target, ADUC702X_FLASH + ADUC702X_FLASH_FEECON, 0x05);
100
101                         if (aduc702x_check_flash_completion(target, 50) != ERROR_OK) {
102                                 LOG_ERROR("failed to erase sector at address 0x%08lX", adr);
103                                 aduc702x_set_write_enable(target, 0);
104                                 return ERROR_FLASH_SECTOR_NOT_ERASED;
105                         }
106
107                         LOG_DEBUG("erased sector at address 0x%08lX", adr);
108                 }
109         }
110
111         aduc702x_set_write_enable(target, 0);
112
113         return ERROR_OK;
114 }
115
116 /* If this fn returns ERROR_TARGET_RESOURCE_NOT_AVAILABLE, then the caller can fall
117  * back to another mechanism that does not require onboard RAM
118  *
119  * Caller should not check for other return values specifically
120  */
121 static int aduc702x_write_block(struct flash_bank *bank,
122         const uint8_t *buffer,
123         uint32_t offset,
124         uint32_t count)
125 {
126         struct target *target = bank->target;
127         uint32_t buffer_size = 7000;
128         struct working_area *write_algorithm;
129         struct working_area *source;
130         uint32_t address = bank->base + offset;
131         struct reg_param reg_params[6];
132         struct arm_algorithm arm_algo;
133         int retval = ERROR_OK;
134
135         if (((count%2) != 0) || ((offset%2) != 0)) {
136                 LOG_ERROR("write block must be multiple of two bytes in offset & length");
137                 return ERROR_FAIL;
138         }
139
140         /* parameters:
141
142         r0 - address of source data (absolute)
143         r1 - number of halfwords to be copied
144         r2 - start address in flash (offset from beginning of flash memory)
145         r3 - exit code
146         r4 - base address of flash controller (0xFFFFF800)
147
148         registers:
149
150         r5 - scratch
151         r6 - set to 2, used to write flash command
152
153         */
154         static const uint32_t aduc702x_flash_write_code[] = {
155                 /* <_start>: */
156                 0xe3a05008,     /* mov  r5, #8  ; 0x8 */
157                 0xe5845004,     /* str  r5, [r4, #4] */
158                 0xe3a06002,     /* mov  r6, #2  ; 0x2 */
159                 /* <next>: */
160                 0xe1c421b0,     /* strh r2, [r4, #16] */
161                 0xe0d050b2,     /* ldrh r5, [r0], #2 */
162                 0xe1c450bc,     /* strh r5, [r4, #12] */
163                 0xe5c46008,     /* strb r6, [r4, #8] */
164                 /* <wait_complete>: */
165                 0xe1d430b0,     /* ldrh r3, [r4] */
166                 0xe3130004,     /* tst  r3, #4  ; 0x4 */
167                 0x1afffffc,     /* bne  1001c <wait_complete> */
168                 0xe2822002,     /* add  r2, r2, #2      ; 0x2 */
169                 0xe2511001,     /* subs r1, r1, #1      ; 0x1 */
170                 0x0a000001,     /* beq  1003c <done> */
171                 0xe3130001,     /* tst  r3, #1  ; 0x1 */
172                 0x1afffff3,     /* bne  1000c <next> */
173                 /* <done>: */
174                 0xeafffffe      /* b    1003c <done> */
175         };
176
177         /* flash write code */
178         if (target_alloc_working_area(target, sizeof(aduc702x_flash_write_code),
179                         &write_algorithm) != ERROR_OK) {
180                 LOG_WARNING("no working area available, can't do block memory writes");
181                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
182         }
183
184         uint8_t code[sizeof(aduc702x_flash_write_code)];
185         target_buffer_set_u32_array(target, code, ARRAY_SIZE(aduc702x_flash_write_code),
186                         aduc702x_flash_write_code);
187         retval = target_write_buffer(target, write_algorithm->address, sizeof(code), code);
188         if (retval != ERROR_OK)
189                 return retval;
190
191         /* memory buffer */
192         while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
193                 buffer_size /= 2;
194                 if (buffer_size <= 256) {
195                         /* we already allocated the writing code, but failed to get a buffer,
196                          *free the algorithm */
197                         target_free_working_area(target, write_algorithm);
198
199                         LOG_WARNING("no large enough working area available, can't do block memory writes");
200                         return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
201                 }
202         }
203
204         arm_algo.common_magic = ARM_COMMON_MAGIC;
205         arm_algo.core_mode = ARM_MODE_SVC;
206         arm_algo.core_state = ARM_STATE_ARM;
207
208         init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
209         init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
210         init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
211         init_reg_param(&reg_params[3], "r3", 32, PARAM_IN);
212         init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT);
213
214         while (count > 0) {
215                 uint32_t thisrun_count = (count > buffer_size) ? buffer_size : count;
216
217                 retval = target_write_buffer(target, source->address, thisrun_count, buffer);
218                 if (retval != ERROR_OK)
219                         break;
220
221                 buf_set_u32(reg_params[0].value, 0, 32, source->address);
222                 buf_set_u32(reg_params[1].value, 0, 32, thisrun_count/2);
223                 buf_set_u32(reg_params[2].value, 0, 32, address);
224                 buf_set_u32(reg_params[4].value, 0, 32, 0xFFFFF800);
225
226                 retval = target_run_algorithm(target, 0, NULL, 5,
227                                 reg_params, write_algorithm->address,
228                                 write_algorithm->address +
229                                 sizeof(aduc702x_flash_write_code) - 4,
230                                 10000, &arm_algo);
231                 if (retval != ERROR_OK) {
232                         LOG_ERROR("error executing aduc702x flash write algorithm");
233                         break;
234                 }
235
236                 if ((buf_get_u32(reg_params[3].value, 0, 32) & 1) != 1) {
237                         /* FIX!!!! what does this mean??? replace w/sensible error message */
238                         LOG_ERROR("aduc702x detected error writing flash");
239                         retval = ERROR_FAIL;
240                         break;
241                 }
242
243                 buffer += thisrun_count;
244                 address += thisrun_count;
245                 count -= thisrun_count;
246         }
247
248         target_free_working_area(target, source);
249         target_free_working_area(target, write_algorithm);
250
251         destroy_reg_param(&reg_params[0]);
252         destroy_reg_param(&reg_params[1]);
253         destroy_reg_param(&reg_params[2]);
254         destroy_reg_param(&reg_params[3]);
255         destroy_reg_param(&reg_params[4]);
256
257         return retval;
258 }
259
260 /* All-JTAG, single-access method.  Very slow.  Used only if there is no
261  * working area available. */
262 static int aduc702x_write_single(struct flash_bank *bank,
263         const uint8_t *buffer,
264         uint32_t offset,
265         uint32_t count)
266 {
267         uint32_t x;
268         uint8_t b;
269         struct target *target = bank->target;
270
271         aduc702x_set_write_enable(target, 1);
272
273         for (x = 0; x < count; x += 2) {
274                 /* FEEADR = address */
275                 target_write_u16(target, ADUC702X_FLASH + ADUC702X_FLASH_FEEADR, offset + x);
276
277                 /* set up data */
278                 if ((x + 1) == count) {
279                         /* last byte */
280                         target_read_u8(target, offset + x + 1, &b);
281                 } else
282                         b = buffer[x + 1];
283
284                 target_write_u16(target, ADUC702X_FLASH + ADUC702X_FLASH_FEEDAT, buffer[x] | (b << 8));
285
286                 /* do single-write command */
287                 target_write_u8(target, ADUC702X_FLASH + ADUC702X_FLASH_FEECON, 0x02);
288
289                 if (aduc702x_check_flash_completion(target, 1) != ERROR_OK) {
290                         LOG_ERROR("single write failed for address 0x%08lX",
291                                 (unsigned long)(offset + x));
292                         aduc702x_set_write_enable(target, 0);
293                         return ERROR_FLASH_OPERATION_FAILED;
294                 }
295
296         }
297         LOG_DEBUG("wrote %d bytes at address 0x%08lX", (int)count, (unsigned long)(offset + x));
298
299         aduc702x_set_write_enable(target, 0);
300
301         return ERROR_OK;
302 }
303
304 static int aduc702x_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
305 {
306         int retval;
307
308         /* try using a block write */
309         retval = aduc702x_write_block(bank, buffer, offset, count);
310         if (retval != ERROR_OK) {
311                 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
312                         /* if block write failed (no sufficient working area),
313                          * use normal (slow) JTAG method */
314                         LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
315
316                         retval = aduc702x_write_single(bank, buffer, offset, count);
317                         if (retval != ERROR_OK) {
318                                 LOG_ERROR("slow write failed");
319                                 return ERROR_FLASH_OPERATION_FAILED;
320                         }
321                 }
322         }
323
324         return retval;
325 }
326
327 static int aduc702x_probe(struct flash_bank *bank)
328 {
329         return ERROR_OK;
330 }
331
332 /* sets FEEMOD bit 3
333  * enable = 1 enables writes & erases, 0 disables them */
334 static int aduc702x_set_write_enable(struct target *target, int enable)
335 {
336         /* don't bother to preserve int enable bit here */
337         target_write_u16(target, ADUC702X_FLASH + ADUC702X_FLASH_FEEMOD, enable ? 8 : 0);
338
339         return ERROR_OK;
340 }
341
342 /* wait up to timeout_ms for controller to not be busy,
343  * then check whether the command passed or failed.
344  *
345  * this function sleeps 1ms between checks (after the first one),
346  * so in some cases may slow things down without a usleep after the first read */
347 static int aduc702x_check_flash_completion(struct target *target, unsigned int timeout_ms)
348 {
349         uint8_t v = 4;
350
351         int64_t endtime = timeval_ms() + timeout_ms;
352         while (1) {
353                 target_read_u8(target, ADUC702X_FLASH + ADUC702X_FLASH_FEESTA, &v);
354                 if ((v & 4) == 0)
355                         break;
356                 alive_sleep(1);
357                 if (timeval_ms() >= endtime)
358                         break;
359         }
360
361         if (v & 2)
362                 return ERROR_FAIL;
363         /* if a command is ignored, both the success and fail bits may be 0 */
364         else if ((v & 3) == 0)
365                 return ERROR_FAIL;
366         else
367                 return ERROR_OK;
368 }
369
370 const struct flash_driver aduc702x_flash = {
371         .name = "aduc702x",
372         .flash_bank_command = aduc702x_flash_bank_command,
373         .erase = aduc702x_erase,
374         .write = aduc702x_write,
375         .read = default_flash_read,
376         .probe = aduc702x_probe,
377         .auto_probe = aduc702x_probe,
378         .erase_check = default_flash_blank_check,
379 };