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

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)