a7e65ec4909f393f3134f2e86dade2dce046cb62
[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 " TARGET_ADDR_FMT,
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 if (lpcspifi_info->dev->chip_erase_cmd == 0x00)
391 return ERROR_FLASH_OPER_UNSUPPORTED;
392
393 retval = lpcspifi_set_sw_mode(bank);
394
395 if (retval == ERROR_OK)
396 retval = lpcspifi_write_enable(bank);
397
398 /* send SPI command "bulk erase" */
399 if (retval == ERROR_OK)
400 ssp_setcs(target, io_base, 0);
401 if (retval == ERROR_OK)
402 retval = ssp_write_reg(target, ssp_base, SSP_DATA, lpcspifi_info->dev->chip_erase_cmd);
403 if (retval == ERROR_OK)
404 retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT);
405 if (retval == ERROR_OK)
406 retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value);
407 if (retval == ERROR_OK)
408 retval = ssp_setcs(target, io_base, 1);
409
410 /* poll flash BSY for self-timed bulk erase */
411 if (retval == ERROR_OK)
412 retval = wait_till_ready(bank, bank->num_sectors*SSP_MAX_TIMEOUT);
413
414 return retval;
415 }
416
417 static int lpcspifi_erase(struct flash_bank *bank, int first, int last)
418 {
419 struct target *target = bank->target;
420 struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
421 struct reg_param reg_params[4];
422 struct armv7m_algorithm armv7m_info;
423 struct working_area *erase_algorithm;
424 int retval = ERROR_OK;
425 int sector;
426
427 LOG_DEBUG("erase from sector %d to sector %d", first, last);
428
429 if (target->state != TARGET_HALTED) {
430 LOG_ERROR("Target not halted");
431 return ERROR_TARGET_NOT_HALTED;
432 }
433
434 if ((first < 0) || (last < first) || (last >= bank->num_sectors)) {
435 LOG_ERROR("Flash sector invalid");
436 return ERROR_FLASH_SECTOR_INVALID;
437 }
438
439 if (!(lpcspifi_info->probed)) {
440 LOG_ERROR("Flash bank not probed");
441 return ERROR_FLASH_BANK_NOT_PROBED;
442 }
443
444 for (sector = first; sector <= last; sector++) {
445 if (bank->sectors[sector].is_protected) {
446 LOG_ERROR("Flash sector %d protected", sector);
447 return ERROR_FAIL;
448 }
449 }
450
451 /* If we're erasing the entire chip and the flash supports
452 * it, use a bulk erase instead of going sector-by-sector. */
453 if (first == 0 && last == (bank->num_sectors - 1)
454 && lpcspifi_info->dev->chip_erase_cmd != lpcspifi_info->dev->erase_cmd) {
455 LOG_DEBUG("Chip supports the bulk erase command."\
456 " Will use bulk erase instead of sector-by-sector erase.");
457 retval = lpcspifi_bulk_erase(bank);
458
459 if (retval == ERROR_OK) {
460 retval = lpcspifi_set_hw_mode(bank);
461 return retval;
462 } else
463 LOG_WARNING("Bulk flash erase failed. Falling back to sector-by-sector erase.");
464 }
465
466 if (lpcspifi_info->dev->erase_cmd == 0x00)
467 return ERROR_FLASH_OPER_UNSUPPORTED;
468
469 retval = lpcspifi_set_hw_mode(bank);
470 if (retval != ERROR_OK)
471 return retval;
472
473 /* see contrib/loaders/flash/lpcspifi_erase.S for src */
474 static const uint8_t lpcspifi_flash_erase_code[] = {
475 0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x08, 0x0a,
476 0x4f, 0xf0, 0xea, 0x08, 0xca, 0xf8, 0x8c, 0x81,
477 0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x90, 0x81,
478 0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x94, 0x81,
479 0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x98, 0x81,
480 0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x9c, 0x81,
481 0x4f, 0xf0, 0x44, 0x08, 0xca, 0xf8, 0xa0, 0x81,
482 0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a,
483 0x4f, 0xf4, 0x00, 0x68, 0xca, 0xf8, 0x14, 0x80,
484 0x4f, 0xf4, 0x80, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a,
485 0x4f, 0xf0, 0xff, 0x08, 0xca, 0xf8, 0xab, 0x80,
486 0x4f, 0xf0, 0x00, 0x0a, 0xc4, 0xf2, 0x05, 0x0a,
487 0x4f, 0xf0, 0x00, 0x08, 0xc0, 0xf2, 0x00, 0x18,
488 0xca, 0xf8, 0x94, 0x80, 0x4f, 0xf4, 0x00, 0x5a,
489 0xc4, 0xf2, 0x05, 0x0a, 0x4f, 0xf0, 0x01, 0x08,
490 0xca, 0xf8, 0x00, 0x87, 0x4f, 0xf4, 0x40, 0x5a,
491 0xc4, 0xf2, 0x08, 0x0a, 0x4f, 0xf0, 0x07, 0x08,
492 0xca, 0xf8, 0x00, 0x80, 0x4f, 0xf0, 0x02, 0x08,
493 0xca, 0xf8, 0x10, 0x80, 0xca, 0xf8, 0x04, 0x80,
494 0x00, 0xf0, 0x52, 0xf8, 0x4f, 0xf0, 0x06, 0x09,
495 0x00, 0xf0, 0x3b, 0xf8, 0x00, 0xf0, 0x48, 0xf8,
496 0x00, 0xf0, 0x4a, 0xf8, 0x4f, 0xf0, 0x05, 0x09,
497 0x00, 0xf0, 0x33, 0xf8, 0x4f, 0xf0, 0x00, 0x09,
498 0x00, 0xf0, 0x2f, 0xf8, 0x00, 0xf0, 0x3c, 0xf8,
499 0x19, 0xf0, 0x02, 0x0f, 0x00, 0xf0, 0x45, 0x80,
500 0x00, 0xf0, 0x3a, 0xf8, 0x4f, 0xea, 0x02, 0x09,
501 0x00, 0xf0, 0x23, 0xf8, 0x4f, 0xea, 0x10, 0x49,
502 0x00, 0xf0, 0x1f, 0xf8, 0x4f, 0xea, 0x10, 0x29,
503 0x00, 0xf0, 0x1b, 0xf8, 0x4f, 0xea, 0x00, 0x09,
504 0x00, 0xf0, 0x17, 0xf8, 0x00, 0xf0, 0x24, 0xf8,
505 0x00, 0xf0, 0x26, 0xf8, 0x4f, 0xf0, 0x05, 0x09,
506 0x00, 0xf0, 0x0f, 0xf8, 0x4f, 0xf0, 0x00, 0x09,
507 0x00, 0xf0, 0x0b, 0xf8, 0x00, 0xf0, 0x18, 0xf8,
508 0x19, 0xf0, 0x01, 0x0f, 0x7f, 0xf4, 0xf0, 0xaf,
509 0x01, 0x39, 0xf9, 0xb1, 0x18, 0x44, 0xff, 0xf7,
510 0xbf, 0xbf, 0x4f, 0xf4, 0x40, 0x5a, 0xc4, 0xf2,
511 0x08, 0x0a, 0xca, 0xf8, 0x08, 0x90, 0xda, 0xf8,
512 0x0c, 0x90, 0x19, 0xf0, 0x10, 0x0f, 0x7f, 0xf4,
513 0xfa, 0xaf, 0xda, 0xf8, 0x08, 0x90, 0x70, 0x47,
514 0x4f, 0xf0, 0xff, 0x08, 0x00, 0xf0, 0x02, 0xb8,
515 0x4f, 0xf0, 0x00, 0x08, 0x4f, 0xf4, 0x80, 0x4a,
516 0xc4, 0xf2, 0x0f, 0x0a, 0xca, 0xf8, 0xab, 0x80,
517 0x70, 0x47, 0x00, 0x20, 0x00, 0xbe, 0xff, 0xff
518 };
519
520 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
521 armv7m_info.core_mode = ARM_MODE_THREAD;
522
523
524 /* Get memory for spifi initialization algorithm */
525 retval = target_alloc_working_area(target, sizeof(lpcspifi_flash_erase_code),
526 &erase_algorithm);
527 if (retval != ERROR_OK) {
528 LOG_ERROR("Insufficient working area. You must configure a working"\
529 " area of at least %zdB in order to erase SPIFI flash.",
530 sizeof(lpcspifi_flash_erase_code));
531 return retval;
532 }
533
534 /* Write algorithm to working area */
535 retval = target_write_buffer(target, erase_algorithm->address,
536 sizeof(lpcspifi_flash_erase_code), lpcspifi_flash_erase_code);
537 if (retval != ERROR_OK) {
538 target_free_working_area(target, erase_algorithm);
539 return retval;
540 }
541
542 init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* Start address */
543 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* Sector count */
544 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* Erase command */
545 init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT); /* Sector size */
546
547 buf_set_u32(reg_params[0].value, 0, 32, bank->sectors[first].offset);
548 buf_set_u32(reg_params[1].value, 0, 32, last - first + 1);
549 buf_set_u32(reg_params[2].value, 0, 32, lpcspifi_info->dev->erase_cmd);
550 buf_set_u32(reg_params[3].value, 0, 32, bank->sectors[first].size);
551
552 /* Run the algorithm */
553 retval = target_run_algorithm(target, 0 , NULL, 4, reg_params,
554 erase_algorithm->address,
555 erase_algorithm->address + sizeof(lpcspifi_flash_erase_code) - 4,
556 3000*(last - first + 1), &armv7m_info);
557
558 if (retval != ERROR_OK)
559 LOG_ERROR("Error executing flash erase algorithm");
560
561 target_free_working_area(target, erase_algorithm);
562
563 destroy_reg_param(&reg_params[0]);
564 destroy_reg_param(&reg_params[1]);
565 destroy_reg_param(&reg_params[2]);
566 destroy_reg_param(&reg_params[3]);
567
568 retval = lpcspifi_set_hw_mode(bank);
569
570 return retval;
571 }
572
573 static int lpcspifi_protect(struct flash_bank *bank, int set,
574 int first, int last)
575 {
576 int sector;
577
578 for (sector = first; sector <= last; sector++)
579 bank->sectors[sector].is_protected = set;
580 return ERROR_OK;
581 }
582
583 static int lpcspifi_write(struct flash_bank *bank, const uint8_t *buffer,
584 uint32_t offset, uint32_t count)
585 {
586 struct target *target = bank->target;
587 struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
588 uint32_t page_size, fifo_size;
589 struct working_area *fifo;
590 struct reg_param reg_params[5];
591 struct armv7m_algorithm armv7m_info;
592 struct working_area *write_algorithm;
593 int sector;
594 int retval = ERROR_OK;
595
596 LOG_DEBUG("offset=0x%08" PRIx32 " count=0x%08" PRIx32,
597 offset, count);
598
599 if (target->state != TARGET_HALTED) {
600 LOG_ERROR("Target not halted");
601 return ERROR_TARGET_NOT_HALTED;
602 }
603
604 if (offset + count > lpcspifi_info->dev->size_in_bytes) {
605 LOG_WARNING("Writes past end of flash. Extra data discarded.");
606 count = lpcspifi_info->dev->size_in_bytes - offset;
607 }
608
609 /* Check sector protection */
610 for (sector = 0; sector < bank->num_sectors; sector++) {
611 /* Start offset in or before this sector? */
612 /* End offset in or behind this sector? */
613 if ((offset <
614 (bank->sectors[sector].offset + bank->sectors[sector].size))
615 && ((offset + count - 1) >= bank->sectors[sector].offset)
616 && bank->sectors[sector].is_protected) {
617 LOG_ERROR("Flash sector %d protected", sector);
618 return ERROR_FAIL;
619 }
620 }
621
622 /* if no valid page_size, use reasonable default */
623 page_size = lpcspifi_info->dev->pagesize ?
624 lpcspifi_info->dev->pagesize : SPIFLASH_DEF_PAGESIZE;
625
626 retval = lpcspifi_set_hw_mode(bank);
627 if (retval != ERROR_OK)
628 return retval;
629
630 /* see contrib/loaders/flash/lpcspifi_write.S for src */
631 static const uint8_t lpcspifi_flash_write_code[] = {
632 0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x08, 0x0a,
633 0x4f, 0xf0, 0xea, 0x08, 0xca, 0xf8, 0x8c, 0x81,
634 0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x90, 0x81,
635 0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x94, 0x81,
636 0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x98, 0x81,
637 0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x9c, 0x81,
638 0x4f, 0xf0, 0x44, 0x08, 0xca, 0xf8, 0xa0, 0x81,
639 0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a,
640 0x4f, 0xf4, 0x00, 0x68, 0xca, 0xf8, 0x14, 0x80,
641 0x4f, 0xf4, 0x80, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a,
642 0x4f, 0xf0, 0xff, 0x08, 0xca, 0xf8, 0xab, 0x80,
643 0x4f, 0xf0, 0x00, 0x0a, 0xc4, 0xf2, 0x05, 0x0a,
644 0x4f, 0xf0, 0x00, 0x08, 0xc0, 0xf2, 0x00, 0x18,
645 0xca, 0xf8, 0x94, 0x80, 0x4f, 0xf4, 0x00, 0x5a,
646 0xc4, 0xf2, 0x05, 0x0a, 0x4f, 0xf0, 0x01, 0x08,
647 0xca, 0xf8, 0x00, 0x87, 0x4f, 0xf4, 0x40, 0x5a,
648 0xc4, 0xf2, 0x08, 0x0a, 0x4f, 0xf0, 0x07, 0x08,
649 0xca, 0xf8, 0x00, 0x80, 0x4f, 0xf0, 0x02, 0x08,
650 0xca, 0xf8, 0x10, 0x80, 0xca, 0xf8, 0x04, 0x80,
651 0x4f, 0xf0, 0x00, 0x0b, 0xa3, 0x44, 0x93, 0x45,
652 0x7f, 0xf6, 0xfc, 0xaf, 0x00, 0xf0, 0x6a, 0xf8,
653 0x4f, 0xf0, 0x06, 0x09, 0x00, 0xf0, 0x53, 0xf8,
654 0x00, 0xf0, 0x60, 0xf8, 0x00, 0xf0, 0x62, 0xf8,
655 0x4f, 0xf0, 0x05, 0x09, 0x00, 0xf0, 0x4b, 0xf8,
656 0x4f, 0xf0, 0x00, 0x09, 0x00, 0xf0, 0x47, 0xf8,
657 0x00, 0xf0, 0x54, 0xf8, 0x19, 0xf0, 0x02, 0x0f,
658 0x00, 0xf0, 0x5d, 0x80, 0x00, 0xf0, 0x52, 0xf8,
659 0x4f, 0xf0, 0x02, 0x09, 0x00, 0xf0, 0x3b, 0xf8,
660 0x4f, 0xea, 0x12, 0x49, 0x00, 0xf0, 0x37, 0xf8,
661 0x4f, 0xea, 0x12, 0x29, 0x00, 0xf0, 0x33, 0xf8,
662 0x4f, 0xea, 0x02, 0x09, 0x00, 0xf0, 0x2f, 0xf8,
663 0xd0, 0xf8, 0x00, 0x80, 0xb8, 0xf1, 0x00, 0x0f,
664 0x00, 0xf0, 0x47, 0x80, 0x47, 0x68, 0x47, 0x45,
665 0x3f, 0xf4, 0xf6, 0xaf, 0x17, 0xf8, 0x01, 0x9b,
666 0x00, 0xf0, 0x21, 0xf8, 0x8f, 0x42, 0x28, 0xbf,
667 0x00, 0xf1, 0x08, 0x07, 0x47, 0x60, 0x01, 0x3b,
668 0xbb, 0xb3, 0x02, 0xf1, 0x01, 0x02, 0x93, 0x45,
669 0x7f, 0xf4, 0xe6, 0xaf, 0x00, 0xf0, 0x22, 0xf8,
670 0xa3, 0x44, 0x00, 0xf0, 0x23, 0xf8, 0x4f, 0xf0,
671 0x05, 0x09, 0x00, 0xf0, 0x0c, 0xf8, 0x4f, 0xf0,
672 0x00, 0x09, 0x00, 0xf0, 0x08, 0xf8, 0x00, 0xf0,
673 0x15, 0xf8, 0x19, 0xf0, 0x01, 0x0f, 0x7f, 0xf4,
674 0xf0, 0xaf, 0xff, 0xf7, 0xa7, 0xbf, 0x4f, 0xf4,
675 0x40, 0x5a, 0xc4, 0xf2, 0x08, 0x0a, 0xca, 0xf8,
676 0x08, 0x90, 0xda, 0xf8, 0x0c, 0x90, 0x19, 0xf0,
677 0x10, 0x0f, 0x7f, 0xf4, 0xfa, 0xaf, 0xda, 0xf8,
678 0x08, 0x90, 0x70, 0x47, 0x4f, 0xf0, 0xff, 0x08,
679 0x00, 0xf0, 0x02, 0xb8, 0x4f, 0xf0, 0x00, 0x08,
680 0x4f, 0xf4, 0x80, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a,
681 0xca, 0xf8, 0xab, 0x80, 0x70, 0x47, 0x00, 0x20,
682 0x50, 0x60, 0xff, 0xf7, 0xef, 0xff, 0x30, 0x46,
683 0x00, 0xbe, 0xff, 0xff
684 };
685
686 if (target_alloc_working_area(target, sizeof(lpcspifi_flash_write_code),
687 &write_algorithm) != ERROR_OK) {
688 LOG_ERROR("Insufficient working area. You must configure"\
689 " a working area > %zdB in order to write to SPIFI flash.",
690 sizeof(lpcspifi_flash_write_code));
691 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
692 }
693
694 retval = target_write_buffer(target, write_algorithm->address,
695 sizeof(lpcspifi_flash_write_code),
696 lpcspifi_flash_write_code);
697 if (retval != ERROR_OK) {
698 target_free_working_area(target, write_algorithm);
699 return retval;
700 }
701
702 /* FIFO allocation */
703 fifo_size = target_get_working_area_avail(target);
704
705 if (fifo_size == 0) {
706 /* if we already allocated the writing code but failed to get fifo
707 * space, free the algorithm */
708 target_free_working_area(target, write_algorithm);
709
710 LOG_ERROR("Insufficient working area. Please allocate at least"\
711 " %zdB of working area to enable flash writes.",
712 sizeof(lpcspifi_flash_write_code) + 1
713 );
714
715 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
716 } else if (fifo_size < page_size)
717 LOG_WARNING("Working area size is limited; flash writes may be"\
718 " slow. Increase working area size to at least %zdB"\
719 " to reduce write times.",
720 (size_t)(sizeof(lpcspifi_flash_write_code) + page_size)
721 );
722 else if (fifo_size > 0x2000) /* Beyond this point, we start to get diminishing returns */
723 fifo_size = 0x2000;
724
725 if (target_alloc_working_area(target, fifo_size, &fifo) != ERROR_OK) {
726 target_free_working_area(target, write_algorithm);
727 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
728 }
729
730 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
731 armv7m_info.core_mode = ARM_MODE_THREAD;
732
733 init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* buffer start, status (out) */
734 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* buffer end */
735 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* target address */
736 init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT); /* count (halfword-16bit) */
737 init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT); /* page size */
738
739 buf_set_u32(reg_params[0].value, 0, 32, fifo->address);
740 buf_set_u32(reg_params[1].value, 0, 32, fifo->address + fifo->size);
741 buf_set_u32(reg_params[2].value, 0, 32, offset);
742 buf_set_u32(reg_params[3].value, 0, 32, count);
743 buf_set_u32(reg_params[4].value, 0, 32, page_size);
744
745 retval = target_run_flash_async_algorithm(target, buffer, count, 1,
746 0, NULL,
747 5, reg_params,
748 fifo->address, fifo->size,
749 write_algorithm->address, 0,
750 &armv7m_info
751 );
752
753 if (retval != ERROR_OK)
754 LOG_ERROR("Error executing flash write algorithm");
755
756 target_free_working_area(target, fifo);
757 target_free_working_area(target, write_algorithm);
758
759 destroy_reg_param(&reg_params[0]);
760 destroy_reg_param(&reg_params[1]);
761 destroy_reg_param(&reg_params[2]);
762 destroy_reg_param(&reg_params[3]);
763 destroy_reg_param(&reg_params[4]);
764
765 /* Switch to HW mode before return to prompt */
766 retval = lpcspifi_set_hw_mode(bank);
767 return retval;
768 }
769
770 /* Return ID of flash device */
771 /* On exit, SW mode is kept */
772 static int lpcspifi_read_flash_id(struct flash_bank *bank, uint32_t *id)
773 {
774 struct target *target = bank->target;
775 struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
776 uint32_t ssp_base = lpcspifi_info->ssp_base;
777 uint32_t io_base = lpcspifi_info->io_base;
778 uint32_t value;
779 uint8_t id_buf[3] = {0, 0, 0};
780 int retval;
781
782 if (target->state != TARGET_HALTED) {
783 LOG_ERROR("Target not halted");
784 return ERROR_TARGET_NOT_HALTED;
785 }
786
787 LOG_DEBUG("Getting ID");
788 retval = lpcspifi_set_sw_mode(bank);
789 if (retval != ERROR_OK)
790 return retval;
791
792 /* poll WIP */
793 if (retval == ERROR_OK)
794 retval = wait_till_ready(bank, SSP_PROBE_TIMEOUT);
795
796 /* Send SPI command "read ID" */
797 if (retval == ERROR_OK)
798 retval = ssp_setcs(target, io_base, 0);
799 if (retval == ERROR_OK)
800 retval = ssp_write_reg(target, ssp_base, SSP_DATA, SPIFLASH_READ_ID);
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
806 /* Dummy write to clock in data */
807 if (retval == ERROR_OK)
808 retval = ssp_write_reg(target, ssp_base, SSP_DATA, 0x00);
809 if (retval == ERROR_OK)
810 retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT);
811 if (retval == ERROR_OK)
812 retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value);
813 if (retval == ERROR_OK)
814 id_buf[0] = value;
815
816 /* Dummy write to clock in data */
817 if (retval == ERROR_OK)
818 retval = ssp_write_reg(target, ssp_base, SSP_DATA, 0x00);
819 if (retval == ERROR_OK)
820 retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT);
821 if (retval == ERROR_OK)
822 retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value);
823 if (retval == ERROR_OK)
824 id_buf[1] = value;
825
826 /* Dummy write to clock in data */
827 if (retval == ERROR_OK)
828 retval = ssp_write_reg(target, ssp_base, SSP_DATA, 0x00);
829 if (retval == ERROR_OK)
830 retval = poll_ssp_busy(target, ssp_base, SSP_CMD_TIMEOUT);
831 if (retval == ERROR_OK)
832 retval = ssp_read_reg(target, ssp_base, SSP_DATA, &value);
833 if (retval == ERROR_OK)
834 id_buf[2] = value;
835
836 if (retval == ERROR_OK)
837 retval = ssp_setcs(target, io_base, 1);
838 if (retval == ERROR_OK)
839 *id = id_buf[2] << 16 | id_buf[1] << 8 | id_buf[0];
840
841 return retval;
842 }
843
844 static int lpcspifi_probe(struct flash_bank *bank)
845 {
846 struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
847 struct flash_sector *sectors;
848 uint32_t id = 0; /* silence uninitialized warning */
849 int retval;
850 uint32_t sectorsize;
851
852 /* If we've already probed, we should be fine to skip this time. */
853 if (lpcspifi_info->probed)
854 return ERROR_OK;
855 lpcspifi_info->probed = 0;
856
857 lpcspifi_info->ssp_base = 0x40083000;
858 lpcspifi_info->io_base = 0x400F4000;
859 lpcspifi_info->ioconfig_base = 0x40086000;
860 lpcspifi_info->bank_num = bank->bank_number;
861
862 /* read and decode flash ID; returns in SW mode */
863 retval = lpcspifi_read_flash_id(bank, &id);
864 if (retval != ERROR_OK)
865 return retval;
866
867 retval = lpcspifi_set_hw_mode(bank);
868 if (retval != ERROR_OK)
869 return retval;
870
871 lpcspifi_info->dev = NULL;
872 for (const struct flash_device *p = flash_devices; p->name ; p++)
873 if (p->device_id == id) {
874 lpcspifi_info->dev = p;
875 break;
876 }
877
878 if (!lpcspifi_info->dev) {
879 LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", id);
880 return ERROR_FAIL;
881 }
882
883 LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")",
884 lpcspifi_info->dev->name, lpcspifi_info->dev->device_id);
885
886 /* Set correct size value */
887 bank->size = lpcspifi_info->dev->size_in_bytes;
888 if (bank->size <= (1UL << 16))
889 LOG_WARNING("device needs 2-byte addresses - not implemented");
890 if (bank->size > (1UL << 24))
891 LOG_WARNING("device needs paging or 4-byte addresses - not implemented");
892
893 /* if no sectors, treat whole bank as single sector */
894 sectorsize = lpcspifi_info->dev->sectorsize ?
895 lpcspifi_info->dev->sectorsize : lpcspifi_info->dev->size_in_bytes;
896
897 /* create and fill sectors array */
898 bank->num_sectors = lpcspifi_info->dev->size_in_bytes / sectorsize;
899 sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
900 if (sectors == NULL) {
901 LOG_ERROR("not enough memory");
902 return ERROR_FAIL;
903 }
904
905 for (int sector = 0; sector < bank->num_sectors; sector++) {
906 sectors[sector].offset = sector * sectorsize;
907 sectors[sector].size = sectorsize;
908 sectors[sector].is_erased = -1;
909 sectors[sector].is_protected = 0;
910 }
911
912 bank->sectors = sectors;
913
914 lpcspifi_info->probed = 1;
915 return ERROR_OK;
916 }
917
918 static int lpcspifi_auto_probe(struct flash_bank *bank)
919 {
920 struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
921 if (lpcspifi_info->probed)
922 return ERROR_OK;
923 return lpcspifi_probe(bank);
924 }
925
926 static int lpcspifi_protect_check(struct flash_bank *bank)
927 {
928 /* Nothing to do. Protection is only handled in SW. */
929 return ERROR_OK;
930 }
931
932 static int get_lpcspifi_info(struct flash_bank *bank, char *buf, int buf_size)
933 {
934 struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
935
936 if (!(lpcspifi_info->probed)) {
937 snprintf(buf, buf_size,
938 "\nSPIFI flash bank not probed yet\n");
939 return ERROR_OK;
940 }
941
942 snprintf(buf, buf_size, "\nSPIFI flash information:\n"
943 " Device \'%s\' (ID 0x%08" PRIx32 ")\n",
944 lpcspifi_info->dev->name, lpcspifi_info->dev->device_id);
945
946 return ERROR_OK;
947 }
948
949 struct flash_driver lpcspifi_flash = {
950 .name = "lpcspifi",
951 .flash_bank_command = lpcspifi_flash_bank_command,
952 .erase = lpcspifi_erase,
953 .protect = lpcspifi_protect,
954 .write = lpcspifi_write,
955 .read = default_flash_read,
956 .probe = lpcspifi_probe,
957 .auto_probe = lpcspifi_auto_probe,
958 .erase_check = default_flash_blank_check,
959 .protect_check = lpcspifi_protect_check,
960 .info = get_lpcspifi_info,
961 .free_driver_priv = default_flash_free_driver_priv,
962 };

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)