flash/nor: implement flash bank deallocation in drivers with simple alloc
[openocd.git] / src / flash / nor / lpcspifi.c
1 /***************************************************************************
2 * Copyright (C) 2012 by George Harris *
3 * george@luminairecoffee.com *
4 * *
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. *
9 * *
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. *
14 * *
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 ***************************************************************************/
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #include "imp.h"
24 #include "spi.h"
25 #include <jtag/jtag.h>
26 #include <helper/time_support.h>
27 #include <target/algorithm.h>
28 #include <target/armv7m.h>
29
30 /* Offsets from ssp_base into config & data registers */
31 #define SSP_CR0 (0x00) /* Control register 0 */
32 #define SSP_CR1 (0x04) /* Control register 1 */
33 #define SSP_DATA (0x08) /* Data register (TX and RX) */
34 #define SSP_SR (0x0C) /* Status register */
35 #define SSP_CPSR (0x10) /* Clock prescale register */
36
37 /* Status register fields */
38 #define SSP_BSY (0x00000010)
39
40 /* Timeout in ms */
41 #define SSP_CMD_TIMEOUT (100)
42 #define SSP_PROBE_TIMEOUT (100)
43 #define SSP_MAX_TIMEOUT (3000)
44
45 /* Size of the stack to alloc in the working area for the execution of
46 * the ROM spifi_init() function */
47 #define SPIFI_INIT_STACK_SIZE 512
48
49 struct lpcspifi_flash_bank {
50 int probed;
51 uint32_t ssp_base;
52 uint32_t io_base;
53 uint32_t ioconfig_base;
54 uint32_t bank_num;
55 uint32_t max_spi_clock_mhz;
56 const struct flash_device *dev;
57 };
58
59 /* flash_bank lpcspifi <base> <size> <chip_width> <bus_width> <target>
60 */
61 FLASH_BANK_COMMAND_HANDLER(lpcspifi_flash_bank_command)
62 {
63 struct lpcspifi_flash_bank *lpcspifi_info;
64
65 if (CMD_ARGC < 6)
66 return ERROR_COMMAND_SYNTAX_ERROR;
67
68 lpcspifi_info = malloc(sizeof(struct lpcspifi_flash_bank));
69 if (lpcspifi_info == NULL) {
70 LOG_ERROR("not enough memory");
71 return ERROR_FAIL;
72 }
73
74 bank->driver_priv = lpcspifi_info;
75 lpcspifi_info->probed = 0;
76
77 return ERROR_OK;
78 }
79
80 static inline int ioconfig_write_reg(struct target *target, uint32_t ioconfig_base, uint32_t offset, uint32_t value)
81 {
82 return target_write_u32(target, ioconfig_base + offset, value);
83 }
84
85 static inline int ssp_write_reg(struct target *target, uint32_t ssp_base, uint32_t offset, uint32_t value)
86 {
87 return target_write_u32(target, ssp_base + offset, value);
88 }
89
90 static inline int io_write_reg(struct target *target, uint32_t io_base, uint32_t offset, uint32_t value)
91 {
92 return target_write_u32(target, io_base + offset, value);
93 }
94
95 static inline int ssp_read_reg(struct target *target, uint32_t ssp_base, uint32_t offset, uint32_t *value)
96 {
97 return target_read_u32(target, ssp_base + offset, value);
98 }
99
100 static int ssp_setcs(struct target *target, uint32_t io_base, unsigned int value)
101 {
102 return io_write_reg(target, io_base, 0x12ac, value ? 0xffffffff : 0x00000000);
103 }
104
105 /* Poll the SSP busy flag. When this comes back as 0, the transfer is complete
106 * and the controller is idle. */
107 static int poll_ssp_busy(struct target *target, uint32_t ssp_base, int timeout)
108 {
109 int64_t endtime;
110 uint32_t value;
111 int retval;
112
113 retval = ssp_read_reg(target, ssp_base, SSP_SR, &value);
114 if ((retval == ERROR_OK) && (value & SSP_BSY) == 0)
115 return ERROR_OK;
116 else if (retval != ERROR_OK)
117 return retval;
118
119 endtime = timeval_ms() + timeout;
120 do {
121 alive_sleep(1);
122 retval = ssp_read_reg(target, ssp_base, SSP_SR, &value);
123 if ((retval == ERROR_OK) && (value & SSP_BSY) == 0)
124 return ERROR_OK;
125 else if (retval != ERROR_OK)
126 return retval;
127 } while (timeval_ms() < endtime);
128
129 LOG_ERROR("Timeout while polling BSY");
130 return ERROR_FLASH_OPERATION_FAILED;
131 }
132
133 /* Un-initialize the ssp module and initialize the SPIFI module */
134 static int lpcspifi_set_hw_mode(struct flash_bank *bank)
135 {
136 struct target *target = bank->target;
137 struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
138 uint32_t ssp_base = lpcspifi_info->ssp_base;
139 struct armv7m_algorithm armv7m_info;
140 struct working_area *spifi_init_algorithm;
141 struct reg_param reg_params[2];
142 int retval = ERROR_OK;
143
144 LOG_DEBUG("Uninitializing LPC43xx SSP");
145 /* Turn off the SSP module */
146 retval = ssp_write_reg(target, ssp_base, SSP_CR1, 0x00000000);
147 if (retval != ERROR_OK)
148 return retval;
149
150 /* see contrib/loaders/flash/lpcspifi_init.S for src */
151 static const uint8_t spifi_init_code[] = {
152 0x4f, 0xea, 0x00, 0x08, 0xa1, 0xb0, 0x00, 0xaf,
153 0x4f, 0xf4, 0xc0, 0x43, 0xc4, 0xf2, 0x08, 0x03,
154 0x4f, 0xf0, 0xf3, 0x02, 0xc3, 0xf8, 0x8c, 0x21,
155 0x4f, 0xf4, 0xc0, 0x43, 0xc4, 0xf2, 0x08, 0x03,
156 0x4f, 0xf4, 0xc0, 0x42, 0xc4, 0xf2, 0x08, 0x02,
157 0x4f, 0xf4, 0xc0, 0x41, 0xc4, 0xf2, 0x08, 0x01,
158 0x4f, 0xf4, 0xc0, 0x40, 0xc4, 0xf2, 0x08, 0x00,
159 0x4f, 0xf0, 0xd3, 0x04, 0xc0, 0xf8, 0x9c, 0x41,
160 0x20, 0x46, 0xc1, 0xf8, 0x98, 0x01, 0x01, 0x46,
161 0xc2, 0xf8, 0x94, 0x11, 0xc3, 0xf8, 0x90, 0x11,
162 0x4f, 0xf4, 0xc0, 0x43, 0xc4, 0xf2, 0x08, 0x03,
163 0x4f, 0xf0, 0x13, 0x02, 0xc3, 0xf8, 0xa0, 0x21,
164 0x40, 0xf2, 0x18, 0x13, 0xc1, 0xf2, 0x40, 0x03,
165 0x1b, 0x68, 0x1c, 0x68, 0x40, 0xf2, 0xb4, 0x30,
166 0xc1, 0xf2, 0x00, 0x00, 0x4f, 0xf0, 0x03, 0x01,
167 0x4f, 0xf0, 0xc0, 0x02, 0x4f, 0xea, 0x08, 0x03,
168 0xa0, 0x47, 0x00, 0xf0, 0x00, 0xb8, 0x00, 0xbe
169 };
170
171 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
172 armv7m_info.core_mode = ARM_MODE_THREAD;
173
174
175 LOG_DEBUG("Allocating working area for SPIFI init algorithm");
176 /* Get memory for spifi initialization algorithm */
177 retval = target_alloc_working_area(target, sizeof(spifi_init_code)
178 + SPIFI_INIT_STACK_SIZE, &spifi_init_algorithm);
179 if (retval != ERROR_OK) {
180 LOG_ERROR("Insufficient working area to initialize SPIFI "\
181 "module. You must allocate at least %zdB of working "\
182 "area in order to use this driver.",
183 sizeof(spifi_init_code) + SPIFI_INIT_STACK_SIZE
184 );
185
186 return retval;
187 }
188
189 LOG_DEBUG("Writing algorithm to working area at 0x%08" TARGET_PRIxADDR,
190 spifi_init_algorithm->address);
191 /* Write algorithm to working area */
192 retval = target_write_buffer(target,
193 spifi_init_algorithm->address,
194 sizeof(spifi_init_code),
195 spifi_init_code
196 );
197
198 if (retval != ERROR_OK) {
199 target_free_working_area(target, spifi_init_algorithm);
200 return retval;
201 }
202
203 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT); /* spifi clk speed */
204 /* the spifi_init() rom API makes use of the stack */
205 init_reg_param(&reg_params[1], "sp", 32, PARAM_OUT);
206
207 /* For now, the algorithm will set up the SPIFI module
208 * @ the IRC clock speed. In the future, it could be made
209 * a bit smarter to use other clock sources if the user has
210 * already configured them in order to speed up memory-
211 * mapped reads. */
212 buf_set_u32(reg_params[0].value, 0, 32, 12);
213 /* valid stack pointer */
214 buf_set_u32(reg_params[1].value, 0, 32, (spifi_init_algorithm->address +
215 sizeof(spifi_init_code) + SPIFI_INIT_STACK_SIZE) & ~7UL);
216
217 /* Run the algorithm */
218 LOG_DEBUG("Running SPIFI init algorithm");
219 retval = target_run_algorithm(target, 0 , NULL, 2, reg_params,
220 spifi_init_algorithm->address,
221 spifi_init_algorithm->address + sizeof(spifi_init_code) - 2,
222 1000, &armv7m_info);
223
224 if (retval != ERROR_OK)
225 LOG_ERROR("Error executing SPIFI init algorithm");
226
227 target_free_working_area(target, spifi_init_algorithm);
228
229 destroy_reg_param(&reg_params[0]);
230 destroy_reg_param(&reg_params[1]);
231
232 return retval;
233 }
234
235 /* Initialize the ssp module */
236 static int lpcspifi_set_sw_mode(struct flash_bank *bank)
237 {
238 struct target *target = bank->target;
239 struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
240 uint32_t ssp_base = lpcspifi_info->ssp_base;
241 uint32_t io_base = lpcspifi_info->io_base;
242 uint32_t ioconfig_base = lpcspifi_info->ioconfig_base;
243 int retval = ERROR_OK;
244
245 /* Re-initialize SPIFI. There are a couple of errata on this, so this makes
246 sure that nothing's in an unhappy state. */
247 retval = lpcspifi_set_hw_mode(bank);
248
249 /* If we couldn't initialize hardware mode, don't even bother continuing */
250 if (retval != ERROR_OK)
251 return retval;
252
253 /* Initialize the pins */
254 retval = ioconfig_write_reg(target, ioconfig_base, 0x194, 0x00000040);
255 if (retval == ERROR_OK)
256 retval = ioconfig_write_reg(target, ioconfig_base, 0x1a0, 0x00000044);
257 if (retval == ERROR_OK)
258 retval = ioconfig_write_reg(target, ioconfig_base, 0x190, 0x00000040);
259 if (retval == ERROR_OK)
260 retval = ioconfig_write_reg(target, ioconfig_base, 0x19c, 0x000000ed);
261 if (retval == ERROR_OK)
262 retval = ioconfig_write_reg(target, ioconfig_base, 0x198, 0x000000ed);
263 if (retval == ERROR_OK)
264 retval = ioconfig_write_reg(target, ioconfig_base, 0x18c, 0x000000ea);
265
266 /* Set CS high & as an output */
267 if (retval == ERROR_OK)
268 retval = io_write_reg(target, io_base, 0x12ac, 0xffffffff);
269 if (retval == ERROR_OK)
270 retval = io_write_reg(target, io_base, 0x2014, 0x00000800);
271
272 /* Initialize the module */
273 if (retval == ERROR_OK)
274 retval = ssp_write_reg(target, ssp_base, SSP_CR0, 0x00000007);
275 if (retval == ERROR_OK)
276 retval = ssp_write_reg(target, ssp_base, SSP_CR1, 0x00000000);
277 if (retval == ERROR_OK)
278 retval = ssp_write_reg(target, ssp_base, SSP_CPSR, 0x00000008);
279 if (retval == ERROR_OK)
280 retval = ssp_write_reg(target, ssp_base, SSP_CR1, 0x00000002);
281
282 /* If something didn't work out, attempt to return SPIFI to HW mode */
283 if (retval != ERROR_OK)
284 lpcspifi_set_hw_mode(bank);
285
286 return retval;
287 }
288
289 /* Read the status register of the external SPI flash chip. */
290 static int read_status_reg(struct flash_bank *bank, uint32_t *status)
291 {
292 struct target *target = bank->target;
293 struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
294 uint32_t ssp_base = lpcspifi_info->ssp_base;
295 uint32_t io_base = lpcspifi_info->io_base;
296 uint32_t value;
297 int retval = ERROR_OK;
298
299 retval = ssp_setcs(target, io_base, 0);
300 if (retval == ERROR_OK)
301 retval = ssp_write_reg(target, ssp_base, SSP_DATA, SPIFLASH_READ_STATUS);
302 if (retval == ERROR_OK)
303 retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT);
304 if (retval == ERROR_OK)
305 retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value);
306 /* Dummy write to clock in the register */
307 if (retval == ERROR_OK)
308 retval = ssp_write_reg(target, ssp_base, SSP_DATA, 0x00);
309 if (retval == ERROR_OK)
310 retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT);
311 if (retval == ERROR_OK)
312 retval = ssp_setcs(target, io_base, 1);
313
314 if (retval == ERROR_OK)
315 retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value);
316 if (retval == ERROR_OK)
317 *status = value;
318
319 return retval;
320 }
321
322 /* check for BSY bit in flash status register */
323 /* timeout in ms */
324 static int wait_till_ready(struct flash_bank *bank, int timeout)
325 {
326 uint32_t status;
327 int retval;
328 int64_t endtime;
329
330 endtime = timeval_ms() + timeout;
331 do {
332 /* read flash status register */
333 retval = read_status_reg(bank, &status);
334 if (retval != ERROR_OK)
335 return retval;
336
337 if ((status & SPIFLASH_BSY_BIT) == 0)
338 return ERROR_OK;
339 alive_sleep(1);
340 } while (timeval_ms() < endtime);
341
342 LOG_ERROR("timeout waiting for flash to finish write/erase operation");
343 return ERROR_FAIL;
344 }
345
346 /* Send "write enable" command to SPI flash chip. */
347 static int lpcspifi_write_enable(struct flash_bank *bank)
348 {
349 struct target *target = bank->target;
350 struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
351 uint32_t ssp_base = lpcspifi_info->ssp_base;
352 uint32_t io_base = lpcspifi_info->io_base;
353 uint32_t status, value;
354 int retval = ERROR_OK;
355
356 retval = ssp_setcs(target, io_base, 0);
357 if (retval == ERROR_OK)
358 retval = ssp_write_reg(target, ssp_base, SSP_DATA, SPIFLASH_WRITE_ENABLE);
359 if (retval == ERROR_OK)
360 retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT);
361 if (retval == ERROR_OK)
362 retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value);
363 if (retval == ERROR_OK)
364 retval = ssp_setcs(target, io_base, 1);
365
366 /* read flash status register */
367 if (retval == ERROR_OK)
368 retval = read_status_reg(bank, &status);
369 if (retval != ERROR_OK)
370 return retval;
371
372 /* Check write enabled */
373 if ((status & SPIFLASH_WE_BIT) == 0) {
374 LOG_ERROR("Cannot enable write to flash. Status=0x%08" PRIx32, status);
375 return ERROR_FAIL;
376 }
377
378 return retval;
379 }
380
381 static int lpcspifi_bulk_erase(struct flash_bank *bank)
382 {
383 struct target *target = bank->target;
384 struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
385 uint32_t ssp_base = lpcspifi_info->ssp_base;
386 uint32_t io_base = lpcspifi_info->io_base;
387 uint32_t value;
388 int retval = ERROR_OK;
389
390 retval = lpcspifi_set_sw_mode(bank);
391
392 if (retval == ERROR_OK)
393 retval = lpcspifi_write_enable(bank);
394
395 /* send SPI command "bulk erase" */
396 if (retval == ERROR_OK)
397 ssp_setcs(target, io_base, 0);
398 if (retval == ERROR_OK)
399 retval = ssp_write_reg(target, ssp_base, SSP_DATA, lpcspifi_info->dev->chip_erase_cmd);
400 if (retval == ERROR_OK)
401 retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT);
402 if (retval == ERROR_OK)
403 retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value);
404 if (retval == ERROR_OK)
405 retval = ssp_setcs(target, io_base, 1);
406
407 /* poll flash BSY for self-timed bulk erase */
408 if (retval == ERROR_OK)
409 retval = wait_till_ready(bank, bank->num_sectors*SSP_MAX_TIMEOUT);
410
411 return retval;
412 }
413
414 static int lpcspifi_erase(struct flash_bank *bank, int first, int last)
415 {
416 struct target *target = bank->target;
417 struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
418 struct reg_param reg_params[4];
419 struct armv7m_algorithm armv7m_info;
420 struct working_area *erase_algorithm;
421 int retval = ERROR_OK;
422 int sector;
423
424 LOG_DEBUG("erase from sector %d to sector %d", first, last);
425
426 if (target->state != TARGET_HALTED) {
427 LOG_ERROR("Target not halted");
428 return ERROR_TARGET_NOT_HALTED;
429 }
430
431 if ((first < 0) || (last < first) || (last >= bank->num_sectors)) {
432 LOG_ERROR("Flash sector invalid");
433 return ERROR_FLASH_SECTOR_INVALID;
434 }
435
436 if (!(lpcspifi_info->probed)) {
437 LOG_ERROR("Flash bank not probed");
438 return ERROR_FLASH_BANK_NOT_PROBED;
439 }
440
441 for (sector = first; sector <= last; sector++) {
442 if (bank->sectors[sector].is_protected) {
443 LOG_ERROR("Flash sector %d protected", sector);
444 return ERROR_FAIL;
445 }
446 }
447
448 /* If we're erasing the entire chip and the flash supports
449 * it, use a bulk erase instead of going sector-by-sector. */
450 if (first == 0 && last == (bank->num_sectors - 1)
451 && lpcspifi_info->dev->chip_erase_cmd != lpcspifi_info->dev->erase_cmd) {
452 LOG_DEBUG("Chip supports the bulk erase command."\
453 " Will use bulk erase instead of sector-by-sector erase.");
454 retval = lpcspifi_bulk_erase(bank);
455
456 if (retval == ERROR_OK) {
457 retval = lpcspifi_set_hw_mode(bank);
458 return retval;
459 } else
460 LOG_WARNING("Bulk flash erase failed. Falling back to sector-by-sector erase.");
461 }
462
463 retval = lpcspifi_set_hw_mode(bank);
464 if (retval != ERROR_OK)
465 return retval;
466
467 /* see contrib/loaders/flash/lpcspifi_erase.S for src */
468 static const uint8_t lpcspifi_flash_erase_code[] = {
469 0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x08, 0x0a,
470 0x4f, 0xf0, 0xea, 0x08, 0xca, 0xf8, 0x8c, 0x81,
471 0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x90, 0x81,
472 0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x94, 0x81,
473 0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x98, 0x81,
474 0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x9c, 0x81,
475 0x4f, 0xf0, 0x44, 0x08, 0xca, 0xf8, 0xa0, 0x81,
476 0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a,
477 0x4f, 0xf4, 0x00, 0x68, 0xca, 0xf8, 0x14, 0x80,
478 0x4f, 0xf4, 0x80, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a,
479 0x4f, 0xf0, 0xff, 0x08, 0xca, 0xf8, 0xab, 0x80,
480 0x4f, 0xf0, 0x00, 0x0a, 0xc4, 0xf2, 0x05, 0x0a,
481 0x4f, 0xf0, 0x00, 0x08, 0xc0, 0xf2, 0x00, 0x18,
482 0xca, 0xf8, 0x94, 0x80, 0x4f, 0xf4, 0x00, 0x5a,
483 0xc4, 0xf2, 0x05, 0x0a, 0x4f, 0xf0, 0x01, 0x08,
484 0xca, 0xf8, 0x00, 0x87, 0x4f, 0xf4, 0x40, 0x5a,
485 0xc4, 0xf2, 0x08, 0x0a, 0x4f, 0xf0, 0x07, 0x08,
486 0xca, 0xf8, 0x00, 0x80, 0x4f, 0xf0, 0x02, 0x08,
487 0xca, 0xf8, 0x10, 0x80, 0xca, 0xf8, 0x04, 0x80,
488 0x00, 0xf0, 0x52, 0xf8, 0x4f, 0xf0, 0x06, 0x09,
489 0x00, 0xf0, 0x3b, 0xf8, 0x00, 0xf0, 0x48, 0xf8,
490 0x00, 0xf0, 0x4a, 0xf8, 0x4f, 0xf0, 0x05, 0x09,
491 0x00, 0xf0, 0x33, 0xf8, 0x4f, 0xf0, 0x00, 0x09,
492 0x00, 0xf0, 0x2f, 0xf8, 0x00, 0xf0, 0x3c, 0xf8,
493 0x19, 0xf0, 0x02, 0x0f, 0x00, 0xf0, 0x45, 0x80,
494 0x00, 0xf0, 0x3a, 0xf8, 0x4f, 0xea, 0x02, 0x09,
495 0x00, 0xf0, 0x23, 0xf8, 0x4f, 0xea, 0x10, 0x49,
496 0x00, 0xf0, 0x1f, 0xf8, 0x4f, 0xea, 0x10, 0x29,
497 0x00, 0xf0, 0x1b, 0xf8, 0x4f, 0xea, 0x00, 0x09,
498 0x00, 0xf0, 0x17, 0xf8, 0x00, 0xf0, 0x24, 0xf8,
499 0x00, 0xf0, 0x26, 0xf8, 0x4f, 0xf0, 0x05, 0x09,
500 0x00, 0xf0, 0x0f, 0xf8, 0x4f, 0xf0, 0x00, 0x09,
501 0x00, 0xf0, 0x0b, 0xf8, 0x00, 0xf0, 0x18, 0xf8,
502 0x19, 0xf0, 0x01, 0x0f, 0x7f, 0xf4, 0xf0, 0xaf,
503 0x01, 0x39, 0xf9, 0xb1, 0x18, 0x44, 0xff, 0xf7,
504 0xbf, 0xbf, 0x4f, 0xf4, 0x40, 0x5a, 0xc4, 0xf2,
505 0x08, 0x0a, 0xca, 0xf8, 0x08, 0x90, 0xda, 0xf8,
506 0x0c, 0x90, 0x19, 0xf0, 0x10, 0x0f, 0x7f, 0xf4,
507 0xfa, 0xaf, 0xda, 0xf8, 0x08, 0x90, 0x70, 0x47,
508 0x4f, 0xf0, 0xff, 0x08, 0x00, 0xf0, 0x02, 0xb8,
509 0x4f, 0xf0, 0x00, 0x08, 0x4f, 0xf4, 0x80, 0x4a,
510 0xc4, 0xf2, 0x0f, 0x0a, 0xca, 0xf8, 0xab, 0x80,
511 0x70, 0x47, 0x00, 0x20, 0x00, 0xbe, 0xff, 0xff
512 };
513
514 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
515 armv7m_info.core_mode = ARM_MODE_THREAD;
516
517
518 /* Get memory for spifi initialization algorithm */
519 retval = target_alloc_working_area(target, sizeof(lpcspifi_flash_erase_code),
520 &erase_algorithm);
521 if (retval != ERROR_OK) {
522 LOG_ERROR("Insufficient working area. You must configure a working"\
523 " area of at least %zdB in order to erase SPIFI flash.",
524 sizeof(lpcspifi_flash_erase_code));
525 return retval;
526 }
527
528 /* Write algorithm to working area */
529 retval = target_write_buffer(target, erase_algorithm->address,
530 sizeof(lpcspifi_flash_erase_code), lpcspifi_flash_erase_code);
531 if (retval != ERROR_OK) {
532 target_free_working_area(target, erase_algorithm);
533 return retval;
534 }
535
536 init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* Start address */
537 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* Sector count */
538 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* Erase command */
539 init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT); /* Sector size */
540
541 buf_set_u32(reg_params[0].value, 0, 32, bank->sectors[first].offset);
542 buf_set_u32(reg_params[1].value, 0, 32, last - first + 1);
543 buf_set_u32(reg_params[2].value, 0, 32, lpcspifi_info->dev->erase_cmd);
544 buf_set_u32(reg_params[3].value, 0, 32, bank->sectors[first].size);
545
546 /* Run the algorithm */
547 retval = target_run_algorithm(target, 0 , NULL, 4, reg_params,
548 erase_algorithm->address,
549 erase_algorithm->address + sizeof(lpcspifi_flash_erase_code) - 4,
550 3000*(last - first + 1), &armv7m_info);
551
552 if (retval != ERROR_OK)
553 LOG_ERROR("Error executing flash erase algorithm");
554
555 target_free_working_area(target, erase_algorithm);
556
557 destroy_reg_param(&reg_params[0]);
558 destroy_reg_param(&reg_params[1]);
559 destroy_reg_param(&reg_params[2]);
560 destroy_reg_param(&reg_params[3]);
561
562 retval = lpcspifi_set_hw_mode(bank);
563
564 return retval;
565 }
566
567 static int lpcspifi_protect(struct flash_bank *bank, int set,
568 int first, int last)
569 {
570 int sector;
571
572 for (sector = first; sector <= last; sector++)
573 bank->sectors[sector].is_protected = set;
574 return ERROR_OK;
575 }
576
577 static int lpcspifi_write(struct flash_bank *bank, const uint8_t *buffer,
578 uint32_t offset, uint32_t count)
579 {
580 struct target *target = bank->target;
581 struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
582 uint32_t page_size, fifo_size;
583 struct working_area *fifo;
584 struct reg_param reg_params[5];
585 struct armv7m_algorithm armv7m_info;
586 struct working_area *write_algorithm;
587 int sector;
588 int retval = ERROR_OK;
589
590 LOG_DEBUG("offset=0x%08" PRIx32 " count=0x%08" PRIx32,
591 offset, count);
592
593 if (target->state != TARGET_HALTED) {
594 LOG_ERROR("Target not halted");
595 return ERROR_TARGET_NOT_HALTED;
596 }
597
598 if (offset + count > lpcspifi_info->dev->size_in_bytes) {
599 LOG_WARNING("Writes past end of flash. Extra data discarded.");
600 count = lpcspifi_info->dev->size_in_bytes - offset;
601 }
602
603 /* Check sector protection */
604 for (sector = 0; sector < bank->num_sectors; sector++) {
605 /* Start offset in or before this sector? */
606 /* End offset in or behind this sector? */
607 if ((offset <
608 (bank->sectors[sector].offset + bank->sectors[sector].size))
609 && ((offset + count - 1) >= bank->sectors[sector].offset)
610 && bank->sectors[sector].is_protected) {
611 LOG_ERROR("Flash sector %d protected", sector);
612 return ERROR_FAIL;
613 }
614 }
615
616 page_size = lpcspifi_info->dev->pagesize;
617
618 retval = lpcspifi_set_hw_mode(bank);
619 if (retval != ERROR_OK)
620 return retval;
621
622 /* see contrib/loaders/flash/lpcspifi_write.S for src */
623 static const uint8_t lpcspifi_flash_write_code[] = {
624 0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x08, 0x0a,
625 0x4f, 0xf0, 0xea, 0x08, 0xca, 0xf8, 0x8c, 0x81,
626 0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x90, 0x81,
627 0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x94, 0x81,
628 0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x98, 0x81,
629 0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x9c, 0x81,
630 0x4f, 0xf0, 0x44, 0x08, 0xca, 0xf8, 0xa0, 0x81,
631 0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a,
632 0x4f, 0xf4, 0x00, 0x68, 0xca, 0xf8, 0x14, 0x80,
633 0x4f, 0xf4, 0x80, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a,
634 0x4f, 0xf0, 0xff, 0x08, 0xca, 0xf8, 0xab, 0x80,
635 0x4f, 0xf0, 0x00, 0x0a, 0xc4, 0xf2, 0x05, 0x0a,
636 0x4f, 0xf0, 0x00, 0x08, 0xc0, 0xf2, 0x00, 0x18,
637 0xca, 0xf8, 0x94, 0x80, 0x4f, 0xf4, 0x00, 0x5a,
638 0xc4, 0xf2, 0x05, 0x0a, 0x4f, 0xf0, 0x01, 0x08,
639 0xca, 0xf8, 0x00, 0x87, 0x4f, 0xf4, 0x40, 0x5a,
640 0xc4, 0xf2, 0x08, 0x0a, 0x4f, 0xf0, 0x07, 0x08,
641 0xca, 0xf8, 0x00, 0x80, 0x4f, 0xf0, 0x02, 0x08,
642 0xca, 0xf8, 0x10, 0x80, 0xca, 0xf8, 0x04, 0x80,
643 0x4f, 0xf0, 0x00, 0x0b, 0xa3, 0x44, 0x93, 0x45,
644 0x7f, 0xf6, 0xfc, 0xaf, 0x00, 0xf0, 0x6a, 0xf8,
645 0x4f, 0xf0, 0x06, 0x09, 0x00, 0xf0, 0x53, 0xf8,
646 0x00, 0xf0, 0x60, 0xf8, 0x00, 0xf0, 0x62, 0xf8,
647 0x4f, 0xf0, 0x05, 0x09, 0x00, 0xf0, 0x4b, 0xf8,
648 0x4f, 0xf0, 0x00, 0x09, 0x00, 0xf0, 0x47, 0xf8,
649 0x00, 0xf0, 0x54, 0xf8, 0x19, 0xf0, 0x02, 0x0f,
650 0x00, 0xf0, 0x5d, 0x80, 0x00, 0xf0, 0x52, 0xf8,
651 0x4f, 0xf0, 0x02, 0x09, 0x00, 0xf0, 0x3b, 0xf8,
652 0x4f, 0xea, 0x12, 0x49, 0x00, 0xf0, 0x37, 0xf8,
653 0x4f, 0xea, 0x12, 0x29, 0x00, 0xf0, 0x33, 0xf8,
654 0x4f, 0xea, 0x02, 0x09, 0x00, 0xf0, 0x2f, 0xf8,
655 0xd0, 0xf8, 0x00, 0x80, 0xb8, 0xf1, 0x00, 0x0f,
656 0x00, 0xf0, 0x47, 0x80, 0x47, 0x68, 0x47, 0x45,
657 0x3f, 0xf4, 0xf6, 0xaf, 0x17, 0xf8, 0x01, 0x9b,
658 0x00, 0xf0, 0x21, 0xf8, 0x8f, 0x42, 0x28, 0xbf,
659 0x00, 0xf1, 0x08, 0x07, 0x47, 0x60, 0x01, 0x3b,
660 0xbb, 0xb3, 0x02, 0xf1, 0x01, 0x02, 0x93, 0x45,
661 0x7f, 0xf4, 0xe6, 0xaf, 0x00, 0xf0, 0x22, 0xf8,
662 0xa3, 0x44, 0x00, 0xf0, 0x23, 0xf8, 0x4f, 0xf0,
663 0x05, 0x09, 0x00, 0xf0, 0x0c, 0xf8, 0x4f, 0xf0,
664 0x00, 0x09, 0x00, 0xf0, 0x08, 0xf8, 0x00, 0xf0,
665 0x15, 0xf8, 0x19, 0xf0, 0x01, 0x0f, 0x7f, 0xf4,
666 0xf0, 0xaf, 0xff, 0xf7, 0xa7, 0xbf, 0x4f, 0xf4,
667 0x40, 0x5a, 0xc4, 0xf2, 0x08, 0x0a, 0xca, 0xf8,
668 0x08, 0x90, 0xda, 0xf8, 0x0c, 0x90, 0x19, 0xf0,
669 0x10, 0x0f, 0x7f, 0xf4, 0xfa, 0xaf, 0xda, 0xf8,
670 0x08, 0x90, 0x70, 0x47, 0x4f, 0xf0, 0xff, 0x08,
671 0x00, 0xf0, 0x02, 0xb8, 0x4f, 0xf0, 0x00, 0x08,
672 0x4f, 0xf4, 0x80, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a,
673 0xca, 0xf8, 0xab, 0x80, 0x70, 0x47, 0x00, 0x20,
674 0x50, 0x60, 0xff, 0xf7, 0xef, 0xff, 0x30, 0x46,
675 0x00, 0xbe, 0xff, 0xff
676 };
677
678 if (target_alloc_working_area(target, sizeof(lpcspifi_flash_write_code),
679 &write_algorithm) != ERROR_OK) {
680 LOG_ERROR("Insufficient working area. You must configure"\
681 " a working area > %zdB in order to write to SPIFI flash.",
682 sizeof(lpcspifi_flash_write_code));
683 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
684 }
685
686 retval = target_write_buffer(target, write_algorithm->address,
687 sizeof(lpcspifi_flash_write_code),
688 lpcspifi_flash_write_code);
689 if (retval != ERROR_OK) {
690 target_free_working_area(target, write_algorithm);
691 return retval;
692 }
693
694 /* FIFO allocation */
695 fifo_size = target_get_working_area_avail(target);
696
697 if (fifo_size == 0) {
698 /* if we already allocated the writing code but failed to get fifo
699 * space, free the algorithm */
700 target_free_working_area(target, write_algorithm);
701
702 LOG_ERROR("Insufficient working area. Please allocate at least"\
703 " %zdB of working area to enable flash writes.",
704 sizeof(lpcspifi_flash_write_code) + 1
705 );
706
707 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
708 } else if (fifo_size < page_size)
709 LOG_WARNING("Working area size is limited; flash writes may be"\
710 " slow. Increase working area size to at least %zdB"\
711 " to reduce write times.",
712 (size_t)(sizeof(lpcspifi_flash_write_code) + page_size)
713 );
714 else if (fifo_size > 0x2000) /* Beyond this point, we start to get diminishing returns */
715 fifo_size = 0x2000;
716
717 if (target_alloc_working_area(target, fifo_size, &fifo) != ERROR_OK) {
718 target_free_working_area(target, write_algorithm);
719 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
720 }
721
722 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
723 armv7m_info.core_mode = ARM_MODE_THREAD;
724
725 init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* buffer start, status (out) */
726 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* buffer end */
727 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* target address */
728 init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT); /* count (halfword-16bit) */
729 init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT); /* page size */
730
731 buf_set_u32(reg_params[0].value, 0, 32, fifo->address);
732 buf_set_u32(reg_params[1].value, 0, 32, fifo->address + fifo->size);
733 buf_set_u32(reg_params[2].value, 0, 32, offset);
734 buf_set_u32(reg_params[3].value, 0, 32, count);
735 buf_set_u32(reg_params[4].value, 0, 32, page_size);
736
737 retval = target_run_flash_async_algorithm(target, buffer, count, 1,
738 0, NULL,
739 5, reg_params,
740 fifo->address, fifo->size,
741 write_algorithm->address, 0,
742 &armv7m_info
743 );
744
745 if (retval != ERROR_OK)
746 LOG_ERROR("Error executing flash write algorithm");
747
748 target_free_working_area(target, fifo);
749 target_free_working_area(target, write_algorithm);
750
751 destroy_reg_param(&reg_params[0]);
752 destroy_reg_param(&reg_params[1]);
753 destroy_reg_param(&reg_params[2]);
754 destroy_reg_param(&reg_params[3]);
755 destroy_reg_param(&reg_params[4]);
756
757 /* Switch to HW mode before return to prompt */
758 retval = lpcspifi_set_hw_mode(bank);
759 return retval;
760 }
761
762 /* Return ID of flash device */
763 /* On exit, SW mode is kept */
764 static int lpcspifi_read_flash_id(struct flash_bank *bank, uint32_t *id)
765 {
766 struct target *target = bank->target;
767 struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
768 uint32_t ssp_base = lpcspifi_info->ssp_base;
769 uint32_t io_base = lpcspifi_info->io_base;
770 uint32_t value;
771 uint8_t id_buf[3] = {0, 0, 0};
772 int retval;
773
774 if (target->state != TARGET_HALTED) {
775 LOG_ERROR("Target not halted");
776 return ERROR_TARGET_NOT_HALTED;
777 }
778
779 LOG_DEBUG("Getting ID");
780 retval = lpcspifi_set_sw_mode(bank);
781 if (retval != ERROR_OK)
782 return retval;
783
784 /* poll WIP */
785 if (retval == ERROR_OK)
786 retval = wait_till_ready(bank, SSP_PROBE_TIMEOUT);
787
788 /* Send SPI command "read ID" */
789 if (retval == ERROR_OK)
790 retval = ssp_setcs(target, io_base, 0);
791 if (retval == ERROR_OK)
792 retval = ssp_write_reg(target, ssp_base, SSP_DATA, SPIFLASH_READ_ID);
793 if (retval == ERROR_OK)
794 retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT);
795 if (retval == ERROR_OK)
796 retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value);
797
798 /* Dummy write to clock in data */
799 if (retval == ERROR_OK)
800 retval = ssp_write_reg(target, ssp_base, SSP_DATA, 0x00);
801 if (retval == ERROR_OK)
802 retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT);
803 if (retval == ERROR_OK)
804 retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value);
805 if (retval == ERROR_OK)
806 id_buf[0] = value;
807
808 /* Dummy write to clock in data */
809 if (retval == ERROR_OK)
810 retval = ssp_write_reg(target, ssp_base, SSP_DATA, 0x00);
811 if (retval == ERROR_OK)
812 retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT);
813 if (retval == ERROR_OK)
814 retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value);
815 if (retval == ERROR_OK)
816 id_buf[1] = value;
817
818 /* Dummy write to clock in data */
819 if (retval == ERROR_OK)
820 retval = ssp_write_reg(target, ssp_base, SSP_DATA, 0x00);
821 if (retval == ERROR_OK)
822 retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT);
823 if (retval == ERROR_OK)
824 retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value);
825 if (retval == ERROR_OK)
826 id_buf[2] = value;
827
828 if (retval == ERROR_OK)
829 retval = ssp_setcs(target, io_base, 1);
830 if (retval == ERROR_OK)
831 *id = id_buf[2] << 16 | id_buf[1] << 8 | id_buf[0];
832
833 return retval;
834 }
835
836 static int lpcspifi_probe(struct flash_bank *bank)
837 {
838 struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
839 struct flash_sector *sectors;
840 uint32_t id = 0; /* silence uninitialized warning */
841 int retval;
842
843 /* If we've already probed, we should be fine to skip this time. */
844 if (lpcspifi_info->probed)
845 return ERROR_OK;
846 lpcspifi_info->probed = 0;
847
848 lpcspifi_info->ssp_base = 0x40083000;
849 lpcspifi_info->io_base = 0x400F4000;
850 lpcspifi_info->ioconfig_base = 0x40086000;
851 lpcspifi_info->bank_num = bank->bank_number;
852
853 /* read and decode flash ID; returns in SW mode */
854 retval = lpcspifi_read_flash_id(bank, &id);
855 if (retval != ERROR_OK)
856 return retval;
857
858 retval = lpcspifi_set_hw_mode(bank);
859 if (retval != ERROR_OK)
860 return retval;
861
862 lpcspifi_info->dev = NULL;
863 for (const struct flash_device *p = flash_devices; p->name ; p++)
864 if (p->device_id == id) {
865 lpcspifi_info->dev = p;
866 break;
867 }
868
869 if (!lpcspifi_info->dev) {
870 LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", id);
871 return ERROR_FAIL;
872 }
873
874 LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")",
875 lpcspifi_info->dev->name, lpcspifi_info->dev->device_id);
876
877 /* Set correct size value */
878 bank->size = lpcspifi_info->dev->size_in_bytes;
879
880 /* create and fill sectors array */
881 bank->num_sectors =
882 lpcspifi_info->dev->size_in_bytes / lpcspifi_info->dev->sectorsize;
883 sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
884 if (sectors == NULL) {
885 LOG_ERROR("not enough memory");
886 return ERROR_FAIL;
887 }
888
889 for (int sector = 0; sector < bank->num_sectors; sector++) {
890 sectors[sector].offset = sector * lpcspifi_info->dev->sectorsize;
891 sectors[sector].size = lpcspifi_info->dev->sectorsize;
892 sectors[sector].is_erased = -1;
893 sectors[sector].is_protected = 0;
894 }
895
896 bank->sectors = sectors;
897
898 lpcspifi_info->probed = 1;
899 return ERROR_OK;
900 }
901
902 static int lpcspifi_auto_probe(struct flash_bank *bank)
903 {
904 struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
905 if (lpcspifi_info->probed)
906 return ERROR_OK;
907 return lpcspifi_probe(bank);
908 }
909
910 static int lpcspifi_protect_check(struct flash_bank *bank)
911 {
912 /* Nothing to do. Protection is only handled in SW. */
913 return ERROR_OK;
914 }
915
916 static int get_lpcspifi_info(struct flash_bank *bank, char *buf, int buf_size)
917 {
918 struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
919
920 if (!(lpcspifi_info->probed)) {
921 snprintf(buf, buf_size,
922 "\nSPIFI flash bank not probed yet\n");
923 return ERROR_OK;
924 }
925
926 snprintf(buf, buf_size, "\nSPIFI flash information:\n"
927 " Device \'%s\' (ID 0x%08" PRIx32 ")\n",
928 lpcspifi_info->dev->name, lpcspifi_info->dev->device_id);
929
930 return ERROR_OK;
931 }
932
933 struct flash_driver lpcspifi_flash = {
934 .name = "lpcspifi",
935 .flash_bank_command = lpcspifi_flash_bank_command,
936 .erase = lpcspifi_erase,
937 .protect = lpcspifi_protect,
938 .write = lpcspifi_write,
939 .read = default_flash_read,
940 .probe = lpcspifi_probe,
941 .auto_probe = lpcspifi_auto_probe,
942 .erase_check = default_flash_blank_check,
943 .protect_check = lpcspifi_protect_check,
944 .info = get_lpcspifi_info,
945 .free_driver_priv = default_flash_free_driver_priv,
946 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)