1 /***************************************************************************
2 * Copyright (C) 2015 by Tobias Diedrich *
3 * <ranma+openwrt@tdiedrich.de> *
5 * based on the stmsmi code written by Antonio Borneo *
6 * <borneo.antonio@gmail.com> *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc. *
22 ***************************************************************************/
24 * Driver for the Atheros AR7xxx/AR9xxx SPI flash interface.
26 * Since no SPI mode register is present, presumably only
27 * SPI "mode 3" (CPOL=1 and CPHA=1) is supported.
29 * The SPI interface supports up to 3 chip selects, however the SPI flash
30 * used for booting the system must be connected to CS0.
32 * On boot, the first 4MiB of flash space are memory-mapped into the
33 * area bf000000 - bfffffff (4 copies), so the MIPS bootstrap
34 * vector bfc00000 is mapped to the beginning of the flash.
36 * By writing a 1 to the REMAP_DISABLE bit in the SPI_CONTROL register,
37 * the full area of 16MiB is mapped.
39 * By writing a 0 to the SPI_FUNCTION_SELECT register (write-only dword
40 * register @bf000000), memory mapping is disabled and the SPI registers
41 * are exposed to the CPU instead:
42 * bf000000 SPI_FUNCTION_SELECT
43 * bf000004 SPI_CONTROL
44 * bf000008 SPI_IO_CONTROL
45 * bf00000c SPI_READ_DATA
47 * When not memory-mapped, the SPI interface is essentially bitbanged
48 * using SPI_CONTROL and SPI_IO_CONTROL with the only hardware-assistance
49 * being the 32bit read-only shift-register SPI_READ_DATA.
58 #include <jtag/jtag.h>
59 #include <helper/time_support.h>
60 #include <helper/types.h>
61 #include <target/mips32.h>
62 #include <target/mips32_pracc.h>
63 #include <target/target.h>
65 #define BITS_PER_BYTE 8
67 #define ATH79_REG_FS 0
68 #define ATH79_REG_CLOCK 4
69 #define ATH79_REG_WRITE 8
70 #define ATH79_REG_DATA 12
72 #define ATH79_SPI_CS_ALLHI 0x70000
73 #define ATH79_SPI_CS0_HI 0x10000
74 #define ATH79_SPI_CS1_HI 0x20000
75 #define ATH79_SPI_CS2_HI 0x40000
76 #define ATH79_SPI_CE_HI 0x00100
77 #define ATH79_SPI_DO_HI 0x00001
79 #define ATH79_XFER_FINAL 0x00000001
80 #define ATH79_XFER_PARTIAL 0x00000000
83 #define ATH79_MAX_TIMEOUT (3000)
85 struct ath79_spi_ctx
{
91 struct ath79_flash_bank
{
95 const struct flash_device
*dev
;
96 struct ath79_spi_ctx spi
;
105 static const struct ath79_target target_devices
[] = {
106 /* name, tap_idcode, io_base */
107 { "ATH79", 0x00000001, 0xbf000000 },
111 static const uint32_t ath79_chipselects
[] = {
112 (~ATH79_SPI_CS0_HI
& ATH79_SPI_CS_ALLHI
),
113 (~ATH79_SPI_CS1_HI
& ATH79_SPI_CS_ALLHI
),
114 (~ATH79_SPI_CS2_HI
& ATH79_SPI_CS_ALLHI
),
117 static void ath79_pracc_addn(struct pracc_queue_info
*ctx
,
118 const uint32_t *instr
,
121 for (int i
= 0; i
< n
; i
++)
122 pracc_add(ctx
, 0, instr
[i
]);
125 static int ath79_spi_bitbang_codegen(struct ath79_flash_bank
*ath79_info
,
126 struct pracc_queue_info
*ctx
,
127 uint8_t *data
, int len
,
130 uint32_t cs_high
= ATH79_SPI_CS_ALLHI
;
131 uint32_t cs_low
= ath79_chipselects
[ath79_info
->chipselect
];
132 uint32_t clock_high
= cs_low
| ATH79_SPI_CE_HI
;
133 uint32_t clock_low
= cs_low
;
134 uint32_t pracc_out
= 0;
135 uint32_t io_base
= ath79_info
->io_base
;
137 const uint32_t preamble1
[] = {
138 /* $15 = MIPS32_PRACC_BASE_ADDR */
139 MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR
),
141 MIPS32_LUI(1, UPPER16(io_base
)),
143 ath79_pracc_addn(ctx
, preamble1
, ARRAY_SIZE(preamble1
));
144 if (ath79_info
->spi
.pre_deselect
) {
145 /* Clear deselect flag so we don't deselect again if
146 * this is a partial xfer.
148 ath79_info
->spi
.pre_deselect
= 0;
149 const uint32_t pre_deselect
[] = {
150 /* [$1 + FS] = 1 (enable flash io register access) */
151 MIPS32_LUI(2, UPPER16(1)),
152 MIPS32_ORI(2, 2, LOWER16(1)),
153 MIPS32_SW(2, ATH79_REG_FS
, 1),
154 /* deselect flash just in case */
155 /* $2 = SPI_CS_DIS */
156 MIPS32_LUI(2, UPPER16(cs_high
)),
157 MIPS32_ORI(2, 2, LOWER16(cs_high
)),
158 /* [$1 + WRITE] = $2 */
159 MIPS32_SW(2, ATH79_REG_WRITE
, 1),
161 ath79_pracc_addn(ctx
, pre_deselect
, ARRAY_SIZE(pre_deselect
));
163 const uint32_t preamble2
[] = {
164 /* t0 = CLOCK_LOW + 0-bit */
165 MIPS32_LUI(8, UPPER16((clock_low
+ 0))),
166 MIPS32_ORI(8, 8, LOWER16((clock_low
+ 0))),
167 /* t1 = CLOCK_LOW + 1-bit */
168 MIPS32_LUI(9, UPPER16((clock_low
+ 1))),
169 MIPS32_ORI(9, 9, LOWER16((clock_low
+ 1))),
170 /* t2 = CLOCK_HIGH + 0-bit */
171 MIPS32_LUI(10, UPPER16((clock_high
+ 0))),
172 MIPS32_ORI(10, 10, LOWER16((clock_high
+ 0))),
173 /* t3 = CLOCK_HIGH + 1-bit */
174 MIPS32_LUI(11, UPPER16((clock_high
+ 1))),
175 MIPS32_ORI(11, 11, LOWER16((clock_high
+ 1))),
177 ath79_pracc_addn(ctx
, preamble2
, ARRAY_SIZE(preamble2
));
179 for (int i
= 0; i
< len
; i
++) {
182 /* Generate bitbang code for one byte, highest bit first .*/
183 for (int j
= BITS_PER_BYTE
- 1; j
>= 0; j
--) {
184 int bit
= ((x
>> j
) & 1);
187 /* [$1 + WRITE] = t1 */
189 MIPS32_SW(9, ATH79_REG_WRITE
, 1));
190 /* [$1 + WRITE] = t3 */
192 MIPS32_SW(11, ATH79_REG_WRITE
, 1));
194 /* [$1 + WRITE] = t0 */
196 MIPS32_SW(8, ATH79_REG_WRITE
, 1));
197 /* [$1 + WRITE] = t2 */
199 MIPS32_SW(10, ATH79_REG_WRITE
, 1));
203 /* $3 = [$1 + DATA] */
204 pracc_add(ctx
, 0, MIPS32_LW(3, ATH79_REG_DATA
, 1));
206 pracc_add(ctx
, MIPS32_PRACC_PARAM_OUT
+ pracc_out
,
207 MIPS32_SW(3, PRACC_OUT_OFFSET
+
212 if (len
& 3) { /* not a multiple of 4 bytes */
213 /* $3 = [$1 + DATA] */
214 pracc_add(ctx
, 0, MIPS32_LW(3, ATH79_REG_DATA
, 1));
216 pracc_add(ctx
, MIPS32_PRACC_PARAM_OUT
+ pracc_out
,
217 MIPS32_SW(3, PRACC_OUT_OFFSET
+ pracc_out
, 15));
221 if (ath79_info
->spi
.post_deselect
&& !partial_xfer
) {
222 const uint32_t post_deselect
[] = {
223 /* $2 = SPI_CS_DIS */
224 MIPS32_LUI(2, UPPER16(cs_high
)),
225 MIPS32_ORI(2, 2, LOWER16(cs_high
)),
226 /* [$1 + WRITE] = $2 */
227 MIPS32_SW(2, ATH79_REG_WRITE
, 1),
229 /* [$1 + FS] = 0 (disable flash io register access) */
230 MIPS32_XORI(2, 2, 0),
231 MIPS32_SW(2, ATH79_REG_FS
, 1),
233 ath79_pracc_addn(ctx
, post_deselect
, ARRAY_SIZE(post_deselect
));
236 /* common pracc epilogue */
238 pracc_add(ctx
, 0, MIPS32_B(NEG16(ctx
->code_count
+ 1)));
239 /* restore $15 from DeSave */
240 pracc_add(ctx
, 0, MIPS32_MFC0(15, 31, 0));
242 return pracc_out
/ 4;
245 static int ath79_spi_bitbang_chunk(struct flash_bank
*bank
,
246 uint8_t *data
, int len
, int *transferred
)
248 struct target
*target
= bank
->target
;
249 struct ath79_flash_bank
*ath79_info
= bank
->driver_priv
;
250 struct mips32_common
*mips32
= target_to_mips32(target
);
251 struct mips_ejtag
*ejtag_info
= &mips32
->ejtag_info
;
255 * These constants must match the worst case in the above code
256 * generator function ath79_spi_bitbang_codegen.
258 const int pracc_pre_post
= 26;
259 const int pracc_loop_byte
= 8 * 2 + 2;
261 struct pracc_queue_info ctx
= {
262 .max_code
= PRACC_MAX_INSTRUCTIONS
264 int max_len
= (ctx
.max_code
- pracc_pre_post
) / pracc_loop_byte
;
265 int to_xfer
= len
> max_len
? max_len
: len
;
266 int partial_xfer
= len
!= to_xfer
;
267 int padded_len
= (to_xfer
+ 3) & ~3;
268 uint32_t *out
= malloc(padded_len
);
271 LOG_ERROR("not enough memory");
276 pracc_queue_init(&ctx
);
277 if (ctx
.retval
!= ERROR_OK
)
280 LOG_DEBUG("ath79_spi_bitbang_bytes(%p, %08x, %p, %d)",
281 target
, ath79_info
->io_base
, data
, len
);
283 LOG_DEBUG("max code %d => max len %d. to_xfer %d",
284 ctx
.max_code
, max_len
, to_xfer
);
286 pracc_words
= ath79_spi_bitbang_codegen(
287 ath79_info
, &ctx
, data
, to_xfer
, partial_xfer
);
289 LOG_DEBUG("Assembled %d instructions, %d stores",
290 ctx
.code_count
, ctx
.store_count
);
292 ctx
.retval
= mips32_pracc_queue_exec(ejtag_info
, &ctx
, out
);
293 if (ctx
.retval
!= ERROR_OK
)
296 if (to_xfer
& 3) { /* Not a multiple of 4 bytes. */
298 * Need to realign last word since we didn't shift the
301 int missed_bytes
= 4 - (to_xfer
& 3);
303 out
[pracc_words
- 1] <<= BITS_PER_BYTE
* missed_bytes
;
307 * pracc reads return uint32_t in host endianness, convert to
309 * Since we know the ATH79 target is big endian and the SPI
310 * shift register has the bytes in highest to lowest bit order,
311 * this will ensure correct memory byte order regardless of host
314 target_buffer_set_u32_array(target
, (uint8_t *)out
, pracc_words
, out
);
316 if (LOG_LEVEL_IS(LOG_LVL_DEBUG
)) {
317 for (int i
= 0; i
< to_xfer
; i
++) {
318 LOG_DEBUG("bitbang %02x => %02x",
319 data
[i
], ((uint8_t *)out
)[i
]);
322 memcpy(data
, out
, to_xfer
);
323 *transferred
= to_xfer
;
326 pracc_queue_free(&ctx
);
331 static void ath79_spi_bitbang_prepare(struct flash_bank
*bank
)
333 struct ath79_flash_bank
*ath79_info
= bank
->driver_priv
;
335 ath79_info
->spi
.pre_deselect
= 1;
338 static int ath79_spi_bitbang_bytes(struct flash_bank
*bank
,
339 uint8_t *data
, int len
, uint32_t flags
)
341 struct ath79_flash_bank
*ath79_info
= bank
->driver_priv
;
345 ath79_info
->spi
.post_deselect
= !!(flags
& ATH79_XFER_FINAL
);
349 retval
= ath79_spi_bitbang_chunk(
350 bank
, data
, len
, &transferred
);
351 if (retval
!= ERROR_OK
)
361 FLASH_BANK_COMMAND_HANDLER(ath79_flash_bank_command
)
363 struct ath79_flash_bank
*ath79_info
;
366 LOG_DEBUG("%s", __func__
);
368 if (CMD_ARGC
< 6 || CMD_ARGC
> 7)
369 return ERROR_COMMAND_SYNTAX_ERROR
;
372 if (strcmp(CMD_ARGV
[6], "cs0") == 0)
373 chipselect
= 0; /* default */
374 else if (strcmp(CMD_ARGV
[6], "cs1") == 0)
376 else if (strcmp(CMD_ARGV
[6], "cs2") == 0)
379 LOG_ERROR("Unknown arg: %s", CMD_ARGV
[6]);
380 return ERROR_COMMAND_SYNTAX_ERROR
;
384 ath79_info
= calloc(1, sizeof(struct ath79_flash_bank
));
386 LOG_ERROR("not enough memory");
390 ath79_info
->chipselect
= chipselect
;
391 bank
->driver_priv
= ath79_info
;
396 /* Read the status register of the external SPI flash chip. */
397 static int read_status_reg(struct flash_bank
*bank
, uint32_t *status
)
399 uint8_t spi_bytes
[] = {SPIFLASH_READ_STATUS
, 0};
402 /* Send SPI command "read STATUS" */
403 ath79_spi_bitbang_prepare(bank
);
404 retval
= ath79_spi_bitbang_bytes(
405 bank
, spi_bytes
, sizeof(spi_bytes
),
408 *status
= spi_bytes
[1];
413 /* check for WIP (write in progress) bit in status register */
415 static int wait_till_ready(struct flash_bank
*bank
, int timeout
)
421 endtime
= timeval_ms() + timeout
;
423 /* read flash status register */
424 retval
= read_status_reg(bank
, &status
);
425 if (retval
!= ERROR_OK
)
428 if ((status
& SPIFLASH_BSY_BIT
) == 0)
431 } while (timeval_ms() < endtime
);
433 LOG_ERROR("timeout");
437 /* Send "write enable" command to SPI flash chip. */
438 static int ath79_write_enable(struct flash_bank
*bank
)
443 uint8_t spi_bytes
[] = {SPIFLASH_WRITE_ENABLE
};
445 /* Send SPI command "write enable" */
446 ath79_spi_bitbang_prepare(bank
);
447 retval
= ath79_spi_bitbang_bytes(
448 bank
, spi_bytes
, sizeof(spi_bytes
),
450 if (retval
!= ERROR_OK
)
453 /* read flash status register */
454 retval
= read_status_reg(bank
, &status
);
455 if (retval
!= ERROR_OK
)
458 /* Check write enabled */
459 if ((status
& SPIFLASH_WE_BIT
) == 0) {
460 LOG_ERROR("Cannot enable write to flash. Status=0x%08" PRIx32
,
468 static int erase_command(struct flash_bank
*bank
, int sector
)
470 struct ath79_flash_bank
*ath79_info
= bank
->driver_priv
;
471 uint32_t offset
= bank
->sectors
[sector
].offset
;
473 uint8_t spi_bytes
[] = {
474 ath79_info
->dev
->erase_cmd
,
480 /* bitbang command */
481 ath79_spi_bitbang_prepare(bank
);
482 return ath79_spi_bitbang_bytes(
483 bank
, spi_bytes
, sizeof(spi_bytes
),
487 static int ath79_erase_sector(struct flash_bank
*bank
, int sector
)
489 int retval
= ath79_write_enable(bank
);
491 if (retval
!= ERROR_OK
)
494 /* send SPI command "block erase" */
495 retval
= erase_command(bank
, sector
);
496 if (retval
!= ERROR_OK
)
499 /* poll WIP for end of self timed Sector Erase cycle */
500 return wait_till_ready(bank
, ATH79_MAX_TIMEOUT
);
503 static int ath79_erase(struct flash_bank
*bank
, int first
, int last
)
505 struct target
*target
= bank
->target
;
506 struct ath79_flash_bank
*ath79_info
= bank
->driver_priv
;
507 int retval
= ERROR_OK
;
510 LOG_DEBUG("%s: from sector %d to sector %d", __func__
, first
, last
);
512 if (target
->state
!= TARGET_HALTED
) {
513 LOG_ERROR("Target not halted");
514 return ERROR_TARGET_NOT_HALTED
;
517 if ((first
< 0) || (last
< first
) || (last
>= bank
->num_sectors
)) {
518 LOG_ERROR("Flash sector invalid");
519 return ERROR_FLASH_SECTOR_INVALID
;
522 if (!ath79_info
->probed
) {
523 LOG_ERROR("Flash bank not probed");
524 return ERROR_FLASH_BANK_NOT_PROBED
;
527 for (sector
= first
; sector
<= last
; sector
++) {
528 if (bank
->sectors
[sector
].is_protected
) {
529 LOG_ERROR("Flash sector %d protected", sector
);
534 for (sector
= first
; sector
<= last
; sector
++) {
535 retval
= ath79_erase_sector(bank
, sector
);
536 if (retval
!= ERROR_OK
)
544 static int ath79_protect(struct flash_bank
*bank
, int set
,
549 for (sector
= first
; sector
<= last
; sector
++)
550 bank
->sectors
[sector
].is_protected
= set
;
554 static int ath79_write_page(struct flash_bank
*bank
, const uint8_t *buffer
,
555 uint32_t address
, uint32_t len
)
557 struct ath79_flash_bank
*ath79_info
= bank
->driver_priv
;
558 uint8_t spi_bytes
[] = {
559 SPIFLASH_PAGE_PROGRAM
,
567 if (address
& 0xff) {
568 LOG_ERROR("ath79_write_page: unaligned write address: %08x",
572 if (!ath79_info
->spi
.page_buf
) {
573 LOG_ERROR("ath79_write_page: page buffer not initialized");
576 if (len
> ath79_info
->dev
->pagesize
) {
577 LOG_ERROR("ath79_write_page: len bigger than page size %d: %d",
578 ath79_info
->dev
->pagesize
, len
);
582 for (i
= 0; i
< len
; i
++) {
583 if (buffer
[i
] != 0xff)
586 if (i
== len
) /* all 0xff, no need to program. */
589 LOG_INFO("writing %d bytes to flash page @0x%08x", len
, address
);
591 memcpy(ath79_info
->spi
.page_buf
, buffer
, len
);
594 retval
= ath79_write_enable(bank
);
595 if (retval
!= ERROR_OK
)
598 /* bitbang command */
599 ath79_spi_bitbang_prepare(bank
);
600 retval
= ath79_spi_bitbang_bytes(
601 bank
, spi_bytes
, sizeof(spi_bytes
),
603 if (retval
!= ERROR_OK
)
607 return ath79_spi_bitbang_bytes(
608 bank
, ath79_info
->spi
.page_buf
, len
,
612 static int ath79_write_buffer(struct flash_bank
*bank
, const uint8_t *buffer
,
613 uint32_t address
, uint32_t len
)
615 struct ath79_flash_bank
*ath79_info
= bank
->driver_priv
;
616 const uint32_t page_size
= ath79_info
->dev
->pagesize
;
619 LOG_DEBUG("%s: address=0x%08" PRIx32
" len=0x%08" PRIx32
,
620 __func__
, address
, len
);
623 int page_len
= len
> page_size
? page_size
: len
;
625 retval
= ath79_write_page(
626 bank
, buffer
, address
, page_len
);
627 if (retval
!= ERROR_OK
)
631 address
+= page_size
;
638 static int ath79_write(struct flash_bank
*bank
, const uint8_t *buffer
,
639 uint32_t offset
, uint32_t count
)
641 struct target
*target
= bank
->target
;
644 LOG_DEBUG("%s: offset=0x%08" PRIx32
" count=0x%08" PRIx32
,
645 __func__
, offset
, count
);
647 if (offset
< bank
->base
|| offset
>= bank
->base
+ bank
->size
) {
648 LOG_ERROR("Start address out of range");
652 offset
-= bank
->base
;
654 if (target
->state
!= TARGET_HALTED
) {
655 LOG_ERROR("Target not halted");
656 return ERROR_TARGET_NOT_HALTED
;
659 if (offset
+ count
> bank
->size
) {
660 LOG_WARNING("Write pasts end of flash. Extra data discarded.");
661 count
= bank
->size
- offset
;
664 /* Check sector protection */
665 for (sector
= 0; sector
< bank
->num_sectors
; sector
++) {
666 /* Start offset in or before this sector? */
667 /* End offset in or behind this sector? */
668 struct flash_sector
*bs
= &bank
->sectors
[sector
];
670 if ((offset
< (bs
->offset
+ bs
->size
)) &&
671 ((offset
+ count
- 1) >= bs
->offset
) &&
673 LOG_ERROR("Flash sector %d protected", sector
);
678 return ath79_write_buffer(bank
, buffer
, offset
, count
);
681 static int ath79_read_buffer(struct flash_bank
*bank
, uint8_t *buffer
,
682 uint32_t address
, uint32_t len
)
684 uint8_t spi_bytes
[] = {
692 LOG_DEBUG("%s: address=0x%08" PRIx32
" len=0x%08" PRIx32
,
693 __func__
, address
, len
);
695 if (address
& 0xff) {
696 LOG_ERROR("ath79_read_buffer: unaligned read address: %08x",
701 LOG_INFO("reading %d bytes from flash @0x%08x", len
, address
);
703 /* bitbang command */
704 ath79_spi_bitbang_prepare(bank
);
705 retval
= ath79_spi_bitbang_bytes(
706 bank
, spi_bytes
, sizeof(spi_bytes
), ATH79_XFER_PARTIAL
);
707 if (retval
!= ERROR_OK
)
711 return ath79_spi_bitbang_bytes(
712 bank
, buffer
, len
, ATH79_XFER_FINAL
);
715 static int ath79_read(struct flash_bank
*bank
, uint8_t *buffer
,
716 uint32_t offset
, uint32_t count
)
718 struct target
*target
= bank
->target
;
720 LOG_DEBUG("%s: offset=0x%08" PRIx32
" count=0x%08" PRIx32
,
721 __func__
, offset
, count
);
723 if (offset
< bank
->base
|| offset
>= bank
->base
+ bank
->size
) {
724 LOG_ERROR("Start address out of range");
728 offset
-= bank
->base
;
730 if (target
->state
!= TARGET_HALTED
) {
731 LOG_ERROR("Target not halted");
732 return ERROR_TARGET_NOT_HALTED
;
735 if (offset
+ count
> bank
->size
) {
736 LOG_WARNING("Reads past end of flash. Extra data discarded.");
737 count
= bank
->size
- offset
;
740 return ath79_read_buffer(bank
, buffer
, offset
, count
);
743 /* Return ID of flash device */
744 static int read_flash_id(struct flash_bank
*bank
, uint32_t *id
)
746 struct target
*target
= bank
->target
;
748 uint8_t spi_bytes
[] = {SPIFLASH_READ_ID
, 0, 0, 0};
750 if (target
->state
!= TARGET_HALTED
) {
751 LOG_ERROR("Target not halted");
752 return ERROR_TARGET_NOT_HALTED
;
755 /* Send SPI command "read ID" */
756 ath79_spi_bitbang_prepare(bank
);
757 retval
= ath79_spi_bitbang_bytes(
758 bank
, spi_bytes
, sizeof(spi_bytes
), ATH79_XFER_FINAL
);
759 if (retval
!= ERROR_OK
)
762 *id
= (spi_bytes
[1] << 0)
763 | (spi_bytes
[2] << 8)
764 | (spi_bytes
[3] << 16);
766 if (*id
== 0xffffff) {
767 LOG_ERROR("No SPI flash found");
774 static int ath79_probe(struct flash_bank
*bank
)
776 struct target
*target
= bank
->target
;
777 struct ath79_flash_bank
*ath79_info
= bank
->driver_priv
;
778 struct flash_sector
*sectors
;
779 uint32_t id
= 0; /* silence uninitialized warning */
780 const struct ath79_target
*target_device
;
783 if (ath79_info
->probed
) {
785 free(ath79_info
->spi
.page_buf
);
787 ath79_info
->probed
= 0;
789 for (target_device
= target_devices
; target_device
->name
;
791 if (target_device
->tap_idcode
== target
->tap
->idcode
)
793 if (!target_device
->name
) {
794 LOG_ERROR("Device ID 0x%" PRIx32
" is not known",
795 target
->tap
->idcode
);
799 ath79_info
->io_base
= target_device
->io_base
;
801 LOG_DEBUG("Found device %s at address 0x%" PRIx32
,
802 target_device
->name
, bank
->base
);
804 retval
= read_flash_id(bank
, &id
);
805 if (retval
!= ERROR_OK
)
808 ath79_info
->dev
= NULL
;
809 for (const struct flash_device
*p
= flash_devices
; p
->name
; p
++)
810 if (p
->device_id
== id
) {
815 if (!ath79_info
->dev
) {
816 LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32
")", id
);
820 LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32
")",
821 ath79_info
->dev
->name
, ath79_info
->dev
->device_id
);
823 /* Set correct size value */
824 bank
->size
= ath79_info
->dev
->size_in_bytes
;
826 /* create and fill sectors array */
828 ath79_info
->dev
->size_in_bytes
/ ath79_info
->dev
->sectorsize
;
829 sectors
= calloc(1, sizeof(struct flash_sector
) * bank
->num_sectors
);
831 LOG_ERROR("not enough memory");
834 ath79_info
->spi
.page_buf
= malloc(ath79_info
->dev
->pagesize
);
835 if (!ath79_info
->spi
.page_buf
) {
836 LOG_ERROR("not enough memory");
841 for (int sector
= 0; sector
< bank
->num_sectors
; sector
++) {
842 sectors
[sector
].offset
= sector
* ath79_info
->dev
->sectorsize
;
843 sectors
[sector
].size
= ath79_info
->dev
->sectorsize
;
844 sectors
[sector
].is_erased
= 0;
845 sectors
[sector
].is_protected
= 1;
848 bank
->sectors
= sectors
;
849 ath79_info
->probed
= 1;
853 static int ath79_auto_probe(struct flash_bank
*bank
)
855 struct ath79_flash_bank
*ath79_info
= bank
->driver_priv
;
857 if (ath79_info
->probed
)
859 return ath79_probe(bank
);
862 static int ath79_flash_blank_check(struct flash_bank
*bank
)
864 /* Not implemented */
868 static int ath79_protect_check(struct flash_bank
*bank
)
870 /* Not implemented */
874 static int get_ath79_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
876 struct ath79_flash_bank
*ath79_info
= bank
->driver_priv
;
878 if (!ath79_info
->probed
) {
879 snprintf(buf
, buf_size
,
880 "\nATH79 flash bank not probed yet\n");
884 snprintf(buf
, buf_size
, "\nATH79 flash information:\n"
885 " Device \'%s\' (ID 0x%08" PRIx32
")\n",
886 ath79_info
->dev
->name
, ath79_info
->dev
->device_id
);
891 struct flash_driver ath79_flash
= {
893 .flash_bank_command
= ath79_flash_bank_command
,
894 .erase
= ath79_erase
,
895 .protect
= ath79_protect
,
896 .write
= ath79_write
,
898 .probe
= ath79_probe
,
899 .auto_probe
= ath79_auto_probe
,
900 .erase_check
= ath79_flash_blank_check
,
901 .protect_check
= ath79_protect_check
,
902 .info
= get_ath79_info
,
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)