1 /***************************************************************************
2 * Copyright (C) 2018 by Simon Qian *
3 * SimonQian@SimonQian.com *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
24 #include <helper/binarybuffer.h>
25 #include <target/algorithm.h>
26 #include <target/armv7m.h>
28 #define W600_FLASH_SECSIZE 0x1000
29 #define W600_FLASH_PAGESIZE 0x100
30 #define W600_FLASH_BASE 0x08000000
31 #define W600_FLASH_PROTECT_SIZE 0x2000
33 /* w600 register locations */
35 #define QFLASH_REGBASE 0X40002000
36 #define QFLASH_CMD_INFO (QFLASH_REGBASE + 0)
37 #define QFLASH_CMD_START (QFLASH_REGBASE + 4)
38 #define QFLASH_BUFFER (QFLASH_REGBASE + 0X200)
40 #define QFLASH_CMD_READ (1ul << 14)
41 #define QFLASH_CMD_WRITE 0
42 #define QFLASH_CMD_ADDR (1ul << 31)
43 #define QFLASH_CMD_DATA (1ul << 15)
44 #define QFLASH_CMD_DATALEN(len) (((len) & 0x3FF) << 16)
46 #define QFLASH_CMD_RDID (QFLASH_CMD_READ | 0x9F)
47 #define QFLASH_CMD_WREN (QFLASH_CMD_WRITE | 0x06)
48 #define QFLASH_CMD_WRDI (QFLASH_CMD_WRITE | 0x04)
49 #define QFLASH_CMD_SE (QFLASH_CMD_WRITE | QFLASH_CMD_ADDR | (1ul << 11) | 0x20)
50 #define QFLASH_CMD_PP (QFLASH_CMD_WRITE | QFLASH_CMD_ADDR | (1ul << 12) | 0x02)
52 #define QFLASH_START (1ul << 28)
53 #define QFLASH_ADDR(addr) (((addr) & 0xFFFFF) << 8)
54 #define QFLASH_CRM(crm) (((crm) & 0xFF) << 0)
56 struct w600_flash_param {
61 static const struct w600_flash_param w600_param[] = {
89 struct w600_flash_bank {
93 const struct w600_flash_param *param;
94 uint32_t register_base;
95 uint32_t user_bank_size;
98 /* flash bank w600 <base> <size> 0 0 <target#>
100 FLASH_BANK_COMMAND_HANDLER(w600_flash_bank_command)
102 struct w600_flash_bank *w600_info;
105 return ERROR_COMMAND_SYNTAX_ERROR;
107 w600_info = malloc(sizeof(struct w600_flash_bank));
109 bank->driver_priv = w600_info;
110 w600_info->probed = 0;
111 w600_info->register_base = QFLASH_REGBASE;
112 w600_info->user_bank_size = bank->size;
117 static int w600_get_delay(struct flash_bank *bank, uint32_t cmd)
119 struct w600_flash_bank *w600_info = bank->driver_priv;
121 if (!w600_info->param)
126 return w600_info->param->se_delay;
128 return w600_info->param->pp_delay;
134 static int w600_start_do(struct flash_bank *bank, uint32_t cmd, uint32_t addr,
135 uint32_t len, int timeout)
137 struct target *target = bank->target;
140 cmd |= QFLASH_CMD_DATALEN(len - 1) | QFLASH_CMD_DATA;
142 LOG_DEBUG("WRITE CMD: 0x%08" PRIx32 "", cmd);
143 int retval = target_write_u32(target, QFLASH_CMD_INFO, cmd);
144 if (retval != ERROR_OK)
147 addr |= QFLASH_START;
148 LOG_DEBUG("WRITE START: 0x%08" PRIx32 "", addr);
149 retval = target_write_u32(target, QFLASH_CMD_START, addr);
150 if (retval != ERROR_OK)
153 LOG_DEBUG("DELAY %dms", timeout);
154 alive_sleep(timeout);
159 LOG_DEBUG("READ START...");
160 retval = target_read_u32(target, QFLASH_CMD_START, &status);
161 if (retval == ERROR_OK)
162 LOG_DEBUG("READ START: 0x%08" PRIx32 "", status);
164 LOG_DEBUG("READ START FAILED");
166 if ((retval != ERROR_OK) || (status & QFLASH_START)) {
168 LOG_ERROR("timed out waiting for flash");
179 static int w600_write_enable(struct flash_bank *bank)
181 return w600_start_do(bank, QFLASH_CMD_WREN, 0, 0, 0);
184 static int w600_write_disable(struct flash_bank *bank)
186 return w600_start_do(bank, QFLASH_CMD_WRDI, 0, 0, 0);
189 static int w600_start(struct flash_bank *bank, uint32_t cmd, uint32_t addr,
192 int retval = w600_write_enable(bank);
193 if (retval != ERROR_OK)
196 retval = w600_start_do(bank, cmd, addr, len, w600_get_delay(bank, cmd));
197 if (retval != ERROR_OK)
200 retval = w600_write_disable(bank);
201 if (retval != ERROR_OK)
207 static int w600_erase(struct flash_bank *bank, int first, int last)
209 int retval = ERROR_OK;
211 if (bank->target->state != TARGET_HALTED) {
212 LOG_ERROR("Target not halted");
213 return ERROR_TARGET_NOT_HALTED;
215 if (first < W600_FLASH_PROTECT_SIZE / W600_FLASH_SECSIZE) {
216 LOG_ERROR("can not erase protected area");
220 for (int i = first; i <= last; i++) {
221 retval = w600_start(bank, QFLASH_CMD_SE,
222 QFLASH_ADDR(bank->sectors[i].offset), 0);
223 if (retval != ERROR_OK)
230 static int w600_write(struct flash_bank *bank, const uint8_t *buffer,
231 uint32_t offset, uint32_t count)
233 struct target *target = bank->target;
234 int retval = ERROR_OK;
236 if (bank->target->state != TARGET_HALTED) {
237 LOG_ERROR("Target not halted");
238 return ERROR_TARGET_NOT_HALTED;
241 if ((offset % W600_FLASH_PAGESIZE) != 0) {
242 LOG_WARNING("offset 0x%" PRIx32 " breaks required %" PRIu32 "-byte alignment",
243 offset, W600_FLASH_PAGESIZE);
244 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
247 if ((count % W600_FLASH_PAGESIZE) != 0) {
248 LOG_WARNING("count 0x%" PRIx32 " breaks required %" PRIu32 "-byte alignment",
249 offset, W600_FLASH_PAGESIZE);
250 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
254 retval = target_write_buffer(target, QFLASH_BUFFER, W600_FLASH_PAGESIZE, buffer);
255 if (retval != ERROR_OK)
258 retval = w600_start(bank, QFLASH_CMD_PP, QFLASH_ADDR(offset),
259 W600_FLASH_PAGESIZE);
260 if (retval != ERROR_OK)
263 count -= W600_FLASH_PAGESIZE;
264 offset += W600_FLASH_PAGESIZE;
265 buffer += W600_FLASH_PAGESIZE;
271 static int w600_get_flash_id(struct flash_bank *bank, uint32_t *flash_id)
273 struct target *target = bank->target;
275 int retval = w600_start(bank, QFLASH_CMD_RDID, 0, 4);
276 if (retval != ERROR_OK)
279 return target_read_u32(target, QFLASH_BUFFER, flash_id);
282 static int w600_probe(struct flash_bank *bank)
284 struct w600_flash_bank *w600_info = bank->driver_priv;
289 w600_info->probed = 0;
291 /* read stm32 device id register */
292 int retval = w600_get_flash_id(bank, &flash_id);
293 if (retval != ERROR_OK)
296 LOG_INFO("flash_id id = 0x%08" PRIx32 "", flash_id);
297 w600_info->id = flash_id;
298 w600_info->param = NULL;
299 for (i = 0; i < ARRAY_SIZE(w600_param); i++) {
300 if (w600_param[i].id == (flash_id & 0xFF)) {
301 w600_info->param = &w600_param[i];
305 if (!w600_info->param) {
306 LOG_ERROR("flash_id not supported for w600");
310 /* if the user sets the size manually then ignore the probed value
311 * this allows us to work around devices that have a invalid flash size register value */
312 if (w600_info->user_bank_size) {
313 LOG_INFO("ignoring flash probed value, using configured bank size");
314 flash_size = w600_info->user_bank_size;
316 flash_size = ((flash_id & 0xFFFFFF) >> 16) & 0xFF;
317 if ((flash_size != 0x14) && (flash_size != 0x13)) {
318 LOG_ERROR("w600 flash size failed, probe inaccurate");
322 flash_size = 1 << flash_size;
325 LOG_INFO("flash size = %dkbytes", flash_size / 1024);
327 /* calculate numbers of pages */
328 size_t num_pages = flash_size / W600_FLASH_SECSIZE;
330 /* check that calculation result makes sense */
331 assert(num_pages > 0);
335 bank->sectors = NULL;
338 bank->base = W600_FLASH_BASE;
339 bank->size = num_pages * W600_FLASH_SECSIZE;
340 bank->num_sectors = num_pages;
341 bank->write_start_alignment = W600_FLASH_PAGESIZE;
342 bank->write_end_alignment = W600_FLASH_PAGESIZE;
343 bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
345 for (i = 0; i < num_pages; i++) {
346 bank->sectors[i].offset = i * W600_FLASH_SECSIZE;
347 bank->sectors[i].size = W600_FLASH_SECSIZE;
348 bank->sectors[i].is_erased = -1;
349 /* offset 0 to W600_FLASH_PROTECT_SIZE shoule be protected */
350 bank->sectors[i].is_protected = (i < W600_FLASH_PROTECT_SIZE / W600_FLASH_SECSIZE);
353 w600_info->probed = 1;
358 static int w600_auto_probe(struct flash_bank *bank)
360 struct w600_flash_bank *w600_info = bank->driver_priv;
361 if (w600_info->probed)
363 return w600_probe(bank);
366 static int get_w600_info(struct flash_bank *bank, char *buf, int buf_size)
370 /* read w600 device id register */
371 int retval = w600_get_flash_id(bank, &flash_id);
372 if (retval != ERROR_OK)
375 snprintf(buf, buf_size, "w600 : 0x%08" PRIx32 "", flash_id);
379 const struct flash_driver w600_flash = {
381 .flash_bank_command = w600_flash_bank_command,
384 .read = default_flash_read,
386 .auto_probe = w600_auto_probe,
387 .erase_check = default_flash_blank_check,
388 .info = get_w600_info,
389 .free_driver_priv = default_flash_free_driver_priv,