jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / flash / nor / eneispif.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /*
4 * Copyright (c) 2024 ENE Technology Inc.
5 * steven@ene.com.tw
6 */
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
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>
18
19 #define ISPICFG 0x0000
20 #define ISPISTS 0x0004
21 #define ISPIADDR 0x0008
22 #define ISPICMD 0x000C
23 #define ISPIDAT 0x0100
24
25 #define ISPISTS_BUSY BIT(0)
26 #define STATUS1_QE BIT(1)
27
28 #define CFG_READ 0x372
29 #define CFG_WRITE 0x371
30
31 #define ISPI_CTRL_BASE 0x50101000
32
33 /* name read qread page erase chip device_id page erase flash
34 * _cmd _cmd _prog _cmd* _erase size size* size
35 * _cmd _cmd
36 */
37 struct flash_device ene_flash_device =
38 FLASH_ID("ISPI flash", 0x03, 0x00, 0x02, 0x20, 0x60, 0x00132085, 0x100, 0x1000, 0x80000);
39
40 struct eneispif_flash_bank {
41 bool probed;
42 target_addr_t ctrl_base;
43 uint32_t dev_id;
44 const struct flash_device *dev;
45 };
46
47 FLASH_BANK_COMMAND_HANDLER(eneispif_flash_bank_command)
48 {
49 struct eneispif_flash_bank *eneispif_info;
50
51 LOG_DEBUG("%s", __func__);
52
53 if (CMD_ARGC < 6)
54 return ERROR_COMMAND_SYNTAX_ERROR;
55
56 eneispif_info = malloc(sizeof(struct eneispif_flash_bank));
57 if (!eneispif_info) {
58 LOG_ERROR("not enough memory");
59 return ERROR_FAIL;
60 }
61
62 bank->driver_priv = eneispif_info;
63 eneispif_info->probed = false;
64 eneispif_info->ctrl_base = ISPI_CTRL_BASE;
65 if (CMD_ARGC >= 7) {
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);
69 }
70
71 return ERROR_OK;
72 }
73
74 static int eneispif_read_reg(struct flash_bank *bank, uint32_t *value, target_addr_t address)
75 {
76 struct target *target = bank->target;
77 struct eneispif_flash_bank *eneispif_info = bank->driver_priv;
78
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);
83 return result;
84 }
85 LOG_DEBUG("Read address " TARGET_ADDR_FMT " = 0x%" PRIx32,
86 eneispif_info->ctrl_base + address, *value);
87 return ERROR_OK;
88 }
89
90 static int eneispif_write_reg(struct flash_bank *bank, target_addr_t address, uint32_t value)
91 {
92 struct target *target = bank->target;
93 struct eneispif_flash_bank *eneispif_info = bank->driver_priv;
94
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);
101 return result;
102 }
103 return ERROR_OK;
104 }
105
106 static int eneispif_wait(struct flash_bank *bank)
107 {
108 int64_t start = timeval_ms();
109
110 while (1) {
111 uint32_t status;
112
113 if (eneispif_read_reg(bank, &status, ISPISTS) != ERROR_OK)
114 return ERROR_FAIL;
115
116 if (!(status & ISPISTS_BUSY))
117 break;
118
119 int64_t now = timeval_ms();
120 if (now - start > 1000) {
121 LOG_ERROR("Busy more than 1000ms.");
122 return ERROR_TARGET_TIMEOUT;
123 }
124 }
125
126 return ERROR_OK;
127 }
128
129 static int eneispi_erase_sector(struct flash_bank *bank, int sector)
130 {
131 int retval = ERROR_OK;
132 struct eneispif_flash_bank *eneispif_info = bank->driver_priv;
133 uint32_t offset;
134 uint32_t conf;
135
136 retval = eneispif_read_reg(bank, &conf, ISPICFG);
137 if (retval != ERROR_OK)
138 return retval;
139
140 offset = bank->sectors[sector].offset;
141 retval = eneispif_write_reg(bank, ISPIADDR, offset); /* Address */
142 if (retval != ERROR_OK)
143 goto done;
144
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)
149 goto done;
150
151 retval = eneispif_wait(bank);
152 if (retval != ERROR_OK)
153 goto done;
154
155 done:
156 eneispif_write_reg(bank, ISPICFG, conf); /* restore */
157 return retval;
158 }
159
160 static int eneispif_erase(struct flash_bank *bank, unsigned int first, unsigned int last)
161 {
162 struct target *target = bank->target;
163 struct eneispif_flash_bank *eneispif_info = bank->driver_priv;
164 int retval = ERROR_OK;
165
166 LOG_DEBUG("%s: from sector %u to sector %u", __func__, first, last);
167
168 if (target->state != TARGET_HALTED) {
169 LOG_ERROR("Target not halted");
170 return ERROR_TARGET_NOT_HALTED;
171 }
172
173 if (last < first || last >= bank->num_sectors) {
174 LOG_ERROR("Flash sector invalid");
175 return ERROR_FLASH_SECTOR_INVALID;
176 }
177
178 if (!(eneispif_info->probed)) {
179 LOG_ERROR("Flash bank not probed");
180 return ERROR_FLASH_BANK_NOT_PROBED;
181 }
182
183 for (unsigned int sector = first; sector <= last; sector++) {
184 if (bank->sectors[sector].is_protected) {
185 LOG_ERROR("Flash sector %u protected", sector);
186 return ERROR_FAIL;
187 }
188 }
189
190 if (eneispif_info->dev->erase_cmd == 0x00)
191 return ERROR_FLASH_OPER_UNSUPPORTED;
192
193 for (unsigned int sector = first; sector <= last; sector++) {
194 retval = eneispi_erase_sector(bank, sector);
195 if (retval != ERROR_OK)
196 break;
197 }
198
199 return retval;
200 }
201
202 static int eneispif_protect(struct flash_bank *bank, int set, unsigned int first, unsigned int last)
203 {
204 for (unsigned int sector = first; sector <= last; sector++)
205 bank->sectors[sector].is_protected = set;
206
207 return ERROR_OK;
208 }
209
210 static int eneispif_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset,
211 uint32_t count)
212 {
213 struct target *target = bank->target;
214 struct eneispif_flash_bank *eneispif_info = bank->driver_priv;
215 uint32_t page_size;
216 uint32_t conf;
217 int retval = ERROR_OK;
218
219 LOG_DEBUG("bank->size=0x%x offset=0x%08" PRIx32 " count=0x%08" PRIx32, bank->size, offset,
220 count);
221
222 if (target->state != TARGET_HALTED) {
223 LOG_ERROR("Target not halted");
224 return ERROR_TARGET_NOT_HALTED;
225 }
226
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;
230 }
231
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);
240 return ERROR_FAIL;
241 }
242 }
243
244 retval = eneispif_read_reg(bank, &conf, ISPICFG);
245 if (retval != ERROR_OK)
246 return retval;
247
248 eneispif_write_reg(bank, ISPICFG, CFG_WRITE); // Cmmmand enable
249
250 /* If no valid page_size, use reasonable default. */
251 page_size =
252 eneispif_info->dev->pagesize ? eneispif_info->dev->pagesize : SPIFLASH_DEF_PAGESIZE;
253 uint32_t page_offset = offset % page_size;
254
255 while (count > 0) {
256 uint32_t cur_count;
257
258 /* clip block at page boundary */
259 if (page_offset + count > page_size)
260 cur_count = page_size - page_offset;
261 else
262 cur_count = count;
263
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)
270 goto err;
271
272 page_offset = 0;
273 buffer += cur_count;
274 offset += cur_count;
275 count -= cur_count;
276 retval = eneispif_wait(bank);
277 if (retval != ERROR_OK)
278 goto err;
279 }
280
281 err:
282 eneispif_write_reg(bank, ISPICFG, conf); /* restore */
283 return retval;
284 }
285
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)
289 {
290 struct eneispif_flash_bank *eneispif_info = bank->driver_priv;
291 struct target *target = bank->target;
292 int retval;
293 uint32_t conf, value;
294 uint8_t buffer[4];
295
296 if (target->state != TARGET_HALTED) {
297 LOG_ERROR("Target not halted");
298 return ERROR_TARGET_NOT_HALTED;
299 }
300
301 retval = eneispif_read_reg(bank, &conf, ISPICFG);
302 if (retval != ERROR_OK)
303 return retval;
304
305 LOG_DEBUG("ISPCFG = (0x%08" PRIx32 ")", conf);
306
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)
311 goto done;
312
313 retval = eneispif_wait(bank);
314 if (retval != ERROR_OK)
315 goto done;
316
317 retval = target_read_buffer(target, eneispif_info->ctrl_base + ISPIDAT, 3, buffer);
318 if (retval != ERROR_OK)
319 goto done;
320 value = (buffer[2] << 16) | (buffer[1] << 8) | buffer[0];
321 LOG_DEBUG("ISPDAT = (0x%08" PRIx32 ")", value);
322
323 *id = value;
324 done:
325 eneispif_write_reg(bank, ISPICFG, conf); // restore
326 return retval;
327 }
328
329 static int eneispif_probe(struct flash_bank *bank)
330 {
331 struct eneispif_flash_bank *eneispif_info = bank->driver_priv;
332 struct flash_sector *sectors;
333 uint32_t id;
334 int retval;
335 uint32_t sectorsize;
336
337 if (eneispif_info->probed)
338 free(bank->sectors);
339
340 eneispif_info->probed = false;
341
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);
345
346 eneispif_write_reg(bank, ISPICFG, CFG_READ); /* RAM map enable */
347
348 retval = eneispif_read_flash_id(bank, &id);
349 if (retval != ERROR_OK)
350 return retval;
351
352 eneispif_info->dev_id = id;
353 eneispif_info->dev = &ene_flash_device;
354
355 LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")", eneispif_info->dev->name,
356 eneispif_info->dev_id);
357
358 /* Set correct size value */
359 bank->size = eneispif_info->dev->size_in_bytes;
360
361 if (bank->size <= (1UL << 16))
362 LOG_WARNING("device needs 2-byte addresses - not implemented");
363
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;
367
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);
371 if (!sectors) {
372 LOG_ERROR("not enough memory");
373 return ERROR_FAIL;
374 }
375
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;
381 }
382
383 bank->sectors = sectors;
384 eneispif_info->probed = true;
385 return ERROR_OK;
386 }
387
388 static int eneispif_auto_probe(struct flash_bank *bank)
389 {
390 struct eneispif_flash_bank *eneispif_info = bank->driver_priv;
391 if (eneispif_info->probed)
392 return ERROR_OK;
393 return eneispif_probe(bank);
394 }
395
396 static int eneispif_protect_check(struct flash_bank *bank)
397 {
398 /* Nothing to do. Protection is only handled in SW. */
399 return ERROR_OK;
400 }
401
402 static int get_eneispif_info(struct flash_bank *bank, struct command_invocation *cmd)
403 {
404 struct eneispif_flash_bank *eneispif_info = bank->driver_priv;
405
406 if (!(eneispif_info->probed)) {
407 command_print(cmd, "ENE ISPI flash bank not probed yet.");
408 return ERROR_OK;
409 }
410
411 command_print(cmd,
412 "ENE ISPI flash information:\n"
413 " Device \'%s\' (ID 0x%08" PRIx32 ")",
414 eneispif_info->dev->name, eneispif_info->dev_id);
415
416 return ERROR_OK;
417 }
418
419 const struct flash_driver eneispif_flash = {
420 .name = "eneispif",
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,
433 };

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)