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

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)