1 /***************************************************************************
2 * Copyright (C) 2015 Robert Jordens <jordens@gmail.com> *
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. *
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. *
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 ***************************************************************************/
23 #include <jtag/jtag.h>
24 #include <flash/nor/spi.h>
25 #include <helper/time_support.h>
27 #define JTAGSPI_MAX_TIMEOUT 3000
30 struct jtagspi_flash_bank
{
32 const struct flash_device
*dev
;
38 FLASH_BANK_COMMAND_HANDLER(jtagspi_flash_bank_command
)
40 struct jtagspi_flash_bank
*info
;
43 return ERROR_COMMAND_SYNTAX_ERROR
;
45 info
= malloc(sizeof(struct jtagspi_flash_bank
));
47 LOG_ERROR("no memory for flash bank info");
50 bank
->driver_priv
= info
;
54 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[6], info
->ir
);
55 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[7], info
->dr_len
);
60 static void jtagspi_set_ir(struct flash_bank
*bank
)
62 struct jtagspi_flash_bank
*info
= bank
->driver_priv
;
63 struct scan_field field
;
66 if (buf_get_u32(info
->tap
->cur_instr
, 0, info
->tap
->ir_length
) == info
->ir
)
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
);
77 static void flip_u8(uint8_t *in
, uint8_t *out
, int len
)
79 for (int i
= 0; i
< len
; i
++)
80 out
[i
] = flip_u32(in
[i
], 8);
83 static int jtagspi_cmd(struct flash_bank
*bank
, uint8_t cmd
,
84 uint32_t *addr
, uint8_t *data
, int len
)
86 struct jtagspi_flash_bank
*info
= bank
->driver_priv
;
87 struct scan_field fields
[3];
92 /* LOG_DEBUG("cmd=0x%02x len=%i", cmd, len); */
95 fields
[n
].num_bits
= 8;
98 h_u24_to_be(cmd_buf
+ 1, *addr
);
99 fields
[n
].num_bits
+= 24;
101 flip_u8(cmd_buf
, cmd_buf
, 4);
102 fields
[n
].out_value
= cmd_buf
;
103 fields
[n
].in_value
= NULL
;
109 lenb
= DIV_ROUND_UP(len
, 8);
110 data_buf
= malloc(lenb
);
112 if (data_buf
== NULL
) {
113 LOG_ERROR("no memory for spi buffer");
117 fields
[n
].num_bits
= info
->dr_len
;
118 fields
[n
].out_value
= NULL
;
119 fields
[n
].in_value
= NULL
;
121 fields
[n
].out_value
= NULL
;
122 fields
[n
].in_value
= data_buf
;
124 flip_u8(data
, data_buf
, lenb
);
125 fields
[n
].out_value
= data_buf
;
126 fields
[n
].in_value
= NULL
;
128 fields
[n
].num_bits
= len
;
132 jtagspi_set_ir(bank
);
133 jtag_add_dr_scan(info
->tap
, n
, fields
, TAP_IDLE
);
134 jtag_execute_queue();
137 flip_u8(data_buf
, data
, lenb
);
142 static int jtagspi_probe(struct flash_bank
*bank
)
144 struct jtagspi_flash_bank
*info
= bank
->driver_priv
;
145 struct flash_sector
*sectors
;
153 if (bank
->target
->tap
== NULL
) {
154 LOG_ERROR("Target has no JTAG tap");
157 info
->tap
= bank
->target
->tap
;
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
);
164 for (const struct flash_device
*p
= flash_devices
; p
->name
; p
++)
165 if (p
->device_id
== id
) {
171 LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32
")", id
);
175 LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32
")",
176 info
->dev
->name
, info
->dev
->device_id
);
178 /* Set correct size value */
179 bank
->size
= info
->dev
->size_in_bytes
;
181 /* create and fill sectors array */
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");
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;
197 bank
->sectors
= sectors
;
202 static void jtagspi_read_status(struct flash_bank
*bank
, uint32_t *status
)
205 jtagspi_cmd(bank
, SPIFLASH_READ_STATUS
, NULL
, &buf
, -8);
207 /* LOG_DEBUG("status=0x%08" PRIx32, *status); */
210 static int jtagspi_wait(struct flash_bank
*bank
, int timeout_ms
)
213 long long t0
= timeval_ms();
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
);
224 } while (dt
<= timeout_ms
);
226 LOG_ERROR("timeout, device still busy");
230 static int jtagspi_write_enable(struct flash_bank
*bank
)
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
);
243 static int jtagspi_bulk_erase(struct flash_bank
*bank
)
245 struct jtagspi_flash_bank
*info
= bank
->driver_priv
;
247 long long t0
= timeval_ms();
249 retval
= jtagspi_write_enable(bank
);
250 if (retval
!= ERROR_OK
)
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
);
258 static int jtagspi_sector_erase(struct flash_bank
*bank
, int sector
)
260 struct jtagspi_flash_bank
*info
= bank
->driver_priv
;
262 long long t0
= timeval_ms();
264 retval
= jtagspi_write_enable(bank
);
265 if (retval
!= ERROR_OK
)
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
);
273 static int jtagspi_erase(struct flash_bank
*bank
, int first
, int last
)
276 struct jtagspi_flash_bank
*info
= bank
->driver_priv
;
277 int retval
= ERROR_OK
;
279 LOG_DEBUG("erase from sector %d to sector %d", first
, last
);
281 if ((first
< 0) || (last
< first
) || (last
>= bank
->num_sectors
)) {
282 LOG_ERROR("Flash sector invalid");
283 return ERROR_FLASH_SECTOR_INVALID
;
286 if (!(info
->probed
)) {
287 LOG_ERROR("Flash bank not probed");
288 return ERROR_FLASH_BANK_NOT_PROBED
;
291 for (sector
= first
; sector
<= last
; sector
++) {
292 if (bank
->sectors
[sector
].is_protected
) {
293 LOG_ERROR("Flash sector %d protected", sector
);
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
)
305 LOG_WARNING("Bulk flash erase failed. Falling back to sector erase.");
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.");
319 static int jtagspi_protect(struct flash_bank
*bank
, int set
, int first
, int last
)
323 if ((first
< 0) || (last
< first
) || (last
>= bank
->num_sectors
)) {
324 LOG_ERROR("Flash sector invalid");
325 return ERROR_FLASH_SECTOR_INVALID
;
328 for (sector
= first
; sector
<= last
; sector
++)
329 bank
->sectors
[sector
].is_protected
= set
;
333 static int jtagspi_protect_check(struct flash_bank
*bank
)
338 static int jtagspi_read(struct flash_bank
*bank
, uint8_t *buffer
, uint32_t offset
, uint32_t count
)
340 struct jtagspi_flash_bank
*info
= bank
->driver_priv
;
342 if (!(info
->probed
)) {
343 LOG_ERROR("Flash bank not yet probed.");
344 return ERROR_FLASH_BANK_NOT_PROBED
;
347 jtagspi_cmd(bank
, SPIFLASH_READ
, &offset
, buffer
, -count
*8);
351 static int jtagspi_page_write(struct flash_bank
*bank
, const uint8_t *buffer
, uint32_t offset
, uint32_t count
)
355 retval
= jtagspi_write_enable(bank
);
356 if (retval
!= ERROR_OK
)
358 jtagspi_cmd(bank
, SPIFLASH_PAGE_PROGRAM
, &offset
, (uint8_t *) buffer
, count
*8);
359 return jtagspi_wait(bank
, JTAGSPI_MAX_TIMEOUT
);
362 static int jtagspi_write(struct flash_bank
*bank
, const uint8_t *buffer
, uint32_t offset
, uint32_t count
)
364 struct jtagspi_flash_bank
*info
= bank
->driver_priv
;
368 if (!(info
->probed
)) {
369 LOG_ERROR("Flash bank not yet probed.");
370 return ERROR_FLASH_BANK_NOT_PROBED
;
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");
380 LOG_DEBUG("wrote page at 0x%08" PRIx32
, offset
+ n
);
385 static int jtagspi_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
387 struct jtagspi_flash_bank
*info
= bank
->driver_priv
;
389 if (!(info
->probed
)) {
390 snprintf(buf
, buf_size
, "\nJTAGSPI flash bank not probed yet\n");
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
);
401 struct flash_driver jtagspi_flash
= {
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
,
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)