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