98c0f46e5f98eb486544e193cf8c7df95de979c8
[fw/openocd] / src / flash / nor / w600.c
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
45 struct w600_flash_param {
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
78 struct w600_flash_bank {
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)
94                 return ERROR_COMMAND_SYNTAX_ERROR;
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);
138         retval = target_write_u32(target, QFLASH_CMD_START, addr);
139         if (retval != ERROR_OK)
140                 return retval;
141
142         LOG_DEBUG("DELAY %dms", timeout);
143         alive_sleep(timeout);
144
145         int retry = 100;
146         uint32_t status;
147         for (;;) {
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);
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");
203                 return ERROR_TARGET_NOT_HALTED;
204         }
205         if (first < W600_FLASH_PROTECT_SIZE / W600_FLASH_SECSIZE) {
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");
228                 return ERROR_TARGET_NOT_HALTED;
229         }
230
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;
235         }
236
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;
241         }
242
243         while (count > 0) {
244                 retval = target_write_buffer(target, QFLASH_BUFFER, W600_FLASH_PAGESIZE, buffer);
245                 if (retval != ERROR_OK)
246                         break;
247
248                 retval = w600_start(bank, QFLASH_CMD_PP, QFLASH_ADDR(offset),
249                                 W600_FLASH_PAGESIZE);
250                 if (retval != ERROR_OK)
251                         break;
252
253                 count -= W600_FLASH_PAGESIZE;
254                 offset += W600_FLASH_PAGESIZE;
255                 buffer += W600_FLASH_PAGESIZE;
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 };