The following patches was applied:
[fw/openocd] / src / flash / ocl.c
1 /***************************************************************************
2  *   Copyright (C) 2007 by Pavel Chromy                                    *
3  *   chromy@asix.cz                                                        *
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 "replacements.h"
25
26 #include "ocl.h"
27
28 #include "flash.h"
29 #include "target.h"
30 #include "log.h"
31 #include "binarybuffer.h"
32 #include "types.h"
33 #include "embeddedice.h"
34 #include "arm7_9_common.h"
35
36 #include <stdlib.h>
37 #include <string.h>
38 #include <unistd.h>
39
40 static int ocl_register_commands(struct command_context_s *cmd_ctx);
41 static int ocl_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
42 static int ocl_erase(struct flash_bank_s *bank, int first, int last);
43 static int ocl_protect(struct flash_bank_s *bank, int set, int first, int last);
44 static int ocl_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
45 static int ocl_probe(struct flash_bank_s *bank);
46 static int ocl_erase_check(struct flash_bank_s *bank);
47 static int ocl_protect_check(struct flash_bank_s *bank);
48 static int ocl_info(struct flash_bank_s *bank, char *buf, int buf_size);
49 static int ocl_auto_probe(struct flash_bank_s *bank);
50
51 flash_driver_t ocl_flash =
52 {
53         .name = "ocl",
54         .register_commands = ocl_register_commands,
55         .flash_bank_command = ocl_flash_bank_command,
56         .erase = ocl_erase,
57         .protect = ocl_protect,
58         .write = ocl_write,
59         .probe = ocl_probe,
60         .erase_check = ocl_erase_check,
61         .protect_check = ocl_protect_check,
62         .info = ocl_info,
63         .auto_probe = ocl_auto_probe
64 };
65
66 typedef struct ocl_priv_s
67 {
68         arm_jtag_t *jtag_info;
69         int buflen;
70         int bufalign;
71 } ocl_priv_t;
72
73 static int ocl_register_commands(struct command_context_s *cmd_ctx)
74 {
75         return ERROR_OK;
76 }
77
78 static int ocl_erase_check(struct flash_bank_s *bank)
79 {
80         return ERROR_OK;
81 }
82
83 static int ocl_protect_check(struct flash_bank_s *bank)
84 {
85         return ERROR_OK;
86 }
87
88 /* flash_bank ocl 0 0 0 0 <target#> */
89 static int ocl_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
90 {
91         int retval;
92         armv4_5_common_t *armv4_5;
93         arm7_9_common_t *arm7_9;
94         ocl_priv_t *ocl;
95
96         if (argc < 6)
97         {
98                 LOG_WARNING("incomplete flash_bank ocl configuration");
99                 return ERROR_FLASH_BANK_INVALID;
100         }
101
102         if ((retval = arm7_9_get_arch_pointers(bank->target, &armv4_5, &arm7_9)) != ERROR_OK)
103                 return retval;
104
105         ocl = bank->driver_priv = malloc(sizeof(ocl_priv_t));
106         ocl->jtag_info = &arm7_9->jtag_info;
107         ocl->buflen = 0;
108         ocl->bufalign = 1;
109
110         return ERROR_OK;
111 }
112
113 static int ocl_erase(struct flash_bank_s *bank, int first, int last)
114 {
115         ocl_priv_t *ocl = bank->driver_priv;
116         int retval;
117         u32 dcc_buffer[3];
118
119         /* check preconditions */
120         if (bank->num_sectors == 0)
121                 return ERROR_FLASH_BANK_NOT_PROBED;
122                 
123         if (bank->target->state != TARGET_RUNNING)
124         {
125                 LOG_ERROR("target has to be running to communicate with the loader");
126                 return ERROR_TARGET_NOT_RUNNING;
127         }
128                 
129         if ((first == 0) && (last == bank->num_sectors - 1))
130         {
131                 dcc_buffer[0] = OCL_ERASE_ALL;
132                 if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
133                         return retval;
134         }
135         else
136         {
137                 dcc_buffer[0] = OCL_ERASE_BLOCK;
138                 dcc_buffer[1] = first;
139                 dcc_buffer[2] = last;
140                 if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 3) != ERROR_OK))
141                         return retval;
142         }
143
144         /* wait for response, fixed timeout of 1 s */
145         if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000) != ERROR_OK))
146         {
147                 if (retval == ERROR_TARGET_TIMEOUT)
148                         LOG_ERROR("loader not responding");
149                 return retval;
150         }
151
152         /* receive response */
153         if ((retval = embeddedice_receive(ocl->jtag_info, dcc_buffer+1, 1) != ERROR_OK))
154                 return retval;
155
156         if (dcc_buffer[1] != OCL_CMD_DONE)
157         {
158                 if (dcc_buffer[0] == OCL_ERASE_ALL)
159                         LOG_ERROR("loader response to OCL_ERASE_ALL 0x%08X", dcc_buffer[1]);
160                 else
161                         LOG_ERROR("loader response to OCL_ERASE_BLOCK 0x%08X", dcc_buffer[1]);
162                 return ERROR_FLASH_OPERATION_FAILED;
163         }
164
165         return ERROR_OK;
166 }
167
168 static int ocl_protect(struct flash_bank_s *bank, int set, int first, int last)
169 {
170         return ERROR_OK;
171 }
172
173 static int ocl_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
174 {
175         ocl_priv_t *ocl = bank->driver_priv;
176         int retval;
177         u32 *dcc_buffer;
178         u32 *dcc_bufptr;
179         int byteofs;
180         int runlen;
181         u32 chksum;
182         
183         int i;
184
185         /* check preconditions */
186         if (ocl->buflen == 0 || ocl->bufalign==0)
187                 return ERROR_FLASH_BANK_NOT_PROBED;
188
189         if (bank->target->state != TARGET_RUNNING)
190         {
191                 LOG_ERROR("target has to be running to communicate with the loader");
192                 return ERROR_TARGET_NOT_RUNNING;
193         }
194
195         /* allocate buffer for max. ocl buffer + overhead */
196         dcc_buffer = malloc(sizeof(u32)*(ocl->buflen/4+3));
197
198         while (count)
199         {
200                 if (count + (offset % ocl->bufalign) > ocl->buflen)
201                         runlen = ocl->buflen - (offset % ocl->bufalign);
202                 else
203                         runlen = count;
204
205                 dcc_buffer[0] = OCL_FLASH_BLOCK | runlen;
206                 dcc_buffer[1] = offset;
207                 dcc_bufptr = &dcc_buffer[2];
208
209                 *dcc_bufptr = 0xffffffff;
210                 byteofs = (offset % ocl->bufalign) % 4;
211                 chksum = OCL_CHKS_INIT;
212
213                 /* copy data to DCC buffer in proper byte order and properly aligned */
214                 for (i=0; i<runlen; i++)
215                 {
216                         switch (byteofs++)
217                         {
218                                 case 0:
219                                         *dcc_bufptr &= *(buffer++) | 0xffffff00;
220                                         break;
221                                 case 1:
222                                         *dcc_bufptr &= ((*(buffer++))<<8) | 0xffff00ff;
223                                         break;
224                                 case 2:
225                                         *dcc_bufptr &= ((*(buffer++))<<16) | 0xff00ffff;
226                                         break;
227                                 case 3:
228                                         *dcc_bufptr &= ((*(buffer++))<<24) | 0x00ffffff;
229                                         chksum ^= *(dcc_bufptr++);
230                                         *dcc_bufptr = 0xffffffff;
231                                         byteofs = 0;
232                                         break;
233                         }
234                 }
235
236                 /* add the remaining word to checksum */
237                 if (byteofs)
238                         chksum ^= *(dcc_bufptr++);
239
240                 *(dcc_bufptr++) = chksum;
241                 
242                 /* send the data */
243                 if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, dcc_bufptr-dcc_buffer)) != ERROR_OK)
244                 {
245                         free(dcc_buffer);
246                   return retval;
247                 }
248
249                 /* wait for response, fixed timeout of 1 s */
250                 if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000) != ERROR_OK))
251                 {
252                         if (retval == ERROR_TARGET_TIMEOUT)
253                                 LOG_ERROR("loader not responding");
254                         free(dcc_buffer);
255                         return retval;
256                 }
257
258                 /* receive response */
259                 if ((retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
260                 {
261                         free(dcc_buffer);
262                         return retval;
263                 }
264
265                 if (dcc_buffer[0] != OCL_CMD_DONE)
266                 {
267                         LOG_ERROR("loader response to OCL_FLASH_BLOCK 0x%08X", dcc_buffer[0]);
268                         free(dcc_buffer);
269                         return ERROR_FLASH_OPERATION_FAILED;
270                 }
271
272                 count -= runlen;
273                 offset += runlen;
274         }
275
276         free(dcc_buffer);
277         return ERROR_OK;
278 }
279
280 static int ocl_probe(struct flash_bank_s *bank)
281 {
282         ocl_priv_t *ocl = bank->driver_priv;
283         int retval;
284         u32 dcc_buffer[1];
285         int sectsize;
286         int i;
287
288         /* purge pending data in DCC */
289         embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
290
291         dcc_buffer[0] = OCL_PROBE;
292         if ((retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
293                 return retval;
294
295         /* wait for response, fixed timeout of 1 s */
296         if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 1000) != ERROR_OK))
297         {
298                 if (retval == ERROR_TARGET_TIMEOUT)
299                         LOG_ERROR("loader not responding");
300                 return retval;
301         }
302
303         /* receive response */
304         if ((retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
305                 return retval;
306                 
307         if (dcc_buffer[0] != OCL_CMD_DONE)
308         {
309                 LOG_ERROR("loader response to OCL_PROBE 0x%08X", dcc_buffer[0]);
310                 return ERROR_FLASH_OPERATION_FAILED;
311         }
312
313         /* receive and fill in parameters, detection of loader is important, receive it one by one */
314         if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK)
315                 || (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
316                 return retval;
317         bank->base = dcc_buffer[0];
318
319         if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK)
320                 || (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
321                 return retval;
322         bank->size = dcc_buffer[0];
323
324         if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK)
325                 || (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
326                 return retval;
327         bank->num_sectors = dcc_buffer[0];
328
329         if ((retval = embeddedice_handshake(ocl->jtag_info, EICE_COMM_CTRL_WBIT, 0) != ERROR_OK)
330                 || (retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1) != ERROR_OK))
331                 return retval;
332         ocl->buflen = dcc_buffer[0] & 0xffff;
333         ocl->bufalign = dcc_buffer[0] >> 16;
334
335         bank->sectors = realloc(bank->sectors, sizeof(flash_sector_t)*bank->num_sectors);
336         if (bank->num_sectors == 0)
337         {
338                 LOG_ERROR("number of sectors shall be non zero value");
339                 return ERROR_FLASH_BANK_INVALID;
340         }
341         if (bank->size % bank->num_sectors) {
342                 LOG_ERROR("bank size not divisible by number of sectors");
343                 return ERROR_FLASH_BANK_INVALID;
344         }
345         sectsize = bank->size / bank->num_sectors;
346         for (i=0; i<bank->num_sectors; i++)
347         {
348                 bank->sectors[i].offset = i * sectsize;
349                 bank->sectors[i].size = sectsize;
350                 bank->sectors[i].is_erased = -1;
351                 bank->sectors[i].is_protected = -1;
352         }
353
354         if (ocl->bufalign == 0)
355                 ocl->bufalign = 1;
356
357         if (ocl->buflen == 0)
358         {
359                 LOG_ERROR("buflen shall be non zero value");
360                 return ERROR_FLASH_BANK_INVALID;
361         }
362
363         if ((ocl->bufalign > ocl->buflen) || (ocl->buflen % ocl->bufalign))
364         {
365                 LOG_ERROR("buflen is not multiple of bufalign");
366                 return ERROR_FLASH_BANK_INVALID;
367         }
368
369         if (ocl->buflen % 4)
370         {
371                 LOG_ERROR("buflen shall be divisible by 4");
372                 return ERROR_FLASH_BANK_INVALID;
373         }
374
375         return ERROR_OK;
376 }
377
378 static int ocl_info(struct flash_bank_s *bank, char *buf, int buf_size)
379 {
380         return ERROR_OK;
381 }
382
383 static int ocl_auto_probe(struct flash_bank_s *bank)
384 {
385         ocl_priv_t *ocl = bank->driver_priv;
386
387         if (ocl->buflen == 0 || ocl->bufalign==0)
388                 return ERROR_FLASH_BANK_NOT_PROBED;
389
390         return ERROR_OK;
391 }