OpenOCD
w600.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  * Copyright (C) 2018 by Simon Qian *
5  * SimonQian@SimonQian.com *
6  ***************************************************************************/
7 
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11 
12 #include "imp.h"
13 #include <helper/binarybuffer.h>
14 #include <target/algorithm.h>
15 #include <target/armv7m.h>
16 
17 #define W600_FLASH_SECSIZE 0x1000
18 #define W600_FLASH_PAGESIZE 0x100
19 #define W600_FLASH_BASE 0x08000000
20 #define W600_FLASH_PROTECT_SIZE 0x2000
21 
22 /* w600 register locations */
23 
24 #define QFLASH_REGBASE 0X40002000
25 #define QFLASH_CMD_INFO (QFLASH_REGBASE + 0)
26 #define QFLASH_CMD_START (QFLASH_REGBASE + 4)
27 #define QFLASH_BUFFER (QFLASH_REGBASE + 0X200)
28 
29 #define QFLASH_CMD_READ (1ul << 14)
30 #define QFLASH_CMD_WRITE 0
31 #define QFLASH_CMD_ADDR (1ul << 31)
32 #define QFLASH_CMD_DATA (1ul << 15)
33 #define QFLASH_CMD_DATALEN(len) (((len) & 0x3FF) << 16)
34 
35 #define QFLASH_CMD_RDID (QFLASH_CMD_READ | 0x9F)
36 #define QFLASH_CMD_WREN (QFLASH_CMD_WRITE | 0x06)
37 #define QFLASH_CMD_WRDI (QFLASH_CMD_WRITE | 0x04)
38 #define QFLASH_CMD_SE (QFLASH_CMD_WRITE | QFLASH_CMD_ADDR | (1ul << 11) | 0x20)
39 #define QFLASH_CMD_PP (QFLASH_CMD_WRITE | QFLASH_CMD_ADDR | (1ul << 12) | 0x02)
40 
41 #define QFLASH_START (1ul << 28)
42 #define QFLASH_ADDR(addr) (((addr) & 0xFFFFF) << 8)
43 #define QFLASH_CRM(crm) (((crm) & 0xFF) << 0)
44 
46  uint8_t id;
47  uint8_t se_delay;
48  uint8_t pp_delay;
49 };
50 static const struct w600_flash_param w600_param[] = {
51  {
52  .id = 0x85,
53  .se_delay = 8,
54  .pp_delay = 2,
55  },
56  {
57  .id = 0x1C,
58  .se_delay = 50,
59  .pp_delay = 1,
60  },
61  {
62  .id = 0xC8,
63  .se_delay = 45,
64  .pp_delay = 1,
65  },
66  {
67  .id = 0x0B,
68  .se_delay = 60,
69  .pp_delay = 1,
70  },
71  {
72  .id = 0x68,
73  .se_delay = 50,
74  .pp_delay = 1,
75  },
76 };
77 
79  bool probed;
80 
81  uint32_t id;
82  const struct w600_flash_param *param;
83  uint32_t register_base;
84  uint32_t user_bank_size;
85 };
86 
87 /* flash bank w600 <base> <size> 0 0 <target#>
88  */
89 FLASH_BANK_COMMAND_HANDLER(w600_flash_bank_command)
90 {
91  struct w600_flash_bank *w600_info;
92 
93  if (CMD_ARGC < 6)
95 
96  w600_info = malloc(sizeof(struct w600_flash_bank));
97 
98  bank->driver_priv = w600_info;
99  w600_info->probed = false;
100  w600_info->register_base = QFLASH_REGBASE;
101  w600_info->user_bank_size = bank->size;
102 
103  return ERROR_OK;
104 }
105 
106 static int w600_get_delay(struct flash_bank *bank, uint32_t cmd)
107 {
108  struct w600_flash_bank *w600_info = bank->driver_priv;
109 
110  if (!w600_info->param)
111  return 0;
112 
113  switch (cmd) {
114  case QFLASH_CMD_SE:
115  return w600_info->param->se_delay;
116  case QFLASH_CMD_PP:
117  return w600_info->param->pp_delay;
118  default:
119  return 0;
120  }
121 }
122 
123 static int w600_start_do(struct flash_bank *bank, uint32_t cmd, uint32_t addr,
124  uint32_t len, int timeout)
125 {
126  struct target *target = bank->target;
127 
128  if (len > 0)
129  cmd |= QFLASH_CMD_DATALEN(len - 1) | QFLASH_CMD_DATA;
130 
131  LOG_DEBUG("WRITE CMD: 0x%08" PRIx32 "", cmd);
132  int retval = target_write_u32(target, QFLASH_CMD_INFO, cmd);
133  if (retval != ERROR_OK)
134  return retval;
135 
136  addr |= QFLASH_START;
137  LOG_DEBUG("WRITE START: 0x%08" PRIx32 "", addr);
139  if (retval != ERROR_OK)
140  return retval;
141 
142  LOG_DEBUG("DELAY %dms", timeout);
144 
145  int retry = 100;
146  uint32_t status;
147  for (;;) {
148  LOG_DEBUG("READ START...");
150  if (retval == ERROR_OK)
151  LOG_DEBUG("READ START: 0x%08" PRIx32 "", status);
152  else
153  LOG_DEBUG("READ START FAILED");
154 
155  if ((retval != ERROR_OK) || (status & QFLASH_START)) {
156  if (retry-- <= 0) {
157  LOG_ERROR("timed out waiting for flash");
158  return ERROR_FAIL;
159  }
160  continue;
161  }
162  break;
163  }
164 
165  return retval;
166 }
167 
168 static int w600_write_enable(struct flash_bank *bank)
169 {
170  return w600_start_do(bank, QFLASH_CMD_WREN, 0, 0, 0);
171 }
172 
173 static int w600_write_disable(struct flash_bank *bank)
174 {
175  return w600_start_do(bank, QFLASH_CMD_WRDI, 0, 0, 0);
176 }
177 
178 static int w600_start(struct flash_bank *bank, uint32_t cmd, uint32_t addr,
179  uint32_t len)
180 {
181  int retval = w600_write_enable(bank);
182  if (retval != ERROR_OK)
183  return retval;
184 
185  retval = w600_start_do(bank, cmd, addr, len, w600_get_delay(bank, cmd));
186  if (retval != ERROR_OK)
187  return retval;
188 
189  retval = w600_write_disable(bank);
190  if (retval != ERROR_OK)
191  return retval;
192 
193  return retval;
194 }
195 
196 static int w600_erase(struct flash_bank *bank, unsigned int first,
197  unsigned int last)
198 {
199  int retval = ERROR_OK;
200 
201  if (bank->target->state != TARGET_HALTED) {
202  LOG_ERROR("Target not halted");
204  }
206  LOG_ERROR("can not erase protected area");
207  return ERROR_FAIL;
208  }
209 
210  for (unsigned int i = first; i <= last; i++) {
211  retval = w600_start(bank, QFLASH_CMD_SE,
212  QFLASH_ADDR(bank->sectors[i].offset), 0);
213  if (retval != ERROR_OK)
214  break;
215  }
216 
217  return retval;
218 }
219 
220 static int w600_write(struct flash_bank *bank, const uint8_t *buffer,
221  uint32_t offset, uint32_t count)
222 {
223  struct target *target = bank->target;
224  int retval = ERROR_OK;
225 
226  if (bank->target->state != TARGET_HALTED) {
227  LOG_ERROR("Target not halted");
229  }
230 
231  if ((offset % W600_FLASH_PAGESIZE) != 0) {
232  LOG_WARNING("offset 0x%" PRIx32 " breaks required %d-byte alignment",
235  }
236 
237  if ((count % W600_FLASH_PAGESIZE) != 0) {
238  LOG_WARNING("count 0x%" PRIx32 " breaks required %d-byte alignment",
241  }
242 
243  while (count > 0) {
245  if (retval != ERROR_OK)
246  break;
247 
250  if (retval != ERROR_OK)
251  break;
252 
256  }
257 
258  return retval;
259 }
260 
261 static int w600_get_flash_id(struct flash_bank *bank, uint32_t *flash_id)
262 {
263  struct target *target = bank->target;
264 
265  int retval = w600_start(bank, QFLASH_CMD_RDID, 0, 4);
266  if (retval != ERROR_OK)
267  return retval;
268 
269  return target_read_u32(target, QFLASH_BUFFER, flash_id);
270 }
271 
272 static int w600_probe(struct flash_bank *bank)
273 {
274  struct w600_flash_bank *w600_info = bank->driver_priv;
275  uint32_t flash_size;
276  uint32_t flash_id;
277  size_t i;
278 
279  w600_info->probed = false;
280 
281  /* read stm32 device id register */
282  int retval = w600_get_flash_id(bank, &flash_id);
283  if (retval != ERROR_OK)
284  return retval;
285 
286  LOG_INFO("flash_id id = 0x%08" PRIx32 "", flash_id);
287  w600_info->id = flash_id;
288  w600_info->param = NULL;
289  for (i = 0; i < ARRAY_SIZE(w600_param); i++) {
290  if (w600_param[i].id == (flash_id & 0xFF)) {
291  w600_info->param = &w600_param[i];
292  break;
293  }
294  }
295  if (!w600_info->param) {
296  LOG_ERROR("flash_id not supported for w600");
297  return ERROR_FAIL;
298  }
299 
300  /* if the user sets the size manually then ignore the probed value
301  * this allows us to work around devices that have a invalid flash size register value */
302  if (w600_info->user_bank_size) {
303  LOG_INFO("ignoring flash probed value, using configured bank size");
304  flash_size = w600_info->user_bank_size;
305  } else {
306  flash_size = ((flash_id & 0xFFFFFF) >> 16) & 0xFF;
307  if ((flash_size != 0x14) && (flash_size != 0x13)) {
308  LOG_ERROR("w600 flash size failed, probe inaccurate");
309  return ERROR_FAIL;
310  }
311 
312  flash_size = 1 << flash_size;
313  }
314 
315  LOG_INFO("flash size = %" PRIu32 " KiB", flash_size / 1024);
316 
317  /* calculate numbers of pages */
318  size_t num_pages = flash_size / W600_FLASH_SECSIZE;
319 
320  /* check that calculation result makes sense */
321  assert(num_pages > 0);
322 
323  free(bank->sectors);
324  bank->sectors = NULL;
325 
326  bank->base = W600_FLASH_BASE;
327  bank->size = num_pages * W600_FLASH_SECSIZE;
328  bank->num_sectors = num_pages;
329  bank->write_start_alignment = W600_FLASH_PAGESIZE;
330  bank->write_end_alignment = W600_FLASH_PAGESIZE;
331  bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
332 
333  for (i = 0; i < num_pages; i++) {
334  bank->sectors[i].offset = i * W600_FLASH_SECSIZE;
335  bank->sectors[i].size = W600_FLASH_SECSIZE;
336  bank->sectors[i].is_erased = -1;
337  /* offset 0 to W600_FLASH_PROTECT_SIZE should be protected */
338  bank->sectors[i].is_protected = (i < W600_FLASH_PROTECT_SIZE / W600_FLASH_SECSIZE);
339  }
340 
341  w600_info->probed = true;
342 
343  return ERROR_OK;
344 }
345 
346 static int w600_auto_probe(struct flash_bank *bank)
347 {
348  struct w600_flash_bank *w600_info = bank->driver_priv;
349  if (w600_info->probed)
350  return ERROR_OK;
351  return w600_probe(bank);
352 }
353 
354 static int get_w600_info(struct flash_bank *bank, struct command_invocation *cmd)
355 {
356  uint32_t flash_id;
357 
358  /* read w600 device id register */
359  int retval = w600_get_flash_id(bank, &flash_id);
360  if (retval != ERROR_OK)
361  return retval;
362 
363  command_print_sameline(cmd, "w600 : 0x%08" PRIx32 "", flash_id);
364  return ERROR_OK;
365 }
366 
367 const struct flash_driver w600_flash = {
368  .name = "w600",
369  .flash_bank_command = w600_flash_bank_command,
370  .erase = w600_erase,
371  .write = w600_write,
372  .read = default_flash_read,
373  .probe = w600_probe,
374  .auto_probe = w600_auto_probe,
375  .erase_check = default_flash_blank_check,
376  .info = get_w600_info,
377  .free_driver_priv = default_flash_free_driver_priv,
378 };
Support functions to access arbitrary bits in a byte array.
void command_print_sameline(struct command_invocation *cmd, const char *format,...)
Definition: command.c:450
#define ERROR_COMMAND_SYNTAX_ERROR
Definition: command.h:385
#define CMD_ARGC
Use this macro to access the number of arguments for the command being handled, rather than accessing...
Definition: command.h:150
uint8_t bank
Definition: esirisc.c:135
#define ERROR_FLASH_DST_BREAKS_ALIGNMENT
Definition: flash/common.h:32
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.
void alive_sleep(uint64_t ms)
Definition: log.c:460
#define LOG_WARNING(expr ...)
Definition: log.h:120
#define ERROR_FAIL
Definition: log.h:161
#define LOG_ERROR(expr ...)
Definition: log.h:123
#define LOG_INFO(expr ...)
Definition: log.h:117
#define LOG_DEBUG(expr ...)
Definition: log.h:109
#define ERROR_OK
Definition: log.h:155
uint32_t addr
Definition: nuttx.c:65
When run_command is called, a new instance will be created on the stack, filled with the proper value...
Definition: command.h:76
Provides details of a flash bank, available either on-chip or through a major interface.
Definition: nor/core.h:75
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
Definition: target.h:120
Definition: psoc6.c:84
uint32_t id
Definition: w600.c:81
uint32_t user_bank_size
Definition: w600.c:84
uint32_t register_base
Definition: w600.c:83
bool probed
Definition: w600.c:79
const struct w600_flash_param * param
Definition: w600.c:82
uint8_t id
Definition: w600.c:46
uint8_t pp_delay
Definition: w600.c:48
uint8_t se_delay
Definition: w600.c:47
int target_write_buffer(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer)
Definition: target.c:2408
int target_write_u32(struct target *target, target_addr_t address, uint32_t value)
Definition: target.c:2707
int target_read_u32(struct target *target, target_addr_t address, uint32_t *value)
Definition: target.c:2616
#define ERROR_TARGET_NOT_HALTED
Definition: target.h:792
@ TARGET_HALTED
Definition: target.h:55
#define ARRAY_SIZE(x)
Compute the number of elements of a variable length array.
Definition: types.h:57
#define NULL
Definition: usb.h:16
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
#define QFLASH_ADDR(addr)
Definition: w600.c:42
#define QFLASH_CMD_DATA
Definition: w600.c:32
static int w600_start_do(struct flash_bank *bank, uint32_t cmd, uint32_t addr, uint32_t len, int timeout)
Definition: w600.c:123
#define QFLASH_CMD_INFO
Definition: w600.c:25
#define QFLASH_CMD_DATALEN(len)
Definition: w600.c:33
static int w600_write_enable(struct flash_bank *bank)
Definition: w600.c:168
static int w600_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
Definition: w600.c:220
static int w600_write_disable(struct flash_bank *bank)
Definition: w600.c:173
#define QFLASH_CMD_WRDI
Definition: w600.c:37
static int w600_get_delay(struct flash_bank *bank, uint32_t cmd)
Definition: w600.c:106
static int w600_erase(struct flash_bank *bank, unsigned int first, unsigned int last)
Definition: w600.c:196
static int w600_start(struct flash_bank *bank, uint32_t cmd, uint32_t addr, uint32_t len)
Definition: w600.c:178
FLASH_BANK_COMMAND_HANDLER(w600_flash_bank_command)
Definition: w600.c:89
#define QFLASH_CMD_PP
Definition: w600.c:39
#define W600_FLASH_BASE
Definition: w600.c:19
static const struct w600_flash_param w600_param[]
Definition: w600.c:50
static int w600_get_flash_id(struct flash_bank *bank, uint32_t *flash_id)
Definition: w600.c:261
#define W600_FLASH_PAGESIZE
Definition: w600.c:18
static int w600_probe(struct flash_bank *bank)
Definition: w600.c:272
#define QFLASH_CMD_SE
Definition: w600.c:38
#define W600_FLASH_SECSIZE
Definition: w600.c:17
#define QFLASH_CMD_RDID
Definition: w600.c:35
static int w600_auto_probe(struct flash_bank *bank)
Definition: w600.c:346
#define QFLASH_CMD_START
Definition: w600.c:26
#define QFLASH_BUFFER
Definition: w600.c:27
const struct flash_driver w600_flash
Definition: w600.c:367
#define QFLASH_START
Definition: w600.c:41
#define QFLASH_CMD_WREN
Definition: w600.c:36
static int get_w600_info(struct flash_bank *bank, struct command_invocation *cmd)
Definition: w600.c:354
#define QFLASH_REGBASE
Definition: w600.c:24
#define W600_FLASH_PROTECT_SIZE
Definition: w600.c:20