jtagspi: new protocol that includes transfer length
[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 };
36
37 FLASH_BANK_COMMAND_HANDLER(jtagspi_flash_bank_command)
38 {
39 struct jtagspi_flash_bank *info;
40
41 if (CMD_ARGC < 7)
42 return ERROR_COMMAND_SYNTAX_ERROR;
43
44 info = malloc(sizeof(struct jtagspi_flash_bank));
45 if (info == NULL) {
46 LOG_ERROR("no memory for flash bank info");
47 return ERROR_FAIL;
48 }
49 bank->driver_priv = info;
50
51 info->tap = NULL;
52 info->probed = 0;
53 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[6], info->ir);
54
55 return ERROR_OK;
56 }
57
58 static void jtagspi_set_ir(struct flash_bank *bank)
59 {
60 struct jtagspi_flash_bank *info = bank->driver_priv;
61 struct scan_field field;
62 uint8_t buf[4];
63
64 LOG_DEBUG("loading jtagspi ir");
65 buf_set_u32(buf, 0, info->tap->ir_length, info->ir);
66 field.num_bits = info->tap->ir_length;
67 field.out_value = buf;
68 field.in_value = NULL;
69 jtag_add_ir_scan(info->tap, &field, TAP_IDLE);
70 }
71
72 static void flip_u8(uint8_t *in, uint8_t *out, int len)
73 {
74 for (int i = 0; i < len; i++)
75 out[i] = flip_u32(in[i], 8);
76 }
77
78 static int jtagspi_cmd(struct flash_bank *bank, uint8_t cmd,
79 uint32_t *addr, uint8_t *data, int len)
80 {
81 struct jtagspi_flash_bank *info = bank->driver_priv;
82 struct scan_field fields[6];
83 uint8_t marker = 1;
84 uint8_t xfer_bits_buf[4];
85 uint8_t addr_buf[3];
86 uint8_t *data_buf;
87 uint32_t xfer_bits;
88 int is_read, lenb, n;
89
90 /* LOG_DEBUG("cmd=0x%02x len=%i", cmd, len); */
91
92 is_read = (len < 0);
93 if (is_read)
94 len = -len;
95
96 n = 0;
97
98 fields[n].num_bits = 1;
99 fields[n].out_value = &marker;
100 fields[n].in_value = NULL;
101 n++;
102
103 xfer_bits = 8 + len - 1;
104 /* cmd + read/write - 1 due to the counter implementation */
105 if (addr)
106 xfer_bits += 24;
107 h_u32_to_be(xfer_bits_buf, xfer_bits);
108 flip_u8(xfer_bits_buf, xfer_bits_buf, 4);
109 fields[n].num_bits = 32;
110 fields[n].out_value = xfer_bits_buf;
111 fields[n].in_value = NULL;
112 n++;
113
114 cmd = flip_u32(cmd, 8);
115 fields[n].num_bits = 8;
116 fields[n].out_value = &cmd;
117 fields[n].in_value = NULL;
118 n++;
119
120 if (addr) {
121 h_u24_to_be(addr_buf, *addr);
122 flip_u8(addr_buf, addr_buf, 3);
123 fields[n].num_bits = 24;
124 fields[n].out_value = addr_buf;
125 fields[n].in_value = NULL;
126 n++;
127 }
128
129 lenb = DIV_ROUND_UP(len, 8);
130 data_buf = malloc(lenb);
131 if (lenb > 0) {
132 if (data_buf == NULL) {
133 LOG_ERROR("no memory for spi buffer");
134 return ERROR_FAIL;
135 }
136 if (is_read) {
137 fields[n].num_bits = jtag_tap_count_enabled();
138 fields[n].out_value = NULL;
139 fields[n].in_value = NULL;
140 n++;
141
142 fields[n].out_value = NULL;
143 fields[n].in_value = data_buf;
144 } else {
145 flip_u8(data, data_buf, lenb);
146 fields[n].out_value = data_buf;
147 fields[n].in_value = NULL;
148 }
149 fields[n].num_bits = len;
150 n++;
151 }
152
153 jtagspi_set_ir(bank);
154 /* passing from an IR scan to SHIFT-DR clears BYPASS registers */
155 jtag_add_dr_scan(info->tap, n, fields, TAP_IDLE);
156 jtag_execute_queue();
157
158 if (is_read)
159 flip_u8(data_buf, data, lenb);
160 free(data_buf);
161 return ERROR_OK;
162 }
163
164 static int jtagspi_probe(struct flash_bank *bank)
165 {
166 struct jtagspi_flash_bank *info = bank->driver_priv;
167 struct flash_sector *sectors;
168 uint8_t in_buf[3];
169 uint32_t id;
170
171 if (info->probed)
172 free(bank->sectors);
173 info->probed = 0;
174
175 if (bank->target->tap == NULL) {
176 LOG_ERROR("Target has no JTAG tap");
177 return ERROR_FAIL;
178 }
179 info->tap = bank->target->tap;
180
181 jtagspi_cmd(bank, SPIFLASH_READ_ID, NULL, in_buf, -24);
182 /* the table in spi.c has the manufacturer byte (first) as the lsb */
183 id = le_to_h_u24(in_buf);
184
185 info->dev = NULL;
186 for (const struct flash_device *p = flash_devices; p->name ; p++)
187 if (p->device_id == id) {
188 info->dev = p;
189 break;
190 }
191
192 if (!(info->dev)) {
193 LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", id);
194 return ERROR_FAIL;
195 }
196
197 LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")",
198 info->dev->name, info->dev->device_id);
199
200 /* Set correct size value */
201 bank->size = info->dev->size_in_bytes;
202
203 /* create and fill sectors array */
204 bank->num_sectors =
205 info->dev->size_in_bytes / info->dev->sectorsize;
206 sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
207 if (sectors == NULL) {
208 LOG_ERROR("not enough memory");
209 return ERROR_FAIL;
210 }
211
212 for (int sector = 0; sector < bank->num_sectors; sector++) {
213 sectors[sector].offset = sector * info->dev->sectorsize;
214 sectors[sector].size = info->dev->sectorsize;
215 sectors[sector].is_erased = -1;
216 sectors[sector].is_protected = 0;
217 }
218
219 bank->sectors = sectors;
220 info->probed = 1;
221 return ERROR_OK;
222 }
223
224 static void jtagspi_read_status(struct flash_bank *bank, uint32_t *status)
225 {
226 uint8_t buf;
227 jtagspi_cmd(bank, SPIFLASH_READ_STATUS, NULL, &buf, -8);
228 *status = buf;
229 /* LOG_DEBUG("status=0x%08" PRIx32, *status); */
230 }
231
232 static int jtagspi_wait(struct flash_bank *bank, int timeout_ms)
233 {
234 uint32_t status;
235 int64_t t0 = timeval_ms();
236 int64_t dt;
237
238 do {
239 dt = timeval_ms() - t0;
240 jtagspi_read_status(bank, &status);
241 if ((status & SPIFLASH_BSY_BIT) == 0) {
242 LOG_DEBUG("waited %" PRId64 " ms", dt);
243 return ERROR_OK;
244 }
245 alive_sleep(1);
246 } while (dt <= timeout_ms);
247
248 LOG_ERROR("timeout, device still busy");
249 return ERROR_FAIL;
250 }
251
252 static int jtagspi_write_enable(struct flash_bank *bank)
253 {
254 uint32_t status;
255
256 jtagspi_cmd(bank, SPIFLASH_WRITE_ENABLE, NULL, NULL, 0);
257 jtagspi_read_status(bank, &status);
258 if ((status & SPIFLASH_WE_BIT) == 0) {
259 LOG_ERROR("Cannot enable write to flash. Status=0x%08" PRIx32, status);
260 return ERROR_FAIL;
261 }
262 return ERROR_OK;
263 }
264
265 static int jtagspi_bulk_erase(struct flash_bank *bank)
266 {
267 struct jtagspi_flash_bank *info = bank->driver_priv;
268 int retval;
269 int64_t t0 = timeval_ms();
270
271 retval = jtagspi_write_enable(bank);
272 if (retval != ERROR_OK)
273 return retval;
274 jtagspi_cmd(bank, info->dev->chip_erase_cmd, NULL, NULL, 0);
275 retval = jtagspi_wait(bank, bank->num_sectors*JTAGSPI_MAX_TIMEOUT);
276 LOG_INFO("took %" PRId64 " ms", timeval_ms() - t0);
277 return retval;
278 }
279
280 static int jtagspi_sector_erase(struct flash_bank *bank, int sector)
281 {
282 struct jtagspi_flash_bank *info = bank->driver_priv;
283 int retval;
284 int64_t t0 = timeval_ms();
285
286 retval = jtagspi_write_enable(bank);
287 if (retval != ERROR_OK)
288 return retval;
289 jtagspi_cmd(bank, info->dev->erase_cmd, &bank->sectors[sector].offset, NULL, 0);
290 retval = jtagspi_wait(bank, JTAGSPI_MAX_TIMEOUT);
291 LOG_INFO("sector %d took %" PRId64 " ms", sector, timeval_ms() - t0);
292 return retval;
293 }
294
295 static int jtagspi_erase(struct flash_bank *bank, int first, int last)
296 {
297 int sector;
298 struct jtagspi_flash_bank *info = bank->driver_priv;
299 int retval = ERROR_OK;
300
301 LOG_DEBUG("erase from sector %d to sector %d", first, last);
302
303 if ((first < 0) || (last < first) || (last >= bank->num_sectors)) {
304 LOG_ERROR("Flash sector invalid");
305 return ERROR_FLASH_SECTOR_INVALID;
306 }
307
308 if (!(info->probed)) {
309 LOG_ERROR("Flash bank not probed");
310 return ERROR_FLASH_BANK_NOT_PROBED;
311 }
312
313 for (sector = first; sector <= last; sector++) {
314 if (bank->sectors[sector].is_protected) {
315 LOG_ERROR("Flash sector %d protected", sector);
316 return ERROR_FAIL;
317 }
318 }
319
320 if (first == 0 && last == (bank->num_sectors - 1)
321 && info->dev->chip_erase_cmd != info->dev->erase_cmd) {
322 LOG_DEBUG("Trying bulk erase.");
323 retval = jtagspi_bulk_erase(bank);
324 if (retval == ERROR_OK)
325 return retval;
326 else
327 LOG_WARNING("Bulk flash erase failed. Falling back to sector erase.");
328 }
329
330 for (sector = first; sector <= last; sector++) {
331 retval = jtagspi_sector_erase(bank, sector);
332 if (retval != ERROR_OK) {
333 LOG_ERROR("Sector erase failed.");
334 break;
335 }
336 }
337
338 return retval;
339 }
340
341 static int jtagspi_protect(struct flash_bank *bank, int set, int first, int last)
342 {
343 int sector;
344
345 if ((first < 0) || (last < first) || (last >= bank->num_sectors)) {
346 LOG_ERROR("Flash sector invalid");
347 return ERROR_FLASH_SECTOR_INVALID;
348 }
349
350 for (sector = first; sector <= last; sector++)
351 bank->sectors[sector].is_protected = set;
352 return ERROR_OK;
353 }
354
355 static int jtagspi_protect_check(struct flash_bank *bank)
356 {
357 return ERROR_OK;
358 }
359
360 static int jtagspi_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
361 {
362 struct jtagspi_flash_bank *info = bank->driver_priv;
363
364 if (!(info->probed)) {
365 LOG_ERROR("Flash bank not yet probed.");
366 return ERROR_FLASH_BANK_NOT_PROBED;
367 }
368
369 jtagspi_cmd(bank, SPIFLASH_READ, &offset, buffer, -count*8);
370 return ERROR_OK;
371 }
372
373 static int jtagspi_page_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
374 {
375 int retval;
376
377 retval = jtagspi_write_enable(bank);
378 if (retval != ERROR_OK)
379 return retval;
380 jtagspi_cmd(bank, SPIFLASH_PAGE_PROGRAM, &offset, (uint8_t *) buffer, count*8);
381 return jtagspi_wait(bank, JTAGSPI_MAX_TIMEOUT);
382 }
383
384 static int jtagspi_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
385 {
386 struct jtagspi_flash_bank *info = bank->driver_priv;
387 int retval;
388 uint32_t n;
389
390 if (!(info->probed)) {
391 LOG_ERROR("Flash bank not yet probed.");
392 return ERROR_FLASH_BANK_NOT_PROBED;
393 }
394
395 for (n = 0; n < count; n += info->dev->pagesize) {
396 retval = jtagspi_page_write(bank, buffer + n, offset + n,
397 MIN(count - n, info->dev->pagesize));
398 if (retval != ERROR_OK) {
399 LOG_ERROR("page write error");
400 return retval;
401 }
402 LOG_DEBUG("wrote page at 0x%08" PRIx32, offset + n);
403 }
404 return ERROR_OK;
405 }
406
407 static int jtagspi_info(struct flash_bank *bank, char *buf, int buf_size)
408 {
409 struct jtagspi_flash_bank *info = bank->driver_priv;
410
411 if (!(info->probed)) {
412 snprintf(buf, buf_size, "\nJTAGSPI flash bank not probed yet\n");
413 return ERROR_OK;
414 }
415
416 snprintf(buf, buf_size, "\nSPIFI flash information:\n"
417 " Device \'%s\' (ID 0x%08" PRIx32 ")\n",
418 info->dev->name, info->dev->device_id);
419
420 return ERROR_OK;
421 }
422
423 struct flash_driver jtagspi_flash = {
424 .name = "jtagspi",
425 .flash_bank_command = jtagspi_flash_bank_command,
426 .erase = jtagspi_erase,
427 .protect = jtagspi_protect,
428 .write = jtagspi_write,
429 .read = jtagspi_read,
430 .probe = jtagspi_probe,
431 .auto_probe = jtagspi_probe,
432 .erase_check = default_flash_blank_check,
433 .protect_check = jtagspi_protect_check,
434 .info = jtagspi_info
435 };

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)