NOR/SPEAr: Add support for Serial NOR
[openocd.git] / src / flash / nor / spearsmi.c
1 /***************************************************************************
2 * Copyright (C) 2010 by Antonio Borneo <borneo.antonio@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, write to the *
16 * Free Software Foundation, Inc., *
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
18 ***************************************************************************/
19
20 /* ATTENTION:
21 * To have flash memory mapped in CPU memory space, the SMI controller
22 * have to be in "HW mode". This requires following constraints:
23 * 1) The command "reset init" have to initialize SMI controller and put
24 * it in HW mode;
25 * 2) every command in this file have to return to prompt in HW mode. */
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include "imp.h"
32 #include "spearsmi.h"
33 #include <jtag/jtag.h>
34 #include <helper/time_support.h>
35
36 #define JTAG_ID_3XX_6XX (0x07926041)
37
38 #define SMI_READ_REG(a) (_SMI_READ_REG(a))
39 #define _SMI_READ_REG(a) \
40 { \
41 int __a; \
42 uint32_t __v; \
43 \
44 __a = target_read_u32(target, io_base + (a), &__v); \
45 if (__a != ERROR_OK) \
46 return __a; \
47 __v; \
48 }
49
50 #define SMI_WRITE_REG(a,v) \
51 { \
52 int __r; \
53 \
54 __r = target_write_u32(target, io_base + (a), (v)); \
55 if (__r != ERROR_OK) \
56 return __r; \
57 }
58
59 #define SMI_POLL_TFF(timeout) \
60 { \
61 int __r; \
62 \
63 __r = poll_tff(target, io_base, timeout); \
64 if (__r != ERROR_OK) \
65 return __r; \
66 }
67
68 #define SMI_SET_SW_MODE() SMI_WRITE_REG(SMI_CR1, \
69 SMI_READ_REG(SMI_CR1) | SMI_SW_MODE)
70 #define SMI_SET_HWWB_MODE() SMI_WRITE_REG(SMI_CR1, \
71 (SMI_READ_REG(SMI_CR1) | SMI_WB_MODE) & ~SMI_SW_MODE)
72 #define SMI_SET_HW_MODE() SMI_WRITE_REG(SMI_CR1, \
73 SMI_READ_REG(SMI_CR1) & ~(SMI_SW_MODE | SMI_WB_MODE))
74 #define SMI_CLEAR_TFF() SMI_WRITE_REG(SMI_SR, ~SMI_TFF)
75
76 #define SMI_BANK_SIZE (0x01000000)
77
78 #define SMI_BASE_3XX_6XX (0xf8000000)
79 #define SMI_CFGREG_3XX_6XX (0xfc000000)
80
81 /* #define SMI_BASE_13XX (0xe6000000) */
82 /* #define SMI_CFGREG_13XX (0xea000000) */
83
84 #define SMI_CR1 (0x00) /* Control register 1 */
85 #define SMI_CR2 (0x04) /* Control register 2 */
86 #define SMI_SR (0x08) /* Status register */
87 #define SMI_TR (0x0c) /* TX */
88 #define SMI_RR (0x10) /* RX */
89
90 /* fields in SMI_CR1 */
91 #define SMI_SW_MODE 0x10000000 /* set to enable SW Mode */
92 #define SMI_WB_MODE 0x20000000 /* Write Burst Mode */
93
94 /* fields in SMI_CR2 */
95 #define SMI_TX_LEN_1 0x00000001 /* data length = 1 byte */
96 #define SMI_TX_LEN_4 0x00000004 /* data length = 4 byte */
97 #define SMI_RX_LEN_3 0x00000030 /* data length = 3 byte */
98 #define SMI_SEND 0x00000080 /* Send data */
99 #define SMI_RSR 0x00000400 /* reads status reg */
100 #define SMI_WE 0x00000800 /* Write Enable */
101 #define SMI_SEL_BANK0 0x00000000 /* Select Bank0 */
102 #define SMI_SEL_BANK1 0x00001000 /* Select Bank1 */
103 #define SMI_SEL_BANK2 0x00002000 /* Select Bank2 */
104 #define SMI_SEL_BANK3 0x00003000 /* Select Bank3 */
105
106 /* fields in SMI_SR */
107 #define SMI_WIP_BIT 0x00000001 /* WIP Bit of SPI SR on SMI SR */
108 #define SMI_WEL_BIT 0x00000002 /* WEL Bit of SPI SR on SMI SR */
109 #define SMI_TFF 0x00000100 /* Transfer Finished Flag */
110
111 /* Commands */
112 #define SMI_READ_ID 0x0000009F /* Read Flash Identification */
113
114 /* Timeout in ms */
115 #define SMI_CMD_TIMEOUT (100)
116 #define SMI_PROBE_TIMEOUT (100)
117 #define SMI_MAX_TIMEOUT (3000)
118
119 /* data structure to maintain flash ids from different vendors */
120 struct flash_device {
121 char *name;
122 uint8_t erase_cmd;
123 uint32_t device_id;
124 uint32_t pagesize;
125 unsigned long sectorsize;
126 unsigned long size_in_bytes;
127 };
128
129 #define FLASH_ID(n, es, id, psize, ssize, size) \
130 { \
131 .name = n, \
132 .erase_cmd = es, \
133 .device_id = id, \
134 .pagesize = psize, \
135 .sectorsize = ssize, \
136 .size_in_bytes = size \
137 }
138
139 static struct flash_device flash_devices[] = {
140 /* name, erase_cmd, device_id, pagesize, sectorsize, size_in_bytes */
141 FLASH_ID("st m25p05", 0xd8, 0x00102020, 0x80, 0x8000, 0x10000),
142 FLASH_ID("st m25p10", 0xd8, 0x00112020, 0x80, 0x8000, 0x20000),
143 FLASH_ID("st m25p20", 0xd8, 0x00122020, 0x100, 0x10000, 0x40000),
144 FLASH_ID("st m25p40", 0xd8, 0x00132020, 0x100, 0x10000, 0x80000),
145 FLASH_ID("st m25p80", 0xd8, 0x00142020, 0x100, 0x10000, 0x100000),
146 FLASH_ID("st m25p16", 0xd8, 0x00152020, 0x100, 0x10000, 0x200000),
147 FLASH_ID("st m25p32", 0xd8, 0x00162020, 0x100, 0x10000, 0x400000),
148 FLASH_ID("st m25p64", 0xd8, 0x00172020, 0x100, 0x10000, 0x800000),
149 FLASH_ID("st m25p128", 0xd8, 0x00182020, 0x100, 0x40000, 0x1000000),
150 FLASH_ID("st m45pe10", 0xd8, 0x00114020, 0x100, 0x10000, 0x20000),
151 FLASH_ID("st m45pe20", 0xd8, 0x00124020, 0x100, 0x10000, 0x40000),
152 FLASH_ID("st m45pe40", 0xd8, 0x00134020, 0x100, 0x10000, 0x80000),
153 FLASH_ID("st m45pe80", 0xd8, 0x00144020, 0x100, 0x10000, 0x100000),
154 FLASH_ID("sp s25fl004", 0xd8, 0x00120201, 0x100, 0x10000, 0x80000),
155 FLASH_ID("sp s25fl008", 0xd8, 0x00130201, 0x100, 0x10000, 0x100000),
156 FLASH_ID("sp s25fl016", 0xd8, 0x00140201, 0x100, 0x10000, 0x200000),
157 FLASH_ID("sp s25fl032", 0xd8, 0x00150201, 0x100, 0x10000, 0x400000),
158 FLASH_ID("sp s25fl064", 0xd8, 0x00160201, 0x100, 0x10000, 0x800000),
159 FLASH_ID("atmel 25f512", 0x52, 0x0065001f, 0x80, 0x8000, 0x10000),
160 FLASH_ID("atmel 25f1024", 0x52, 0x0060001f, 0x100, 0x8000, 0x20000),
161 FLASH_ID("atmel 25f2048", 0x52, 0x0063001f, 0x100, 0x10000, 0x40000),
162 FLASH_ID("atmel 25f4096", 0x52, 0x0064001f, 0x100, 0x10000, 0x80000),
163 FLASH_ID("atmel 25fs040", 0xd7, 0x0004661f, 0x100, 0x10000, 0x80000),
164 FLASH_ID("mac 25l512", 0xd8, 0x001020c2, 0x010, 0x10000, 0x10000),
165 FLASH_ID("mac 25l1005", 0xd8, 0x001120c2, 0x010, 0x10000, 0x20000),
166 FLASH_ID("mac 25l2005", 0xd8, 0x001220c2, 0x010, 0x10000, 0x40000),
167 FLASH_ID("mac 25l4005", 0xd8, 0x001320c2, 0x010, 0x10000, 0x80000),
168 FLASH_ID("mac 25l8005", 0xd8, 0x001420c2, 0x010, 0x10000, 0x100000),
169 FLASH_ID("mac 25l1605", 0xd8, 0x001520c2, 0x100, 0x10000, 0x200000),
170 FLASH_ID("mac 25l3205", 0xd8, 0x001620c2, 0x100, 0x10000, 0x400000),
171 FLASH_ID("mac 25l6405", 0xd8, 0x001720c2, 0x100, 0x10000, 0x800000),
172 FLASH_ID(NULL, 0, 0, 0, 0, 0)
173 };
174
175 FLASH_BANK_COMMAND_HANDLER(spearsmi_flash_bank_command)
176 {
177 struct spearsmi_flash_bank *spearsmi_info;
178
179 LOG_DEBUG(__FUNCTION__);
180
181 if (CMD_ARGC < 6)
182 {
183 LOG_WARNING("incomplete flash_bank spearsmi configuration");
184 return ERROR_FLASH_BANK_INVALID;
185 }
186
187 spearsmi_info = malloc(sizeof(struct spearsmi_flash_bank));
188 if (spearsmi_info == NULL)
189 {
190 LOG_ERROR("not enough memory");
191 return ERROR_FAIL;
192 }
193
194 bank->driver_priv = spearsmi_info;
195 spearsmi_info->probed = 0;
196
197 return ERROR_OK;
198 }
199
200 /* Poll transmit finished flag */
201 /* timeout in ms */
202 static int poll_tff(struct target *target, uint32_t io_base, int timeout)
203 {
204 long long endtime;
205
206 if (SMI_READ_REG(SMI_SR) & SMI_TFF)
207 return ERROR_OK;
208
209 endtime = timeval_ms() + timeout;
210 do {
211 alive_sleep(1);
212 if (SMI_READ_REG(SMI_SR) & SMI_TFF)
213 return ERROR_OK;
214 } while (timeval_ms() < endtime);
215
216 LOG_ERROR("Timeout while polling TFF");
217 return ERROR_FLASH_OPERATION_FAILED;
218 }
219
220 static int read_status_reg(struct flash_bank *bank, uint32_t *status)
221 {
222 struct target *target = bank->target;
223 struct spearsmi_flash_bank *spearsmi_info = bank->driver_priv;
224 uint32_t io_base = spearsmi_info->io_base;
225
226 /* clear transmit finished flag */
227 SMI_CLEAR_TFF();
228
229 /* Read status */
230 SMI_WRITE_REG(SMI_CR2, spearsmi_info->bank_num | SMI_RSR);
231
232 /* Poll transmit finished flag */
233 SMI_POLL_TFF(SMI_CMD_TIMEOUT);
234
235 /* clear transmit finished flag */
236 SMI_CLEAR_TFF();
237
238 /* Check write enabled */
239 *status = SMI_READ_REG(SMI_SR) & 0x0000ffff;
240
241 /* clean-up SMI_CR2 */
242 SMI_WRITE_REG(SMI_CR2, 0); /* AB: Required ? */
243
244 return ERROR_OK;
245 }
246
247 /* check for WIP (write in progress) bit in status register */
248 /* timeout in ms */
249 static int wait_till_ready(struct flash_bank *bank, int timeout)
250 {
251 uint32_t status;
252 int retval;
253 long long endtime;
254
255 endtime = timeval_ms() + timeout;
256 do {
257 /* read flash status register */
258 retval = read_status_reg(bank, &status);
259 if (retval != ERROR_OK)
260 return retval;
261
262 if ((status & SMI_WIP_BIT) == 0)
263 return ERROR_OK;
264 alive_sleep(1);
265 } while (timeval_ms() < endtime);
266
267 LOG_ERROR("timeout");
268 return ERROR_FAIL;
269 }
270
271 static int smi_write_enable(struct flash_bank *bank)
272 {
273 struct target *target = bank->target;
274 struct spearsmi_flash_bank *spearsmi_info = bank->driver_priv;
275 uint32_t io_base = spearsmi_info->io_base;
276 uint32_t status;
277 int retval;
278
279 /* Enter in HW mode */
280 SMI_SET_HW_MODE(); /* AB: is this correct ?*/
281
282 /* clear transmit finished flag */
283 SMI_CLEAR_TFF();
284
285 /* Send write enable command */
286 SMI_WRITE_REG(SMI_CR2, spearsmi_info->bank_num | SMI_WE);
287
288 /* Poll transmit finished flag */
289 SMI_POLL_TFF(SMI_CMD_TIMEOUT);
290
291 /* read flash status register */
292 retval = read_status_reg(bank, &status);
293 if (retval != ERROR_OK)
294 return retval;
295
296 /* Check write enabled */
297 if ((status & SMI_WEL_BIT) == 0)
298 {
299 LOG_ERROR("Cannot enable write to flash. Status=0x%08" PRIx32, status);
300 return ERROR_FAIL;
301 }
302
303 return ERROR_OK;
304 }
305
306 static uint32_t erase_command(struct spearsmi_flash_bank *spearsmi_info,
307 uint32_t offset)
308 {
309 union {
310 uint32_t command;
311 uint8_t x[4];
312 } cmd;
313
314 cmd.x[0] = spearsmi_info->dev->erase_cmd;
315 cmd.x[1] = offset >> 16;
316 cmd.x[2] = offset >> 8;
317 cmd.x[3] = offset;
318
319 return cmd.command;
320 }
321
322 static int smi_erase_sector(struct flash_bank *bank, int sector)
323 {
324 struct target *target = bank->target;
325 struct spearsmi_flash_bank *spearsmi_info = bank->driver_priv;
326 uint32_t io_base = spearsmi_info->io_base;
327 uint32_t cmd;
328 int retval;
329
330 retval = smi_write_enable(bank);
331 if (retval != ERROR_OK)
332 return retval;
333
334 /* Switch to SW mode to send sector erase command */
335 SMI_SET_SW_MODE();
336
337 /* clear transmit finished flag */
338 SMI_CLEAR_TFF();
339
340 /* send erase command */
341 cmd = erase_command(spearsmi_info, bank->sectors[sector].offset);
342 SMI_WRITE_REG(SMI_TR, cmd);
343 SMI_WRITE_REG(SMI_CR2, spearsmi_info->bank_num | SMI_SEND | SMI_TX_LEN_4);
344
345 /* Poll transmit finished flag */
346 SMI_POLL_TFF(SMI_CMD_TIMEOUT);
347
348 /* poll WIP for end of self timed Sector Erase cycle */
349 retval = wait_till_ready(bank, SMI_MAX_TIMEOUT);
350 if (retval != ERROR_OK)
351 return retval;
352
353 return ERROR_OK;
354 }
355
356 static int spearsmi_erase(struct flash_bank *bank, int first, int last)
357 {
358 struct target *target = bank->target;
359 struct spearsmi_flash_bank *spearsmi_info = bank->driver_priv;
360 uint32_t io_base = spearsmi_info->io_base;
361 int retval = ERROR_OK;
362 int sector;
363
364 LOG_DEBUG("%s: from sector %d to sector %d", __FUNCTION__, first, last);
365
366 if (target->state != TARGET_HALTED)
367 {
368 LOG_ERROR("Target not halted");
369 return ERROR_TARGET_NOT_HALTED;
370 }
371
372 if ((first < 0) || (last < first) || (last >= bank->num_sectors))
373 {
374 LOG_ERROR("Flash sector invalid");
375 return ERROR_FLASH_SECTOR_INVALID;
376 }
377
378 if (!(spearsmi_info->probed))
379 {
380 LOG_ERROR("Flash bank not probed");
381 return ERROR_FLASH_BANK_NOT_PROBED;
382 }
383
384 for (sector = first; sector <= last; sector++)
385 {
386 if (bank->sectors[sector].is_protected)
387 {
388 LOG_ERROR("Flash sector %d protected", sector);
389 return ERROR_FAIL;
390 }
391 }
392
393 for (sector = first; sector <= last; sector++)
394 {
395 retval = smi_erase_sector(bank, sector);
396 if (retval != ERROR_OK)
397 break;
398 keep_alive();
399 }
400
401 /* Switch to HW mode before return to prompt */
402 SMI_SET_HW_MODE();
403 return retval;
404 }
405
406 static int spearsmi_protect(struct flash_bank *bank, int set,
407 int first, int last)
408 {
409 int sector;
410
411 for (sector = first; sector <= last; sector++)
412 bank->sectors[sector].is_protected = set;
413 return ERROR_OK;
414 }
415
416 static int smi_write_buffer(struct flash_bank *bank, uint8_t *buffer,
417 uint32_t address, uint32_t len)
418 {
419 struct target *target = bank->target;
420 struct spearsmi_flash_bank *spearsmi_info = bank->driver_priv;
421 uint32_t io_base = spearsmi_info->io_base;
422 int retval;
423
424 LOG_DEBUG("%s: address=0x%08" PRIx32 " len=0x%08" PRIx32,
425 __FUNCTION__, address, len);
426
427 retval = smi_write_enable(bank);
428 if (retval != ERROR_OK)
429 return retval;
430
431 /* HW mode, write burst mode */
432 SMI_SET_HWWB_MODE();
433
434 retval = target_write_buffer(target, address, len, buffer);
435 if (retval != ERROR_OK)
436 return retval;
437
438 return ERROR_OK;
439 }
440
441 static int spearsmi_write(struct flash_bank *bank, uint8_t *buffer,
442 uint32_t offset, uint32_t count)
443 {
444 struct target *target = bank->target;
445 struct spearsmi_flash_bank *spearsmi_info = bank->driver_priv;
446 uint32_t io_base = spearsmi_info->io_base;
447 uint32_t cur_count, page_size, page_offset;
448 int sector;
449 int retval = ERROR_OK;
450
451 LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32,
452 __FUNCTION__, offset, count);
453
454 if (target->state != TARGET_HALTED)
455 {
456 LOG_ERROR("Target not halted");
457 return ERROR_TARGET_NOT_HALTED;
458 }
459
460 if (offset + count > spearsmi_info->dev->size_in_bytes)
461 {
462 LOG_WARNING("Write pasts end of flash. Extra data discarded.");
463 count = spearsmi_info->dev->size_in_bytes - offset;
464 }
465
466 /* Check sector protection */
467 for (sector = 0; sector < bank->num_sectors; sector++)
468 {
469 /* Start offset in or before this sector? */
470 /* End offset in or behind this sector? */
471 if ( (offset <
472 (bank->sectors[sector].offset + bank->sectors[sector].size))
473 && ((offset + count - 1) >= bank->sectors[sector].offset)
474 && bank->sectors[sector].is_protected )
475 {
476 LOG_ERROR("Flash sector %d protected", sector);
477 return ERROR_FAIL;
478 }
479 }
480
481 page_size = spearsmi_info->dev->pagesize;
482
483 /* unaligned buffer head */
484 if (count > 0 && (offset & 3) != 0)
485 {
486 cur_count = 4 - (offset & 3);
487 if (cur_count > count)
488 cur_count = count;
489 retval = smi_write_buffer(bank, buffer, bank->base + offset,
490 cur_count);
491 if (retval != ERROR_OK)
492 goto err;
493 offset += cur_count;
494 buffer += cur_count;
495 count -= cur_count;
496 }
497
498 page_offset = offset % page_size;
499 /* central part, aligned words */
500 while (count >= 4)
501 {
502 /* clip block at page boundary */
503 if (page_offset + count > page_size)
504 cur_count = page_size - page_offset;
505 else
506 cur_count = count & ~3;
507
508 retval = smi_write_buffer(bank, buffer, bank->base + offset,
509 cur_count);
510 if (retval != ERROR_OK)
511 goto err;
512
513 page_offset = 0;
514 buffer += cur_count;
515 offset += cur_count;
516 count -= cur_count;
517
518 keep_alive();
519 }
520
521 /* buffer tail */
522 if (count > 0)
523 retval = smi_write_buffer(bank, buffer, bank->base + offset, count);
524
525 err:
526 /* Switch to HW mode before return to prompt */
527 SMI_SET_HW_MODE();
528 return retval;
529 }
530
531 /* Return ID of flash device */
532 /* On exit, SW mode is kept */
533 static int read_flash_id(struct flash_bank *bank, uint32_t *id)
534 {
535 struct target *target = bank->target;
536 struct spearsmi_flash_bank *spearsmi_info = bank->driver_priv;
537 uint32_t io_base = spearsmi_info->io_base;
538 int retval;
539
540 if (target->state != TARGET_HALTED)
541 {
542 LOG_ERROR("Target not halted");
543 return ERROR_TARGET_NOT_HALTED;
544 }
545
546 /* poll WIP */
547 retval = wait_till_ready(bank, SMI_PROBE_TIMEOUT);
548 if (retval != ERROR_OK)
549 return retval;
550
551 /* enter in SW mode */
552 SMI_SET_SW_MODE();
553
554 /* clear transmit finished flag */
555 SMI_CLEAR_TFF();
556
557 /* Require read flash ID */
558 SMI_WRITE_REG(SMI_TR, SMI_READ_ID);
559 SMI_WRITE_REG(SMI_CR2,
560 spearsmi_info->bank_num | SMI_SEND | SMI_RX_LEN_3 | SMI_TX_LEN_1);
561
562 /* Poll transmit finished flag */
563 SMI_POLL_TFF(SMI_CMD_TIMEOUT);
564
565 /* clear transmit finished flag */
566 SMI_CLEAR_TFF();
567
568 /* read ID */
569 *id = SMI_READ_REG(SMI_RR) & 0x00ffffff;
570 return ERROR_OK;
571 }
572
573 static int spearsmi_probe(struct flash_bank *bank)
574 {
575 struct target *target = bank->target;
576 struct spearsmi_flash_bank *spearsmi_info = bank->driver_priv;
577 uint32_t io_base;
578 struct flash_sector *sectors;
579 uint32_t id = 0; /* silence uninitialized warning */
580 int retval;
581
582 if (spearsmi_info->probed)
583 free(bank->sectors);
584 spearsmi_info->probed = 0;
585
586 /* check for SPEAr device */
587 switch (target->tap->idcode)
588 {
589 case JTAG_ID_3XX_6XX:
590 /* SPEAr3xx/6xx */
591 spearsmi_info->io_base = SMI_CFGREG_3XX_6XX;
592 switch (bank->base)
593 {
594 case SMI_BASE_3XX_6XX:
595 spearsmi_info->bank_num = SMI_SEL_BANK0;
596 break;
597 case SMI_BASE_3XX_6XX + SMI_BANK_SIZE:
598 spearsmi_info->bank_num = SMI_SEL_BANK1;
599 break;
600 case SMI_BASE_3XX_6XX + 2*SMI_BANK_SIZE:
601 spearsmi_info->bank_num = SMI_SEL_BANK2;
602 break;
603 case SMI_BASE_3XX_6XX + 3*SMI_BANK_SIZE:
604 spearsmi_info->bank_num = SMI_SEL_BANK3;
605 break;
606 default:
607 LOG_ERROR("Invalid base address 0x%" PRIx32, bank->base);
608 return ERROR_FAIL;
609 }
610 break;
611
612 default:
613 LOG_ERROR("0x%" PRIx32 " is invalid id for SPEAr device",
614 target->tap->idcode);
615 return ERROR_FAIL;
616 }
617 io_base = spearsmi_info->io_base;
618
619 /* read and decode flash ID; returns in SW mode */
620 retval = read_flash_id(bank, &id);
621 SMI_SET_HW_MODE();
622 if (retval != ERROR_OK)
623 return retval;
624
625 for (struct flash_device *p = flash_devices; p->name ; p++)
626 if (p->device_id == id) {
627 spearsmi_info->dev = p;
628 break;
629 }
630
631 if (!spearsmi_info->dev)
632 {
633 LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", id);
634 return ERROR_FAIL;
635 }
636
637 LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")",
638 spearsmi_info->dev->name, spearsmi_info->dev->device_id);
639
640 /* Set correct size value */
641 bank->size = spearsmi_info->dev->size_in_bytes;
642
643 /* create and fill sectors array */
644 bank->num_sectors =
645 spearsmi_info->dev->size_in_bytes / spearsmi_info->dev->sectorsize;
646 sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
647 if (sectors == NULL)
648 {
649 LOG_ERROR("not enough memory");
650 return ERROR_FAIL;
651 }
652
653 for (int sector = 0; sector < bank->num_sectors; sector++)
654 {
655 sectors[sector].offset = sector * spearsmi_info->dev->sectorsize;
656 sectors[sector].size = spearsmi_info->dev->sectorsize;
657 sectors[sector].is_erased = -1;
658 sectors[sector].is_protected = 1;
659 }
660
661 bank->sectors = sectors;
662 spearsmi_info->probed = 1;
663 return ERROR_OK;
664 }
665
666 static int spearsmi_auto_probe(struct flash_bank *bank)
667 {
668 struct spearsmi_flash_bank *spearsmi_info = bank->driver_priv;
669 if (spearsmi_info->probed)
670 return ERROR_OK;
671 return spearsmi_probe(bank);
672 }
673
674 static int spearsmi_protect_check(struct flash_bank *bank)
675 {
676 /* Nothing to do. Protection is only handled in SW. */
677 return ERROR_OK;
678 }
679
680 static int get_spearsmi_info(struct flash_bank *bank, char *buf, int buf_size)
681 {
682 struct spearsmi_flash_bank *spearsmi_info = bank->driver_priv;
683 int printed;
684
685 if (!(spearsmi_info->probed))
686 {
687 printed = snprintf(buf, buf_size,
688 "\nSPEAr SMI flash bank not probed yet\n");
689 return ERROR_OK;
690 }
691
692 printed = snprintf(buf, buf_size, "\nSPEAr SMI flash information:\n"
693 " Device \'%s\' (ID 0x%08x)\n",
694 spearsmi_info->dev->name, spearsmi_info->dev->device_id);
695 buf += printed;
696 buf_size -= printed;
697
698 return ERROR_OK;
699 }
700
701 struct flash_driver spearsmi_flash = {
702 .name = "spearsmi",
703 .flash_bank_command = spearsmi_flash_bank_command,
704 .erase = spearsmi_erase,
705 .protect = spearsmi_protect,
706 .write = spearsmi_write,
707 .read = default_flash_read,
708 .probe = spearsmi_probe,
709 .auto_probe = spearsmi_auto_probe,
710 .erase_check = default_flash_blank_check,
711 .protect_check = spearsmi_protect_check,
712 .info = get_spearsmi_info,
713 };

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)