0ba4dc21ecec24812fa0d75d3afb59094abe0d07
[openocd.git] / src / flash / nor / jtagspi.c
1 /***************************************************************************
2 * Copyright (C) 2015 Robert Jordens <jordens@gmail.com> *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
16 ***************************************************************************/
17
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21
22 #include "imp.h"
23 #include <jtag/jtag.h>
24 #include <flash/nor/spi.h>
25 #include <helper/time_support.h>
26
27 #define JTAGSPI_MAX_TIMEOUT 3000
28
29
30 struct jtagspi_flash_bank {
31 struct jtag_tap *tap;
32 const struct flash_device *dev;
33 int probed;
34 uint32_t ir;
35 uint32_t dr_len;
36 };
37
38 FLASH_BANK_COMMAND_HANDLER(jtagspi_flash_bank_command)
39 {
40 struct jtagspi_flash_bank *info;
41
42 if (CMD_ARGC < 8)
43 return ERROR_COMMAND_SYNTAX_ERROR;
44
45 info = malloc(sizeof(struct jtagspi_flash_bank));
46 if (info == NULL) {
47 LOG_ERROR("no memory for flash bank info");
48 return ERROR_FAIL;
49 }
50 bank->driver_priv = info;
51
52 info->tap = NULL;
53 info->probed = 0;
54 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[6], info->ir);
55 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[7], info->dr_len);
56
57 return ERROR_OK;
58 }
59
60 static void jtagspi_set_ir(struct flash_bank *bank)
61 {
62 struct jtagspi_flash_bank *info = bank->driver_priv;
63 struct scan_field field;
64 uint8_t buf[4];
65
66 if (buf_get_u32(info->tap->cur_instr, 0, info->tap->ir_length) == info->ir)
67 return;
68
69 LOG_DEBUG("loading jtagspi ir");
70 buf_set_u32(buf, 0, info->tap->ir_length, info->ir);
71 field.num_bits = info->tap->ir_length;
72 field.out_value = buf;
73 field.in_value = NULL;
74 jtag_add_ir_scan(info->tap, &field, TAP_IDLE);
75 }
76
77 static void flip_u8(uint8_t *in, uint8_t *out, int len)
78 {
79 for (int i = 0; i < len; i++)
80 out[i] = flip_u32(in[i], 8);
81 }
82
83 static int jtagspi_cmd(struct flash_bank *bank, uint8_t cmd,
84 uint32_t *addr, uint8_t *data, int len)
85 {
86 struct jtagspi_flash_bank *info = bank->driver_priv;
87 struct scan_field fields[3];
88 uint8_t cmd_buf[4];
89 uint8_t *data_buf;
90 int is_read, lenb, n;
91
92 /* LOG_DEBUG("cmd=0x%02x len=%i", cmd, len); */
93
94 n = 0;
95 fields[n].num_bits = 8;
96 cmd_buf[0] = cmd;
97 if (addr) {
98 h_u24_to_be(cmd_buf + 1, *addr);
99 fields[n].num_bits += 24;
100 }
101 flip_u8(cmd_buf, cmd_buf, 4);
102 fields[n].out_value = cmd_buf;
103 fields[n].in_value = NULL;
104 n++;
105
106 is_read = (len < 0);
107 if (is_read)
108 len = -len;
109 lenb = DIV_ROUND_UP(len, 8);
110 data_buf = malloc(lenb);
111 if (lenb > 0) {
112 if (data_buf == NULL) {
113 LOG_ERROR("no memory for spi buffer");
114 return ERROR_FAIL;
115 }
116 if (is_read) {
117 fields[n].num_bits = info->dr_len;
118 fields[n].out_value = NULL;
119 fields[n].in_value = NULL;
120 n++;
121 fields[n].out_value = NULL;
122 fields[n].in_value = data_buf;
123 } else {
124 flip_u8(data, data_buf, lenb);
125 fields[n].out_value = data_buf;
126 fields[n].in_value = NULL;
127 }
128 fields[n].num_bits = len;
129 n++;
130 }
131
132 jtagspi_set_ir(bank);
133 jtag_add_dr_scan(info->tap, n, fields, TAP_IDLE);
134 jtag_execute_queue();
135
136 if (is_read)
137 flip_u8(data_buf, data, lenb);
138 free(data_buf);
139 return ERROR_OK;
140 }
141
142 static int jtagspi_probe(struct flash_bank *bank)
143 {
144 struct jtagspi_flash_bank *info = bank->driver_priv;
145 struct flash_sector *sectors;
146 uint8_t in_buf[3];
147 uint32_t id;
148
149 if (info->probed)
150 free(bank->sectors);
151 info->probed = 0;
152
153 if (bank->target->tap == NULL) {
154 LOG_ERROR("Target has no JTAG tap");
155 return ERROR_FAIL;
156 }
157 info->tap = bank->target->tap;
158
159 jtagspi_cmd(bank, SPIFLASH_READ_ID, NULL, in_buf, -24);
160 /* the table in spi.c has the manufacturer byte (first) as the lsb */
161 id = le_to_h_u24(in_buf);
162
163 info->dev = NULL;
164 for (const struct flash_device *p = flash_devices; p->name ; p++)
165 if (p->device_id == id) {
166 info->dev = p;
167 break;
168 }
169
170 if (!(info->dev)) {
171 LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", id);
172 return ERROR_FAIL;
173 }
174
175 LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")",
176 info->dev->name, info->dev->device_id);
177
178 /* Set correct size value */
179 bank->size = info->dev->size_in_bytes;
180
181 /* create and fill sectors array */
182 bank->num_sectors =
183 info->dev->size_in_bytes / info->dev->sectorsize;
184 sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
185 if (sectors == NULL) {
186 LOG_ERROR("not enough memory");
187 return ERROR_FAIL;
188 }
189
190 for (int sector = 0; sector < bank->num_sectors; sector++) {
191 sectors[sector].offset = sector * info->dev->sectorsize;
192 sectors[sector].size = info->dev->sectorsize;
193 sectors[sector].is_erased = -1;
194 sectors[sector].is_protected = 0;
195 }
196
197 bank->sectors = sectors;
198 info->probed = 1;
199 return ERROR_OK;
200 }
201
202 static void jtagspi_read_status(struct flash_bank *bank, uint32_t *status)
203 {
204 uint8_t buf;
205 jtagspi_cmd(bank, SPIFLASH_READ_STATUS, NULL, &buf, -8);
206 *status = buf;
207 /* LOG_DEBUG("status=0x%08" PRIx32, *status); */
208 }
209
210 static int jtagspi_wait(struct flash_bank *bank, int timeout_ms)
211 {
212 uint32_t status;
213 long long t0 = timeval_ms();
214 long long dt;
215
216 do {
217 dt = timeval_ms() - t0;
218 jtagspi_read_status(bank, &status);
219 if ((status & SPIFLASH_BSY_BIT) == 0) {
220 LOG_DEBUG("waited %lld ms", dt);
221 return ERROR_OK;
222 }
223 alive_sleep(1);
224 } while (dt <= timeout_ms);
225
226 LOG_ERROR("timeout, device still busy");
227 return ERROR_FAIL;
228 }
229
230 static int jtagspi_write_enable(struct flash_bank *bank)
231 {
232 uint32_t status;
233
234 jtagspi_cmd(bank, SPIFLASH_WRITE_ENABLE, NULL, NULL, 0);
235 jtagspi_read_status(bank, &status);
236 if ((status & SPIFLASH_WE_BIT) == 0) {
237 LOG_ERROR("Cannot enable write to flash. Status=0x%08" PRIx32, status);
238 return ERROR_FAIL;
239 }
240 return ERROR_OK;
241 }
242
243 static int jtagspi_bulk_erase(struct flash_bank *bank)
244 {
245 struct jtagspi_flash_bank *info = bank->driver_priv;
246 int retval;
247 long long t0 = timeval_ms();
248
249 retval = jtagspi_write_enable(bank);
250 if (retval != ERROR_OK)
251 return retval;
252 jtagspi_cmd(bank, info->dev->chip_erase_cmd, NULL, NULL, 0);
253 retval = jtagspi_wait(bank, bank->num_sectors*JTAGSPI_MAX_TIMEOUT);
254 LOG_INFO("took %lld ms", timeval_ms() - t0);
255 return retval;
256 }
257
258 static int jtagspi_sector_erase(struct flash_bank *bank, int sector)
259 {
260 struct jtagspi_flash_bank *info = bank->driver_priv;
261 int retval;
262 long long t0 = timeval_ms();
263
264 retval = jtagspi_write_enable(bank);
265 if (retval != ERROR_OK)
266 return retval;
267 jtagspi_cmd(bank, info->dev->erase_cmd, &bank->sectors[sector].offset, NULL, 0);
268 retval = jtagspi_wait(bank, JTAGSPI_MAX_TIMEOUT);
269 LOG_INFO("sector %d took %lld ms", sector, timeval_ms() - t0);
270 return retval;
271 }
272
273 static int jtagspi_erase(struct flash_bank *bank, int first, int last)
274 {
275 int sector;
276 struct jtagspi_flash_bank *info = bank->driver_priv;
277 int retval = ERROR_OK;
278
279 LOG_DEBUG("erase from sector %d to sector %d", first, last);
280
281 if ((first < 0) || (last < first) || (last >= bank->num_sectors)) {
282 LOG_ERROR("Flash sector invalid");
283 return ERROR_FLASH_SECTOR_INVALID;
284 }
285
286 if (!(info->probed)) {
287 LOG_ERROR("Flash bank not probed");
288 return ERROR_FLASH_BANK_NOT_PROBED;
289 }
290
291 for (sector = first; sector <= last; sector++) {
292 if (bank->sectors[sector].is_protected) {
293 LOG_ERROR("Flash sector %d protected", sector);
294 return ERROR_FAIL;
295 }
296 }
297
298 if (first == 0 && last == (bank->num_sectors - 1)
299 && info->dev->chip_erase_cmd != info->dev->erase_cmd) {
300 LOG_DEBUG("Trying bulk erase.");
301 retval = jtagspi_bulk_erase(bank);
302 if (retval == ERROR_OK)
303 return retval;
304 else
305 LOG_WARNING("Bulk flash erase failed. Falling back to sector erase.");
306 }
307
308 for (sector = first; sector <= last; sector++) {
309 retval = jtagspi_sector_erase(bank, sector);
310 if (retval != ERROR_OK) {
311 LOG_ERROR("Sector erase failed.");
312 break;
313 }
314 }
315
316 return retval;
317 }
318
319 static int jtagspi_protect(struct flash_bank *bank, int set, int first, int last)
320 {
321 int sector;
322
323 if ((first < 0) || (last < first) || (last >= bank->num_sectors)) {
324 LOG_ERROR("Flash sector invalid");
325 return ERROR_FLASH_SECTOR_INVALID;
326 }
327
328 for (sector = first; sector <= last; sector++)
329 bank->sectors[sector].is_protected = set;
330 return ERROR_OK;
331 }
332
333 static int jtagspi_protect_check(struct flash_bank *bank)
334 {
335 return ERROR_OK;
336 }
337
338 static int jtagspi_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
339 {
340 struct jtagspi_flash_bank *info = bank->driver_priv;
341
342 if (!(info->probed)) {
343 LOG_ERROR("Flash bank not yet probed.");
344 return ERROR_FLASH_BANK_NOT_PROBED;
345 }
346
347 jtagspi_cmd(bank, SPIFLASH_READ, &offset, buffer, -count*8);
348 return ERROR_OK;
349 }
350
351 static int jtagspi_page_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
352 {
353 int retval;
354
355 retval = jtagspi_write_enable(bank);
356 if (retval != ERROR_OK)
357 return retval;
358 jtagspi_cmd(bank, SPIFLASH_PAGE_PROGRAM, &offset, (uint8_t *) buffer, count*8);
359 return jtagspi_wait(bank, JTAGSPI_MAX_TIMEOUT);
360 }
361
362 static int jtagspi_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
363 {
364 struct jtagspi_flash_bank *info = bank->driver_priv;
365 int retval;
366 uint32_t n;
367
368 if (!(info->probed)) {
369 LOG_ERROR("Flash bank not yet probed.");
370 return ERROR_FLASH_BANK_NOT_PROBED;
371 }
372
373 for (n = 0; n < count; n += info->dev->pagesize) {
374 retval = jtagspi_page_write(bank, buffer + n, offset + n,
375 MIN(count - n, info->dev->pagesize));
376 if (retval != ERROR_OK) {
377 LOG_ERROR("page write error");
378 return retval;
379 }
380 LOG_DEBUG("wrote page at 0x%08" PRIx32, offset + n);
381 }
382 return ERROR_OK;
383 }
384
385 static int jtagspi_info(struct flash_bank *bank, char *buf, int buf_size)
386 {
387 struct jtagspi_flash_bank *info = bank->driver_priv;
388
389 if (!(info->probed)) {
390 snprintf(buf, buf_size, "\nJTAGSPI flash bank not probed yet\n");
391 return ERROR_OK;
392 }
393
394 snprintf(buf, buf_size, "\nSPIFI flash information:\n"
395 " Device \'%s\' (ID 0x%08" PRIx32 ")\n",
396 info->dev->name, info->dev->device_id);
397
398 return ERROR_OK;
399 }
400
401 struct flash_driver jtagspi_flash = {
402 .name = "jtagspi",
403 .flash_bank_command = jtagspi_flash_bank_command,
404 .erase = jtagspi_erase,
405 .protect = jtagspi_protect,
406 .write = jtagspi_write,
407 .read = jtagspi_read,
408 .probe = jtagspi_probe,
409 .auto_probe = jtagspi_probe,
410 .erase_check = default_flash_blank_check,
411 .protect_check = jtagspi_protect_check,
412 .info = jtagspi_info
413 };

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)