openocd: fix SPDX tag format for files .c
[fw/openocd] / src / flash / nor / ocl.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4  *   Copyright (C) 2007 by Pavel Chromy                                    *
5  *   chromy@asix.cz                                                        *
6  ***************************************************************************/
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
12 #include "imp.h"
13 #include "ocl.h"
14 #include <target/embeddedice.h>
15
16 struct ocl_priv {
17         struct arm_jtag *jtag_info;
18         unsigned int buflen;
19         unsigned int bufalign;
20 };
21
22 /* flash_bank ocl 0 0 0 0 <target#> */
23 FLASH_BANK_COMMAND_HANDLER(ocl_flash_bank_command)
24 {
25         struct arm7_9_common *arm7_9;
26         struct ocl_priv *ocl;
27
28         if (CMD_ARGC < 6)
29                 return ERROR_COMMAND_SYNTAX_ERROR;
30
31         arm7_9 = target_to_arm7_9(bank->target);
32         if (!is_arm7_9(arm7_9))
33                 return ERROR_TARGET_INVALID;
34
35         ocl = bank->driver_priv = malloc(sizeof(struct ocl_priv));
36         ocl->jtag_info = &arm7_9->jtag_info;
37         ocl->buflen = 0;
38         ocl->bufalign = 1;
39
40         return ERROR_OK;
41 }
42
43 static int ocl_erase(struct flash_bank *bank, unsigned int first,
44                 unsigned int last)
45 {
46         struct ocl_priv *ocl = bank->driver_priv;
47         int retval;
48         uint32_t dcc_buffer[3];
49
50         /* check preconditions */
51         if (bank->num_sectors == 0)
52                 return ERROR_FLASH_BANK_NOT_PROBED;
53
54         if (bank->target->state != TARGET_RUNNING) {
55                 LOG_ERROR("target has to be running to communicate with the loader");
56                 return ERROR_TARGET_NOT_RUNNING;
57         }
58
59         if ((first == 0) && (last == bank->num_sectors - 1)) {
60                 dcc_buffer[0] = OCL_ERASE_ALL;
61                 retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1);
62                 if (retval != ERROR_OK)
63                         return retval;
64         } else {
65                 dcc_buffer[0] = OCL_ERASE_BLOCK;
66                 dcc_buffer[1] = first;
67                 dcc_buffer[2] = last;
68                 retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 3);
69                 if (retval != ERROR_OK)
70                         return retval;
71         }
72
73         /* wait for response, fixed timeout of 1 s */
74         retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000);
75         if (retval != ERROR_OK)
76                 return retval;
77
78         /* receive response */
79         retval = embeddedice_receive(ocl->jtag_info, dcc_buffer + 1, 1);
80         if (retval != ERROR_OK)
81                 return retval;
82
83         if (dcc_buffer[1] != OCL_CMD_DONE) {
84                 if (dcc_buffer[0] == OCL_ERASE_ALL)
85                         LOG_ERROR("loader response to OCL_ERASE_ALL 0x%08" PRIx32 "", dcc_buffer[1]);
86                 else
87                         LOG_ERROR("loader response to OCL_ERASE_BLOCK 0x%08" PRIx32 "", dcc_buffer[1]);
88                 return ERROR_FLASH_OPERATION_FAILED;
89         }
90
91         return ERROR_OK;
92 }
93
94 static int ocl_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
95 {
96         struct ocl_priv *ocl = bank->driver_priv;
97         int retval;
98         uint32_t *dcc_buffer;
99         uint32_t *dcc_bufptr;
100         int byteofs;
101         int runlen;
102         uint32_t chksum;
103
104         int i;
105
106         /* check preconditions */
107         if (ocl->buflen == 0 || ocl->bufalign == 0)
108                 return ERROR_FLASH_BANK_NOT_PROBED;
109
110         if (bank->target->state != TARGET_RUNNING) {
111                 LOG_ERROR("target has to be running to communicate with the loader");
112                 return ERROR_TARGET_NOT_RUNNING;
113         }
114
115         /* allocate buffer for max. ocl buffer + overhead */
116         dcc_buffer = malloc(sizeof(uint32_t)*(ocl->buflen/4 + 3));
117
118         while (count) {
119                 if (count + (offset % ocl->bufalign) > ocl->buflen)
120                         runlen = ocl->buflen - (offset % ocl->bufalign);
121                 else
122                         runlen = count;
123
124                 dcc_buffer[0] = OCL_FLASH_BLOCK | runlen;
125                 dcc_buffer[1] = offset;
126                 dcc_bufptr = &dcc_buffer[2];
127
128                 *dcc_bufptr = 0xffffffff;
129                 byteofs = (offset % ocl->bufalign) % 4;
130                 chksum = OCL_CHKS_INIT;
131
132                 /* copy data to DCC buffer in proper byte order and properly aligned */
133                 for (i = 0; i < runlen; i++) {
134                         switch (byteofs++) {
135                                 case 0:
136                                         *dcc_bufptr &= *(buffer++) | 0xffffff00;
137                                         break;
138                                 case 1:
139                                         *dcc_bufptr &= ((*(buffer++)) << 8) | 0xffff00ff;
140                                         break;
141                                 case 2:
142                                         *dcc_bufptr &= ((*(buffer++)) << 16) | 0xff00ffff;
143                                         break;
144                                 case 3:
145                                         *dcc_bufptr &= ((*(buffer++)) << 24) | 0x00ffffff;
146                                         chksum ^= *(dcc_bufptr++);
147                                         *dcc_bufptr = 0xffffffff;
148                                         byteofs = 0;
149                                         break;
150                         }
151                 }
152
153                 /* add the remaining word to checksum */
154                 if (byteofs)
155                         chksum ^= *(dcc_bufptr++);
156
157                 *(dcc_bufptr++) = chksum;
158
159                 /* send the data */
160                 retval = embeddedice_send(ocl->jtag_info, dcc_buffer, dcc_bufptr-dcc_buffer);
161                 if (retval != ERROR_OK) {
162                         free(dcc_buffer);
163                   return retval;
164                 }
165
166                 /* wait for response, fixed timeout of 1 s */
167                 retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000);
168                 if (retval != ERROR_OK) {
169                         free(dcc_buffer);
170                         return retval;
171                 }
172
173                 /* receive response */
174                 retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
175                 if (retval != ERROR_OK) {
176                         free(dcc_buffer);
177                         return retval;
178                 }
179
180                 if (dcc_buffer[0] != OCL_CMD_DONE) {
181                         LOG_ERROR("loader response to OCL_FLASH_BLOCK 0x%08" PRIx32 "", dcc_buffer[0]);
182                         free(dcc_buffer);
183                         return ERROR_FLASH_OPERATION_FAILED;
184                 }
185
186                 count -= runlen;
187                 offset += runlen;
188         }
189
190         free(dcc_buffer);
191         return ERROR_OK;
192 }
193
194 static int ocl_probe(struct flash_bank *bank)
195 {
196         struct ocl_priv *ocl = bank->driver_priv;
197         int retval;
198         uint32_t dcc_buffer[1];
199         int sectsize;
200
201         /* purge pending data in DCC */
202         embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
203
204         dcc_buffer[0] = OCL_PROBE;
205         retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1);
206         if (retval != ERROR_OK)
207                 return retval;
208
209         /* wait for response, fixed timeout of 1 s */
210         retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000);
211         if (retval != ERROR_OK)
212                 return retval;
213
214         /* receive response */
215         retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
216         if (retval != ERROR_OK)
217                 return retval;
218
219         if (dcc_buffer[0] != OCL_CMD_DONE) {
220                 LOG_ERROR("loader response to OCL_PROBE 0x%08" PRIx32 "", dcc_buffer[0]);
221                 return ERROR_FLASH_OPERATION_FAILED;
222         }
223
224         /* receive and fill in parameters, detection of loader is important, receive it one by one */
225         retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0);
226         if (retval != ERROR_OK)
227                 return retval;
228         retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
229         if (retval != ERROR_OK)
230                 return retval;
231         bank->base = dcc_buffer[0];
232
233         retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0);
234         if (retval != ERROR_OK)
235                 return retval;
236         retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
237         if (retval != ERROR_OK)
238                 return retval;
239         bank->size = dcc_buffer[0];
240
241         retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0);
242         if (retval != ERROR_OK)
243                 return retval;
244         retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
245         if (retval != ERROR_OK)
246                 return retval;
247         bank->num_sectors = dcc_buffer[0];
248
249         retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0);
250         if (retval != ERROR_OK)
251                 return retval;
252         retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
253         if (retval != ERROR_OK)
254                 return retval;
255         ocl->buflen = dcc_buffer[0] & 0xffff;
256         ocl->bufalign = dcc_buffer[0] >> 16;
257
258         bank->sectors = realloc(bank->sectors, sizeof(struct flash_sector)*bank->num_sectors);
259         if (bank->num_sectors == 0) {
260                 LOG_ERROR("number of sectors shall be non zero value");
261                 return ERROR_FLASH_BANK_INVALID;
262         }
263         if (bank->size % bank->num_sectors) {
264                 LOG_ERROR("bank size not divisible by number of sectors");
265                 return ERROR_FLASH_BANK_INVALID;
266         }
267         sectsize = bank->size / bank->num_sectors;
268         for (unsigned int i = 0; i < bank->num_sectors; i++) {
269                 bank->sectors[i].offset = i * sectsize;
270                 bank->sectors[i].size = sectsize;
271                 bank->sectors[i].is_erased = -1;
272                 bank->sectors[i].is_protected = -1;
273         }
274
275         if (ocl->bufalign == 0)
276                 ocl->bufalign = 1;
277
278         if (ocl->buflen == 0) {
279                 LOG_ERROR("buflen shall be non zero value");
280                 return ERROR_FLASH_BANK_INVALID;
281         }
282
283         if ((ocl->bufalign > ocl->buflen) || (ocl->buflen % ocl->bufalign)) {
284                 LOG_ERROR("buflen is not multiple of bufalign");
285                 return ERROR_FLASH_BANK_INVALID;
286         }
287
288         if (ocl->buflen % 4) {
289                 LOG_ERROR("buflen shall be divisible by 4");
290                 return ERROR_FLASH_BANK_INVALID;
291         }
292
293         return ERROR_OK;
294 }
295
296 static int ocl_auto_probe(struct flash_bank *bank)
297 {
298         struct ocl_priv *ocl = bank->driver_priv;
299
300         if (ocl->buflen == 0 || ocl->bufalign == 0)
301                 return ERROR_FLASH_BANK_NOT_PROBED;
302
303         return ERROR_OK;
304 }
305
306 const struct flash_driver ocl_flash = {
307         .name = "ocl",
308         .flash_bank_command = ocl_flash_bank_command,
309         .erase = ocl_erase,
310         .write = ocl_write,
311         .read = default_flash_read,
312         .probe = ocl_probe,
313         .erase_check = default_flash_blank_check,
314         .auto_probe = ocl_auto_probe,
315         .free_driver_priv = default_flash_free_driver_priv,
316 };