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

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)