1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright (c) 2024 ENE Technology Inc.
12 #include <helper/time_support.h>
13 #include <helper/bits.h>
14 #include <target/target.h>
15 #include <flash/nor/core.h>
16 #include <flash/nor/driver.h>
17 #include <flash/nor/spi.h>
19 #define ISPICFG 0x0000
20 #define ISPISTS 0x0004
21 #define ISPIADDR 0x0008
22 #define ISPICMD 0x000C
23 #define ISPIDAT 0x0100
25 #define ISPISTS_BUSY BIT(0)
26 #define STATUS1_QE BIT(1)
28 #define CFG_READ 0x372
29 #define CFG_WRITE 0x371
31 #define ISPI_CTRL_BASE 0x50101000
33 /* name read qread page erase chip device_id page erase flash
34 * _cmd _cmd _prog _cmd* _erase size size* size
37 struct flash_device ene_flash_device
=
38 FLASH_ID("ISPI flash", 0x03, 0x00, 0x02, 0x20, 0x60, 0x00132085, 0x100, 0x1000, 0x80000);
40 struct eneispif_flash_bank
{
42 target_addr_t ctrl_base
;
44 const struct flash_device
*dev
;
47 FLASH_BANK_COMMAND_HANDLER(eneispif_flash_bank_command
)
49 struct eneispif_flash_bank
*eneispif_info
;
51 LOG_DEBUG("%s", __func__
);
54 return ERROR_COMMAND_SYNTAX_ERROR
;
56 eneispif_info
= malloc(sizeof(struct eneispif_flash_bank
));
58 LOG_ERROR("not enough memory");
62 bank
->driver_priv
= eneispif_info
;
63 eneispif_info
->probed
= false;
64 eneispif_info
->ctrl_base
= ISPI_CTRL_BASE
;
66 COMMAND_PARSE_ADDRESS(CMD_ARGV
[6], eneispif_info
->ctrl_base
);
67 LOG_INFO("ASSUMING ISPI device at ctrl_base = " TARGET_ADDR_FMT
,
68 eneispif_info
->ctrl_base
);
74 static int eneispif_read_reg(struct flash_bank
*bank
, uint32_t *value
, target_addr_t address
)
76 struct target
*target
= bank
->target
;
77 struct eneispif_flash_bank
*eneispif_info
= bank
->driver_priv
;
79 int result
= target_read_u32(target
, eneispif_info
->ctrl_base
+ address
, value
);
80 if (result
!= ERROR_OK
) {
81 LOG_ERROR("%s error at " TARGET_ADDR_FMT
, __func__
,
82 eneispif_info
->ctrl_base
+ address
);
85 LOG_DEBUG("Read address " TARGET_ADDR_FMT
" = 0x%" PRIx32
,
86 eneispif_info
->ctrl_base
+ address
, *value
);
90 static int eneispif_write_reg(struct flash_bank
*bank
, target_addr_t address
, uint32_t value
)
92 struct target
*target
= bank
->target
;
93 struct eneispif_flash_bank
*eneispif_info
= bank
->driver_priv
;
95 LOG_DEBUG("Write address " TARGET_ADDR_FMT
" = 0x%" PRIx32
,
96 eneispif_info
->ctrl_base
+ address
, value
);
97 int result
= target_write_u32(target
, eneispif_info
->ctrl_base
+ address
, value
);
98 if (result
!= ERROR_OK
) {
99 LOG_ERROR("%s error writing 0x%" PRIx32
" to " TARGET_ADDR_FMT
, __func__
,
100 value
, eneispif_info
->ctrl_base
+ address
);
106 static int eneispif_wait(struct flash_bank
*bank
)
108 int64_t start
= timeval_ms();
113 if (eneispif_read_reg(bank
, &status
, ISPISTS
) != ERROR_OK
)
116 if (!(status
& ISPISTS_BUSY
))
119 int64_t now
= timeval_ms();
120 if (now
- start
> 1000) {
121 LOG_ERROR("Busy more than 1000ms.");
122 return ERROR_TARGET_TIMEOUT
;
129 static int eneispi_erase_sector(struct flash_bank
*bank
, int sector
)
131 int retval
= ERROR_OK
;
132 struct eneispif_flash_bank
*eneispif_info
= bank
->driver_priv
;
136 retval
= eneispif_read_reg(bank
, &conf
, ISPICFG
);
137 if (retval
!= ERROR_OK
)
140 offset
= bank
->sectors
[sector
].offset
;
141 retval
= eneispif_write_reg(bank
, ISPIADDR
, offset
); /* Address */
142 if (retval
!= ERROR_OK
)
145 eneispif_write_reg(bank
, ISPICFG
, CFG_WRITE
); /* Cmmmand enable */
146 eneispif_write_reg(bank
, ISPICMD
, SPIFLASH_WRITE_ENABLE
); /* Write enable */
147 retval
= eneispif_write_reg(bank
, ISPICMD
, eneispif_info
->dev
->erase_cmd
); /* Erase page */
148 if (retval
!= ERROR_OK
)
151 retval
= eneispif_wait(bank
);
152 if (retval
!= ERROR_OK
)
156 eneispif_write_reg(bank
, ISPICFG
, conf
); /* restore */
160 static int eneispif_erase(struct flash_bank
*bank
, unsigned int first
, unsigned int last
)
162 struct target
*target
= bank
->target
;
163 struct eneispif_flash_bank
*eneispif_info
= bank
->driver_priv
;
164 int retval
= ERROR_OK
;
166 LOG_DEBUG("%s: from sector %u to sector %u", __func__
, first
, last
);
168 if (target
->state
!= TARGET_HALTED
) {
169 LOG_ERROR("Target not halted");
170 return ERROR_TARGET_NOT_HALTED
;
173 if (last
< first
|| last
>= bank
->num_sectors
) {
174 LOG_ERROR("Flash sector invalid");
175 return ERROR_FLASH_SECTOR_INVALID
;
178 if (!(eneispif_info
->probed
)) {
179 LOG_ERROR("Flash bank not probed");
180 return ERROR_FLASH_BANK_NOT_PROBED
;
183 for (unsigned int sector
= first
; sector
<= last
; sector
++) {
184 if (bank
->sectors
[sector
].is_protected
) {
185 LOG_ERROR("Flash sector %u protected", sector
);
190 if (eneispif_info
->dev
->erase_cmd
== 0x00)
191 return ERROR_FLASH_OPER_UNSUPPORTED
;
193 for (unsigned int sector
= first
; sector
<= last
; sector
++) {
194 retval
= eneispi_erase_sector(bank
, sector
);
195 if (retval
!= ERROR_OK
)
202 static int eneispif_protect(struct flash_bank
*bank
, int set
, unsigned int first
, unsigned int last
)
204 for (unsigned int sector
= first
; sector
<= last
; sector
++)
205 bank
->sectors
[sector
].is_protected
= set
;
210 static int eneispif_write(struct flash_bank
*bank
, const uint8_t *buffer
, uint32_t offset
,
213 struct target
*target
= bank
->target
;
214 struct eneispif_flash_bank
*eneispif_info
= bank
->driver_priv
;
217 int retval
= ERROR_OK
;
219 LOG_DEBUG("bank->size=0x%x offset=0x%08" PRIx32
" count=0x%08" PRIx32
, bank
->size
, offset
,
222 if (target
->state
!= TARGET_HALTED
) {
223 LOG_ERROR("Target not halted");
224 return ERROR_TARGET_NOT_HALTED
;
227 if (offset
+ count
> eneispif_info
->dev
->size_in_bytes
) {
228 LOG_WARNING("Write past end of flash. Extra data discarded.");
229 count
= eneispif_info
->dev
->size_in_bytes
- offset
;
232 /* Check sector protection */
233 for (unsigned int sector
= 0; sector
< bank
->num_sectors
; sector
++) {
234 /* Start offset in or before this sector? */
235 /* End offset in or behind this sector? */
236 if ((offset
< (bank
->sectors
[sector
].offset
+ bank
->sectors
[sector
].size
)) &&
237 ((offset
+ count
- 1) >= bank
->sectors
[sector
].offset
) &&
238 bank
->sectors
[sector
].is_protected
) {
239 LOG_ERROR("Flash sector %u protected", sector
);
244 retval
= eneispif_read_reg(bank
, &conf
, ISPICFG
);
245 if (retval
!= ERROR_OK
)
248 eneispif_write_reg(bank
, ISPICFG
, CFG_WRITE
); // Cmmmand enable
250 /* If no valid page_size, use reasonable default. */
252 eneispif_info
->dev
->pagesize
? eneispif_info
->dev
->pagesize
: SPIFLASH_DEF_PAGESIZE
;
253 uint32_t page_offset
= offset
% page_size
;
258 /* clip block at page boundary */
259 if (page_offset
+ count
> page_size
)
260 cur_count
= page_size
- page_offset
;
264 eneispif_write_reg(bank
, ISPICMD
, SPIFLASH_WRITE_ENABLE
); /* Write enable */
265 target_write_buffer(target
, eneispif_info
->ctrl_base
+ ISPIDAT
, cur_count
, buffer
);
266 eneispif_write_reg(bank
, ISPIADDR
, offset
);
267 retval
= eneispif_write_reg(bank
, ISPICMD
,
268 (cur_count
<< 16) | eneispif_info
->dev
->pprog_cmd
);
269 if (retval
!= ERROR_OK
)
276 retval
= eneispif_wait(bank
);
277 if (retval
!= ERROR_OK
)
282 eneispif_write_reg(bank
, ISPICFG
, conf
); /* restore */
286 /* Return ID of flash device */
287 /* On exit, SW mode is kept */
288 static int eneispif_read_flash_id(struct flash_bank
*bank
, uint32_t *id
)
290 struct eneispif_flash_bank
*eneispif_info
= bank
->driver_priv
;
291 struct target
*target
= bank
->target
;
293 uint32_t conf
, value
;
296 if (target
->state
!= TARGET_HALTED
) {
297 LOG_ERROR("Target not halted");
298 return ERROR_TARGET_NOT_HALTED
;
301 retval
= eneispif_read_reg(bank
, &conf
, ISPICFG
);
302 if (retval
!= ERROR_OK
)
305 LOG_DEBUG("ISPCFG = (0x%08" PRIx32
")", conf
);
307 /* read ID from Receive Register */
308 eneispif_write_reg(bank
, ISPICFG
, CFG_WRITE
); /* Cmmmand enable */
309 retval
= eneispif_write_reg(bank
, ISPICMD
, (3 << 16) | SPIFLASH_READ_ID
);
310 if (retval
!= ERROR_OK
)
313 retval
= eneispif_wait(bank
);
314 if (retval
!= ERROR_OK
)
317 retval
= target_read_buffer(target
, eneispif_info
->ctrl_base
+ ISPIDAT
, 3, buffer
);
318 if (retval
!= ERROR_OK
)
320 value
= (buffer
[2] << 16) | (buffer
[1] << 8) | buffer
[0];
321 LOG_DEBUG("ISPDAT = (0x%08" PRIx32
")", value
);
325 eneispif_write_reg(bank
, ISPICFG
, conf
); // restore
329 static int eneispif_probe(struct flash_bank
*bank
)
331 struct eneispif_flash_bank
*eneispif_info
= bank
->driver_priv
;
332 struct flash_sector
*sectors
;
337 if (eneispif_info
->probed
)
340 eneispif_info
->probed
= false;
342 LOG_INFO("Assuming ISPI flash at address " TARGET_ADDR_FMT
343 " with controller at " TARGET_ADDR_FMT
,
344 bank
->base
, eneispif_info
->ctrl_base
);
346 eneispif_write_reg(bank
, ISPICFG
, CFG_READ
); /* RAM map enable */
348 retval
= eneispif_read_flash_id(bank
, &id
);
349 if (retval
!= ERROR_OK
)
352 eneispif_info
->dev_id
= id
;
353 eneispif_info
->dev
= &ene_flash_device
;
355 LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32
")", eneispif_info
->dev
->name
,
356 eneispif_info
->dev_id
);
358 /* Set correct size value */
359 bank
->size
= eneispif_info
->dev
->size_in_bytes
;
361 if (bank
->size
<= (1UL << 16))
362 LOG_WARNING("device needs 2-byte addresses - not implemented");
364 /* if no sectors, treat whole bank as single sector */
365 sectorsize
= eneispif_info
->dev
->sectorsize
? eneispif_info
->dev
->sectorsize
366 : eneispif_info
->dev
->size_in_bytes
;
368 /* create and fill sectors array */
369 bank
->num_sectors
= eneispif_info
->dev
->size_in_bytes
/ sectorsize
;
370 sectors
= malloc(sizeof(struct flash_sector
) * bank
->num_sectors
);
372 LOG_ERROR("not enough memory");
376 for (unsigned int sector
= 0; sector
< bank
->num_sectors
; sector
++) {
377 sectors
[sector
].offset
= sector
* sectorsize
;
378 sectors
[sector
].size
= sectorsize
;
379 sectors
[sector
].is_erased
= -1;
380 sectors
[sector
].is_protected
= 0;
383 bank
->sectors
= sectors
;
384 eneispif_info
->probed
= true;
388 static int eneispif_auto_probe(struct flash_bank
*bank
)
390 struct eneispif_flash_bank
*eneispif_info
= bank
->driver_priv
;
391 if (eneispif_info
->probed
)
393 return eneispif_probe(bank
);
396 static int eneispif_protect_check(struct flash_bank
*bank
)
398 /* Nothing to do. Protection is only handled in SW. */
402 static int get_eneispif_info(struct flash_bank
*bank
, struct command_invocation
*cmd
)
404 struct eneispif_flash_bank
*eneispif_info
= bank
->driver_priv
;
406 if (!(eneispif_info
->probed
)) {
407 command_print(cmd
, "ENE ISPI flash bank not probed yet.");
412 "ENE ISPI flash information:\n"
413 " Device \'%s\' (ID 0x%08" PRIx32
")",
414 eneispif_info
->dev
->name
, eneispif_info
->dev_id
);
419 const struct flash_driver eneispif_flash
= {
421 .usage
= "flash bank <name> 'eneispif' <base_address> <size> 0 0 <target> <ctrl_base>",
422 .flash_bank_command
= eneispif_flash_bank_command
,
423 .erase
= eneispif_erase
,
424 .protect
= eneispif_protect
,
425 .write
= eneispif_write
,
426 .read
= default_flash_read
,
427 .probe
= eneispif_probe
,
428 .auto_probe
= eneispif_auto_probe
,
429 .erase_check
= default_flash_blank_check
,
430 .protect_check
= eneispif_protect_check
,
431 .info
= get_eneispif_info
,
432 .free_driver_priv
= default_flash_free_driver_priv
,
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)