OpenOCD
eneispif.c
Go to the documentation of this file.
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  */
38  FLASH_ID("ISPI flash", 0x03, 0x00, 0x02, 0x20, 0x60, 0x00132085, 0x100, 0x1000, 0x80000);
39 
41  bool probed;
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)
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 
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 */
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");
171  }
172 
173  if (last < first || last >= bank->num_sectors) {
174  LOG_ERROR("Flash sector invalid");
176  }
177 
178  if (!(eneispif_info->probed)) {
179  LOG_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)
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");
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 
265  target_write_buffer(target, eneispif_info->ctrl_base + ISPIDAT, cur_count, buffer);
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");
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 
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 
397 {
398  /* Nothing to do. Protection is only handled in SW. */
399  return ERROR_OK;
400 }
401 
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 
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 };
void command_print(struct command_invocation *cmd, const char *format,...)
Definition: command.c:443
#define CMD_ARGV
Use this macro to access the arguments for the command being handled, rather than accessing the varia...
Definition: command.h:156
#define COMMAND_PARSE_ADDRESS(in, out)
Definition: command.h:452
#define ERROR_COMMAND_SYNTAX_ERROR
Definition: command.h:402
#define CMD_ARGC
Use this macro to access the number of arguments for the command being handled, rather than accessing...
Definition: command.h:151
#define ISPIADDR
Definition: eneispif.c:21
static int eneispif_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
Definition: eneispif.c:210
#define CFG_READ
Definition: eneispif.c:28
#define CFG_WRITE
Definition: eneispif.c:29
const struct flash_driver eneispif_flash
Definition: eneispif.c:419
struct flash_device ene_flash_device
Definition: eneispif.c:37
#define ISPICFG
Definition: eneispif.c:19
static int eneispif_probe(struct flash_bank *bank)
Definition: eneispif.c:329
#define ISPISTS_BUSY
Definition: eneispif.c:25
static int eneispif_erase(struct flash_bank *bank, unsigned int first, unsigned int last)
Definition: eneispif.c:160
#define ISPISTS
Definition: eneispif.c:20
static int eneispi_erase_sector(struct flash_bank *bank, int sector)
Definition: eneispif.c:129
static int eneispif_read_flash_id(struct flash_bank *bank, uint32_t *id)
Definition: eneispif.c:288
#define ISPIDAT
Definition: eneispif.c:23
FLASH_BANK_COMMAND_HANDLER(eneispif_flash_bank_command)
Definition: eneispif.c:47
static int eneispif_protect(struct flash_bank *bank, int set, unsigned int first, unsigned int last)
Definition: eneispif.c:202
static int eneispif_wait(struct flash_bank *bank)
Definition: eneispif.c:106
static int get_eneispif_info(struct flash_bank *bank, struct command_invocation *cmd)
Definition: eneispif.c:402
#define ISPICMD
Definition: eneispif.c:22
static int eneispif_write_reg(struct flash_bank *bank, target_addr_t address, uint32_t value)
Definition: eneispif.c:90
static int eneispif_read_reg(struct flash_bank *bank, uint32_t *value, target_addr_t address)
Definition: eneispif.c:74
#define ISPI_CTRL_BASE
Definition: eneispif.c:31
static int eneispif_protect_check(struct flash_bank *bank)
Definition: eneispif.c:396
static int eneispif_auto_probe(struct flash_bank *bank)
Definition: eneispif.c:388
uint8_t bank
Definition: esirisc.c:135
#define ERROR_FLASH_OPER_UNSUPPORTED
Definition: flash/common.h:36
#define ERROR_FLASH_SECTOR_INVALID
Definition: flash/common.h:29
#define ERROR_FLASH_BANK_NOT_PROBED
Definition: flash/common.h:35
int default_flash_blank_check(struct flash_bank *bank)
Provides default erased-bank check handling.
int default_flash_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
Provides default read implementation for flash memory.
void default_flash_free_driver_priv(struct flash_bank *bank)
Deallocates bank->driver_priv.
static int64_t start
Definition: log.c:42
#define LOG_WARNING(expr ...)
Definition: log.h:129
#define ERROR_FAIL
Definition: log.h:170
#define LOG_ERROR(expr ...)
Definition: log.h:132
#define LOG_INFO(expr ...)
Definition: log.h:126
#define LOG_DEBUG(expr ...)
Definition: log.h:109
#define ERROR_OK
Definition: log.h:164
Upper level NOR flash interfaces.
char id[RTT_CB_MAX_ID_LENGTH]
Control block identifier.
Definition: rtt/rtt.c:32
#define FLASH_ID(n, re, qr, pp, es, ces, id, psize, ssize, size)
Definition: spi.h:33
#define SPIFLASH_READ_ID
Definition: spi.h:72
#define SPIFLASH_WRITE_ENABLE
Definition: spi.h:75
#define SPIFLASH_DEF_PAGESIZE
Definition: spi.h:82
When run_command is called, a new instance will be created on the stack, filled with the proper value...
Definition: command.h:76
const struct flash_device * dev
Definition: eneispif.c:44
uint32_t dev_id
Definition: eneispif.c:43
target_addr_t ctrl_base
Definition: eneispif.c:42
Provides details of a flash bank, available either on-chip or through a major interface.
Definition: nor/core.h:75
uint32_t sectorsize
Definition: spi.h:29
const char * name
Definition: spi.h:21
uint32_t pagesize
Definition: spi.h:28
uint32_t size_in_bytes
Definition: spi.h:30
uint8_t pprog_cmd
Definition: spi.h:24
uint8_t erase_cmd
Definition: spi.h:25
Provides the implementation-independent structure that defines all of the callbacks required by OpenO...
Definition: nor/driver.h:39
const char * name
Gives a human-readable name of this flash driver, This field is used to select and initialize the dri...
Definition: nor/driver.h:44
Describes the geometry and status of a single flash sector within a flash bank.
Definition: nor/core.h:28
int is_erased
Indication of erasure status: 0 = not erased, 1 = erased, other = unknown.
Definition: nor/core.h:42
uint32_t offset
Bus offset from start of the flash chip (in bytes).
Definition: nor/core.h:30
int is_protected
Indication of protection status: 0 = unprotected/unlocked, 1 = protected/locked, other = unknown.
Definition: nor/core.h:55
uint32_t size
Number of bytes in this flash sector.
Definition: nor/core.h:32
Definition: target.h:116
enum target_state state
Definition: target.h:157
int target_write_buffer(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer)
Definition: target.c:2342
int target_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer)
Definition: target.c:2407
int target_write_u32(struct target *target, target_addr_t address, uint32_t value)
Definition: target.c:2641
int target_read_u32(struct target *target, target_addr_t address, uint32_t *value)
Definition: target.c:2550
#define ERROR_TARGET_NOT_HALTED
Definition: target.h:790
@ TARGET_HALTED
Definition: target.h:56
#define ERROR_TARGET_TIMEOUT
Definition: target.h:789
int64_t timeval_ms(void)
#define TARGET_ADDR_FMT
Definition: types.h:342
uint64_t target_addr_t
Definition: types.h:335
uint8_t status[4]
Definition: vdebug.c:17
uint8_t cmd
Definition: vdebug.c:1
uint8_t offset[4]
Definition: vdebug.c:9
uint8_t count[4]
Definition: vdebug.c:22