1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 /***************************************************************************
4 * Copyright (C) 2018 by Simon Qian *
5 * SimonQian@SimonQian.com *
6 ***************************************************************************/
13 #include <helper/binarybuffer.h>
14 #include <target/algorithm.h>
15 #include <target/armv7m.h>
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
22 /* w600 register locations */
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)
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)
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)
41 #define QFLASH_START (1ul << 28)
42 #define QFLASH_ADDR(addr) (((addr) & 0xFFFFF) << 8)
43 #define QFLASH_CRM(crm) (((crm) & 0xFF) << 0)
45 struct w600_flash_param
{
50 static const struct w600_flash_param w600_param
[] = {
78 struct w600_flash_bank
{
82 const struct w600_flash_param
*param
;
83 uint32_t register_base
;
84 uint32_t user_bank_size
;
87 /* flash bank w600 <base> <size> 0 0 <target#>
89 FLASH_BANK_COMMAND_HANDLER(w600_flash_bank_command
)
91 struct w600_flash_bank
*w600_info
;
94 return ERROR_COMMAND_SYNTAX_ERROR
;
96 w600_info
= malloc(sizeof(struct w600_flash_bank
));
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
;
106 static int w600_get_delay(struct flash_bank
*bank
, uint32_t cmd
)
108 struct w600_flash_bank
*w600_info
= bank
->driver_priv
;
110 if (!w600_info
->param
)
115 return w600_info
->param
->se_delay
;
117 return w600_info
->param
->pp_delay
;
123 static int w600_start_do(struct flash_bank
*bank
, uint32_t cmd
, uint32_t addr
,
124 uint32_t len
, int timeout
)
126 struct target
*target
= bank
->target
;
129 cmd
|= QFLASH_CMD_DATALEN(len
- 1) | QFLASH_CMD_DATA
;
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
)
136 addr
|= QFLASH_START
;
137 LOG_DEBUG("WRITE START: 0x%08" PRIx32
"", addr
);
138 retval
= target_write_u32(target
, QFLASH_CMD_START
, addr
);
139 if (retval
!= ERROR_OK
)
142 LOG_DEBUG("DELAY %dms", timeout
);
143 alive_sleep(timeout
);
148 LOG_DEBUG("READ START...");
149 retval
= target_read_u32(target
, QFLASH_CMD_START
, &status
);
150 if (retval
== ERROR_OK
)
151 LOG_DEBUG("READ START: 0x%08" PRIx32
"", status
);
153 LOG_DEBUG("READ START FAILED");
155 if ((retval
!= ERROR_OK
) || (status
& QFLASH_START
)) {
157 LOG_ERROR("timed out waiting for flash");
168 static int w600_write_enable(struct flash_bank
*bank
)
170 return w600_start_do(bank
, QFLASH_CMD_WREN
, 0, 0, 0);
173 static int w600_write_disable(struct flash_bank
*bank
)
175 return w600_start_do(bank
, QFLASH_CMD_WRDI
, 0, 0, 0);
178 static int w600_start(struct flash_bank
*bank
, uint32_t cmd
, uint32_t addr
,
181 int retval
= w600_write_enable(bank
);
182 if (retval
!= ERROR_OK
)
185 retval
= w600_start_do(bank
, cmd
, addr
, len
, w600_get_delay(bank
, cmd
));
186 if (retval
!= ERROR_OK
)
189 retval
= w600_write_disable(bank
);
190 if (retval
!= ERROR_OK
)
196 static int w600_erase(struct flash_bank
*bank
, unsigned int first
,
199 int retval
= ERROR_OK
;
201 if (bank
->target
->state
!= TARGET_HALTED
) {
202 LOG_ERROR("Target not halted");
203 return ERROR_TARGET_NOT_HALTED
;
205 if (first
< W600_FLASH_PROTECT_SIZE
/ W600_FLASH_SECSIZE
) {
206 LOG_ERROR("can not erase protected area");
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
)
220 static int w600_write(struct flash_bank
*bank
, const uint8_t *buffer
,
221 uint32_t offset
, uint32_t count
)
223 struct target
*target
= bank
->target
;
224 int retval
= ERROR_OK
;
226 if (bank
->target
->state
!= TARGET_HALTED
) {
227 LOG_ERROR("Target not halted");
228 return ERROR_TARGET_NOT_HALTED
;
231 if ((offset
% W600_FLASH_PAGESIZE
) != 0) {
232 LOG_WARNING("offset 0x%" PRIx32
" breaks required %d-byte alignment",
233 offset
, W600_FLASH_PAGESIZE
);
234 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
237 if ((count
% W600_FLASH_PAGESIZE
) != 0) {
238 LOG_WARNING("count 0x%" PRIx32
" breaks required %d-byte alignment",
239 offset
, W600_FLASH_PAGESIZE
);
240 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
244 retval
= target_write_buffer(target
, QFLASH_BUFFER
, W600_FLASH_PAGESIZE
, buffer
);
245 if (retval
!= ERROR_OK
)
248 retval
= w600_start(bank
, QFLASH_CMD_PP
, QFLASH_ADDR(offset
),
249 W600_FLASH_PAGESIZE
);
250 if (retval
!= ERROR_OK
)
253 count
-= W600_FLASH_PAGESIZE
;
254 offset
+= W600_FLASH_PAGESIZE
;
255 buffer
+= W600_FLASH_PAGESIZE
;
261 static int w600_get_flash_id(struct flash_bank
*bank
, uint32_t *flash_id
)
263 struct target
*target
= bank
->target
;
265 int retval
= w600_start(bank
, QFLASH_CMD_RDID
, 0, 4);
266 if (retval
!= ERROR_OK
)
269 return target_read_u32(target
, QFLASH_BUFFER
, flash_id
);
272 static int w600_probe(struct flash_bank
*bank
)
274 struct w600_flash_bank
*w600_info
= bank
->driver_priv
;
279 w600_info
->probed
= false;
281 /* read stm32 device id register */
282 int retval
= w600_get_flash_id(bank
, &flash_id
);
283 if (retval
!= ERROR_OK
)
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
];
295 if (!w600_info
->param
) {
296 LOG_ERROR("flash_id not supported for w600");
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
;
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");
312 flash_size
= 1 << flash_size
;
315 LOG_INFO("flash size = %" PRIu32
"kbytes", flash_size
/ 1024);
317 /* calculate numbers of pages */
318 size_t num_pages
= flash_size
/ W600_FLASH_SECSIZE
;
320 /* check that calculation result makes sense */
321 assert(num_pages
> 0);
324 bank
->sectors
= NULL
;
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
);
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
);
341 w600_info
->probed
= true;
346 static int w600_auto_probe(struct flash_bank
*bank
)
348 struct w600_flash_bank
*w600_info
= bank
->driver_priv
;
349 if (w600_info
->probed
)
351 return w600_probe(bank
);
354 static int get_w600_info(struct flash_bank
*bank
, struct command_invocation
*cmd
)
358 /* read w600 device id register */
359 int retval
= w600_get_flash_id(bank
, &flash_id
);
360 if (retval
!= ERROR_OK
)
363 command_print_sameline(cmd
, "w600 : 0x%08" PRIx32
"", flash_id
);
367 const struct flash_driver w600_flash
= {
369 .flash_bank_command
= w600_flash_bank_command
,
372 .read
= default_flash_read
,
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
,