target/cortex_m: add DSCSR_CDSKEY bit definition
[openocd.git] / src / flash / nor / ocl.c
blobe00c365edd30834ad67e0340fe532b291f7d4cbd
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2007 by Pavel Chromy *
5 * chromy@asix.cz *
6 ***************************************************************************/
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
12 #include "imp.h"
13 #include "ocl.h"
14 #include <target/embeddedice.h>
16 struct ocl_priv {
17 struct arm_jtag *jtag_info;
18 unsigned int buflen;
19 unsigned int bufalign;
22 /* flash_bank ocl 0 0 0 0 <target#> */
23 FLASH_BANK_COMMAND_HANDLER(ocl_flash_bank_command)
25 struct arm7_9_common *arm7_9;
26 struct ocl_priv *ocl;
28 if (CMD_ARGC < 6)
29 return ERROR_COMMAND_SYNTAX_ERROR;
31 arm7_9 = target_to_arm7_9(bank->target);
32 if (!is_arm7_9(arm7_9))
33 return ERROR_TARGET_INVALID;
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;
40 return ERROR_OK;
43 static int ocl_erase(struct flash_bank *bank, unsigned int first,
44 unsigned int last)
46 struct ocl_priv *ocl = bank->driver_priv;
47 int retval;
48 uint32_t dcc_buffer[3];
50 /* check preconditions */
51 if (bank->num_sectors == 0)
52 return ERROR_FLASH_BANK_NOT_PROBED;
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;
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;
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;
78 /* receive response */
79 retval = embeddedice_receive(ocl->jtag_info, dcc_buffer + 1, 1);
80 if (retval != ERROR_OK)
81 return retval;
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;
91 return ERROR_OK;
94 static int ocl_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
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;
104 int i;
106 /* check preconditions */
107 if (ocl->buflen == 0 || ocl->bufalign == 0)
108 return ERROR_FLASH_BANK_NOT_PROBED;
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;
115 /* allocate buffer for max. ocl buffer + overhead */
116 dcc_buffer = malloc(sizeof(uint32_t)*(ocl->buflen/4 + 3));
118 while (count) {
119 if (count + (offset % ocl->bufalign) > ocl->buflen)
120 runlen = ocl->buflen - (offset % ocl->bufalign);
121 else
122 runlen = count;
124 dcc_buffer[0] = OCL_FLASH_BLOCK | runlen;
125 dcc_buffer[1] = offset;
126 dcc_bufptr = &dcc_buffer[2];
128 *dcc_bufptr = 0xffffffff;
129 byteofs = (offset % ocl->bufalign) % 4;
130 chksum = OCL_CHKS_INIT;
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;
153 /* add the remaining word to checksum */
154 if (byteofs)
155 chksum ^= *(dcc_bufptr++);
157 *(dcc_bufptr++) = chksum;
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;
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;
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;
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;
186 count -= runlen;
187 offset += runlen;
190 free(dcc_buffer);
191 return ERROR_OK;
194 static int ocl_probe(struct flash_bank *bank)
196 struct ocl_priv *ocl = bank->driver_priv;
197 int retval;
198 uint32_t dcc_buffer[1];
199 int sectsize;
201 /* purge pending data in DCC */
202 embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
204 dcc_buffer[0] = OCL_PROBE;
205 retval = embeddedice_send(ocl->jtag_info, dcc_buffer, 1);
206 if (retval != ERROR_OK)
207 return retval;
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;
214 /* receive response */
215 retval = embeddedice_receive(ocl->jtag_info, dcc_buffer, 1);
216 if (retval != ERROR_OK)
217 return retval;
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;
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];
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];
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];
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;
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;
263 if (bank->size % bank->num_sectors) {
264 LOG_ERROR("bank size not divisible by number of sectors");
265 return ERROR_FLASH_BANK_INVALID;
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;
275 if (ocl->bufalign == 0)
276 ocl->bufalign = 1;
278 if (ocl->buflen == 0) {
279 LOG_ERROR("buflen shall be non zero value");
280 return ERROR_FLASH_BANK_INVALID;
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;
288 if (ocl->buflen % 4) {
289 LOG_ERROR("buflen shall be divisible by 4");
290 return ERROR_FLASH_BANK_INVALID;
293 return ERROR_OK;
296 static int ocl_auto_probe(struct flash_bank *bank)
298 struct ocl_priv *ocl = bank->driver_priv;
300 if (ocl->buflen == 0 || ocl->bufalign == 0)
301 return ERROR_FLASH_BANK_NOT_PROBED;
303 return ERROR_OK;
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,