flash/nor/rp2040: check target halted before flash operation
[fw/openocd] / src / flash / nor / rp2040.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
6
7 #include "imp.h"
8 #include <helper/binarybuffer.h>
9 #include <target/algorithm.h>
10 #include <target/armv7m.h>
11 #include "spi.h"
12
13 /* NOTE THAT THIS CODE REQUIRES FLASH ROUTINES in BOOTROM WITH FUNCTION TABLE PTR AT 0x00000010
14    Your gdbinit should load the bootrom.elf if appropriate */
15
16 /* this is 'M' 'u', 1 (version) */
17 #define BOOTROM_MAGIC 0x01754d
18 #define BOOTROM_MAGIC_ADDR 0x00000010
19
20 /* Call a ROM function via the debug trampoline
21    Up to four arguments passed in r0...r3 as per ABI
22    Function address is passed in r7
23    the trampoline is needed because OpenOCD "algorithm" code insists on sw breakpoints. */
24
25 #define MAKE_TAG(a, b) (((b)<<8) | a)
26 #define FUNC_DEBUG_TRAMPOLINE       MAKE_TAG('D', 'T')
27 #define FUNC_DEBUG_TRAMPOLINE_END   MAKE_TAG('D', 'E')
28 #define FUNC_FLASH_EXIT_XIP         MAKE_TAG('E', 'X')
29 #define FUNC_CONNECT_INTERNAL_FLASH MAKE_TAG('I', 'F')
30 #define FUNC_FLASH_RANGE_ERASE      MAKE_TAG('R', 'E')
31 #define FUNC_FLASH_RANGE_PROGRAM    MAKE_TAG('R', 'P')
32 #define FUNC_FLASH_FLUSH_CACHE      MAKE_TAG('F', 'C')
33 #define FUNC_FLASH_ENTER_CMD_XIP    MAKE_TAG('C', 'X')
34
35 struct rp2040_flash_bank {
36         /* flag indicating successful flash probe */
37         bool probed;
38         /* stack used by Boot ROM calls */
39         struct working_area *stack;
40         /* function jump table populated by rp2040_flash_probe() */
41         uint16_t jump_debug_trampoline;
42         uint16_t jump_debug_trampoline_end;
43         uint16_t jump_flash_exit_xip;
44         uint16_t jump_connect_internal_flash;
45         uint16_t jump_flash_range_erase;
46         uint16_t jump_flash_range_program;
47         uint16_t jump_flush_cache;
48         uint16_t jump_enter_cmd_xip;
49         /* detected model of SPI flash */
50         const struct flash_device *dev;
51 };
52
53 static uint32_t rp2040_lookup_symbol(struct target *target, uint32_t tag, uint16_t *symbol)
54 {
55         uint32_t magic;
56         int err = target_read_u32(target, BOOTROM_MAGIC_ADDR, &magic);
57         if (err != ERROR_OK)
58                 return err;
59
60         magic &= 0xffffff; /* ignore bootrom version */
61         if (magic != BOOTROM_MAGIC) {
62                 if (!((magic ^ BOOTROM_MAGIC)&0xffff))
63                         LOG_ERROR("Incorrect RP2040 BOOT ROM version");
64                 else
65                         LOG_ERROR("RP2040 BOOT ROM not found");
66                 return ERROR_FAIL;
67         }
68
69         /* dereference the table pointer */
70         uint16_t table_entry;
71         err = target_read_u16(target, BOOTROM_MAGIC_ADDR + 4, &table_entry);
72         if (err != ERROR_OK)
73                 return err;
74
75         uint16_t entry_tag;
76         do {
77                 err = target_read_u16(target, table_entry, &entry_tag);
78                 if (err != ERROR_OK)
79                         return err;
80                 if (entry_tag == tag) {
81                         /* 16 bit symbol is next */
82                         return target_read_u16(target, table_entry + 2, symbol);
83                 }
84                 table_entry += 4;
85         } while (entry_tag);
86         return ERROR_FAIL;
87 }
88
89 static int rp2040_call_rom_func(struct target *target, struct rp2040_flash_bank *priv,
90                 uint16_t func_offset, uint32_t argdata[], unsigned int n_args, int timeout_ms)
91 {
92         char *regnames[4] = { "r0", "r1", "r2", "r3" };
93
94         assert(n_args <= ARRAY_SIZE(regnames)); /* only allow register arguments */
95
96         if (!priv->stack) {
97                 LOG_ERROR("no stack for flash programming code");
98                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
99         }
100         target_addr_t stacktop = priv->stack->address + priv->stack->size;
101
102         LOG_DEBUG("Calling ROM func @0x%" PRIx16 " with %d arguments", func_offset, n_args);
103         LOG_DEBUG("Calling on core \"%s\"", target->cmd_name);
104
105         struct reg_param args[ARRAY_SIZE(regnames) + 2];
106         struct armv7m_algorithm alg_info;
107
108         for (unsigned int i = 0; i < n_args; ++i) {
109                 init_reg_param(&args[i], regnames[i], 32, PARAM_OUT);
110                 buf_set_u32(args[i].value, 0, 32, argdata[i]);
111         }
112         /* Pass function pointer in r7 */
113         init_reg_param(&args[n_args], "r7", 32, PARAM_OUT);
114         buf_set_u32(args[n_args].value, 0, 32, func_offset);
115         init_reg_param(&args[n_args + 1], "sp", 32, PARAM_OUT);
116         buf_set_u32(args[n_args + 1].value, 0, 32, stacktop);
117
118
119         for (unsigned int i = 0; i < n_args + 2; ++i)
120                 LOG_DEBUG("Set %s = 0x%" PRIx32, args[i].reg_name, buf_get_u32(args[i].value, 0, 32));
121
122         /* Actually call the function */
123         alg_info.common_magic = ARMV7M_COMMON_MAGIC;
124         alg_info.core_mode = ARM_MODE_THREAD;
125         int err = target_run_algorithm(
126                 target,
127                 0, NULL,          /* No memory arguments */
128                 n_args + 1, args, /* User arguments + r7 */
129                 priv->jump_debug_trampoline, priv->jump_debug_trampoline_end,
130                 timeout_ms,
131                 &alg_info
132         );
133         for (unsigned int i = 0; i < n_args + 2; ++i)
134                 destroy_reg_param(&args[i]);
135         if (err != ERROR_OK)
136                 LOG_ERROR("Failed to invoke ROM function @0x%" PRIx16 "\n", func_offset);
137         return err;
138
139 }
140
141 /* Finalize flash write/erase/read ID
142  * - flush cache
143  * - enters memory-mapped (XIP) mode to make flash data visible
144  * - deallocates target ROM func stack if previously allocated
145  */
146 static int rp2040_finalize_stack_free(struct flash_bank *bank)
147 {
148         struct rp2040_flash_bank *priv = bank->driver_priv;
149         struct target *target = bank->target;
150
151         /* Always flush before returning to execute-in-place, to invalidate stale
152          * cache contents. The flush call also restores regular hardware-controlled
153          * chip select following a rp2040_flash_exit_xip().
154          */
155         LOG_DEBUG("Flushing flash cache after write behind");
156         int err = rp2040_call_rom_func(target, priv, priv->jump_flush_cache, NULL, 0, 1000);
157         if (err != ERROR_OK) {
158                 LOG_ERROR("Failed to flush flash cache");
159                 /* Intentionally continue after error and try to setup xip anyway */
160         }
161
162         LOG_DEBUG("Configuring SSI for execute-in-place");
163         err = rp2040_call_rom_func(target, priv, priv->jump_enter_cmd_xip, NULL, 0, 1000);
164         if (err != ERROR_OK)
165                 LOG_ERROR("Failed to set SSI to XIP mode");
166
167         target_free_working_area(target, priv->stack);
168         priv->stack = NULL;
169         return err;
170 }
171
172 /* Prepare flash write/erase/read ID
173  * - allocates a stack for target ROM func
174  * - switches the SPI interface from memory-mapped mode to direct command mode
175  * Always pair with a call of rp2040_finalize_stack_free()
176  * after flash operation finishes or fails.
177  */
178 static int rp2040_stack_grab_and_prep(struct flash_bank *bank)
179 {
180         struct rp2040_flash_bank *priv = bank->driver_priv;
181         struct target *target = bank->target;
182
183         /* target_alloc_working_area always allocates multiples of 4 bytes, so no worry about alignment */
184         const int STACK_SIZE = 256;
185         int err = target_alloc_working_area(target, STACK_SIZE, &priv->stack);
186         if (err != ERROR_OK) {
187                 LOG_ERROR("Could not allocate stack for flash programming code");
188                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
189         }
190
191         LOG_DEBUG("Connecting internal flash");
192         err = rp2040_call_rom_func(target, priv, priv->jump_connect_internal_flash, NULL, 0, 1000);
193         if (err != ERROR_OK) {
194                 LOG_ERROR("Failed to connect internal flash");
195                 return err;
196         }
197
198         LOG_DEBUG("Kicking flash out of XIP mode");
199         err = rp2040_call_rom_func(target, priv, priv->jump_flash_exit_xip, NULL, 0, 1000);
200         if (err != ERROR_OK) {
201                 LOG_ERROR("Failed to exit flash XIP mode");
202                 return err;
203         }
204
205         return ERROR_OK;
206 }
207
208 static int rp2040_flash_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
209 {
210         LOG_DEBUG("Writing %d bytes starting at 0x%" PRIx32, count, offset);
211
212         struct rp2040_flash_bank *priv = bank->driver_priv;
213         struct target *target = bank->target;
214
215         if (target->state != TARGET_HALTED) {
216                 LOG_ERROR("Target not halted");
217                 return ERROR_TARGET_NOT_HALTED;
218         }
219
220         struct working_area *bounce = NULL;
221
222         int err = rp2040_stack_grab_and_prep(bank);
223         if (err != ERROR_OK)
224                 goto cleanup;
225
226         unsigned int avail_pages = target_get_working_area_avail(target) / priv->dev->pagesize;
227         /* We try to allocate working area rounded down to device page size,
228          * al least 1 page, at most the write data size
229          */
230         unsigned int chunk_size = MIN(MAX(avail_pages, 1) * priv->dev->pagesize, count);
231         err = target_alloc_working_area(target, chunk_size, &bounce);
232         if (err != ERROR_OK) {
233                 LOG_ERROR("Could not allocate bounce buffer for flash programming. Can't continue");
234                 goto cleanup;
235         }
236
237         LOG_DEBUG("Allocated flash bounce buffer @" TARGET_ADDR_FMT, bounce->address);
238
239         while (count > 0) {
240                 uint32_t write_size = count > chunk_size ? chunk_size : count;
241                 LOG_DEBUG("Writing %d bytes to offset 0x%" PRIx32, write_size, offset);
242                 err = target_write_buffer(target, bounce->address, write_size, buffer);
243                 if (err != ERROR_OK) {
244                         LOG_ERROR("Could not load data into target bounce buffer");
245                         break;
246                 }
247                 uint32_t args[3] = {
248                         offset, /* addr */
249                         bounce->address, /* data */
250                         write_size /* count */
251                 };
252                 err = rp2040_call_rom_func(target, priv, priv->jump_flash_range_program,
253                                                                  args, ARRAY_SIZE(args), 3000);
254                 if (err != ERROR_OK) {
255                         LOG_ERROR("Failed to invoke flash programming code on target");
256                         break;
257                 }
258
259                 buffer += write_size;
260                 offset += write_size;
261                 count -= write_size;
262         }
263
264 cleanup:
265         target_free_working_area(target, bounce);
266
267         rp2040_finalize_stack_free(bank);
268
269         return err;
270 }
271
272 static int rp2040_flash_erase(struct flash_bank *bank, unsigned int first, unsigned int last)
273 {
274         struct rp2040_flash_bank *priv = bank->driver_priv;
275         struct target *target = bank->target;
276
277         if (target->state != TARGET_HALTED) {
278                 LOG_ERROR("Target not halted");
279                 return ERROR_TARGET_NOT_HALTED;
280         }
281
282         uint32_t start_addr = bank->sectors[first].offset;
283         uint32_t length = bank->sectors[last].offset + bank->sectors[last].size - start_addr;
284         LOG_DEBUG("RP2040 erase %d bytes starting at 0x%" PRIx32, length, start_addr);
285
286         int err = rp2040_stack_grab_and_prep(bank);
287         if (err != ERROR_OK)
288                 goto cleanup;
289
290         LOG_DEBUG("Remote call flash_range_erase");
291
292         uint32_t args[4] = {
293                 bank->sectors[first].offset, /* addr */
294                 bank->sectors[last].offset + bank->sectors[last].size - bank->sectors[first].offset, /* count */
295                 priv->dev->sectorsize, /* block_size */
296                 priv->dev->erase_cmd /* block_cmd */
297         };
298
299         /*
300         The RP2040 Boot ROM provides a _flash_range_erase() API call documented in Section 2.8.3.1.3:
301         https://datasheets.raspberrypi.org/rp2040/rp2040-datasheet.pdf
302         and the particular source code for said Boot ROM function can be found here:
303         https://github.com/raspberrypi/pico-bootrom/blob/master/bootrom/program_flash_generic.c
304
305         In theory, the function algorithm provides for erasing both a smaller "sector" (4096 bytes) and
306         an optional larger "block" (size and command provided in args).
307         */
308
309         int timeout_ms = 2000 * (last - first) + 1000;
310         err = rp2040_call_rom_func(target, priv, priv->jump_flash_range_erase,
311                                                         args, ARRAY_SIZE(args), timeout_ms);
312
313 cleanup:
314         rp2040_finalize_stack_free(bank);
315
316         return err;
317 }
318
319 /* -----------------------------------------------------------------------------
320    Driver probing etc */
321
322 static int rp2040_ssel_active(struct target *target, bool active)
323 {
324         const target_addr_t qspi_ctrl_addr = 0x4001800c;
325         const uint32_t qspi_ctrl_outover_low  = 2UL << 8;
326         const uint32_t qspi_ctrl_outover_high = 3UL << 8;
327         uint32_t state = (active) ? qspi_ctrl_outover_low : qspi_ctrl_outover_high;
328         uint32_t val;
329
330         int err = target_read_u32(target, qspi_ctrl_addr, &val);
331         if (err != ERROR_OK)
332                 return err;
333
334         val = (val & ~qspi_ctrl_outover_high) | state;
335
336         err = target_write_u32(target, qspi_ctrl_addr, val);
337         if (err != ERROR_OK)
338                 return err;
339
340         return ERROR_OK;
341 }
342
343 static int rp2040_spi_read_flash_id(struct target *target, uint32_t *devid)
344 {
345         uint32_t device_id = 0;
346         const target_addr_t ssi_dr0 = 0x18000060;
347
348         int err = rp2040_ssel_active(target, true);
349
350         /* write RDID request into SPI peripheral's FIFO */
351         for (int count = 0; (count < 4) && (err == ERROR_OK); count++)
352                 err = target_write_u32(target, ssi_dr0, SPIFLASH_READ_ID);
353
354         /* by this time, there is a receive FIFO entry for every write */
355         for (int count = 0; (count < 4) && (err == ERROR_OK); count++) {
356                 uint32_t status;
357                 err = target_read_u32(target, ssi_dr0, &status);
358
359                 device_id >>= 8;
360                 device_id |= (status & 0xFF) << 24;
361         }
362
363         if (err == ERROR_OK)
364                 *devid = device_id >> 8;
365
366         int err2 = rp2040_ssel_active(target, false);
367         if (err2 != ERROR_OK)
368                 LOG_ERROR("SSEL inactive failed");
369
370         return err;
371 }
372
373 static int rp2040_flash_probe(struct flash_bank *bank)
374 {
375         struct rp2040_flash_bank *priv = bank->driver_priv;
376         struct target *target = bank->target;
377
378         if (target->state != TARGET_HALTED) {
379                 LOG_ERROR("Target not halted");
380                 return ERROR_TARGET_NOT_HALTED;
381         }
382
383         int err = rp2040_lookup_symbol(target, FUNC_DEBUG_TRAMPOLINE, &priv->jump_debug_trampoline);
384         if (err != ERROR_OK) {
385                 LOG_ERROR("Debug trampoline not found in RP2040 ROM.");
386                 return err;
387         }
388         priv->jump_debug_trampoline &= ~1u; /* mask off thumb bit */
389
390         err = rp2040_lookup_symbol(target, FUNC_DEBUG_TRAMPOLINE_END, &priv->jump_debug_trampoline_end);
391         if (err != ERROR_OK) {
392                 LOG_ERROR("Debug trampoline end not found in RP2040 ROM.");
393                 return err;
394         }
395         priv->jump_debug_trampoline_end &= ~1u; /* mask off thumb bit */
396
397         err = rp2040_lookup_symbol(target, FUNC_FLASH_EXIT_XIP, &priv->jump_flash_exit_xip);
398         if (err != ERROR_OK) {
399                 LOG_ERROR("Function FUNC_FLASH_EXIT_XIP not found in RP2040 ROM.");
400                 return err;
401         }
402
403         err = rp2040_lookup_symbol(target, FUNC_CONNECT_INTERNAL_FLASH, &priv->jump_connect_internal_flash);
404         if (err != ERROR_OK) {
405                 LOG_ERROR("Function FUNC_CONNECT_INTERNAL_FLASH not found in RP2040 ROM.");
406                 return err;
407         }
408
409         err = rp2040_lookup_symbol(target, FUNC_FLASH_RANGE_ERASE, &priv->jump_flash_range_erase);
410         if (err != ERROR_OK) {
411                 LOG_ERROR("Function FUNC_FLASH_RANGE_ERASE not found in RP2040 ROM.");
412                 return err;
413         }
414
415         err = rp2040_lookup_symbol(target, FUNC_FLASH_RANGE_PROGRAM, &priv->jump_flash_range_program);
416         if (err != ERROR_OK) {
417                 LOG_ERROR("Function FUNC_FLASH_RANGE_PROGRAM not found in RP2040 ROM.");
418                 return err;
419         }
420
421         err = rp2040_lookup_symbol(target, FUNC_FLASH_FLUSH_CACHE, &priv->jump_flush_cache);
422         if (err != ERROR_OK) {
423                 LOG_ERROR("Function FUNC_FLASH_FLUSH_CACHE not found in RP2040 ROM.");
424                 return err;
425         }
426
427         err = rp2040_lookup_symbol(target, FUNC_FLASH_ENTER_CMD_XIP, &priv->jump_enter_cmd_xip);
428         if (err != ERROR_OK) {
429                 LOG_ERROR("Function FUNC_FLASH_ENTER_CMD_XIP not found in RP2040 ROM.");
430                 return err;
431         }
432
433         err = rp2040_stack_grab_and_prep(bank);
434
435         uint32_t device_id = 0;
436         if (err == ERROR_OK)
437                 err = rp2040_spi_read_flash_id(target, &device_id);
438
439         rp2040_finalize_stack_free(bank);
440
441         if (err != ERROR_OK)
442                 return err;
443
444         /* search for a SPI flash Device ID match */
445         priv->dev = NULL;
446         for (const struct flash_device *p = flash_devices; p->name ; p++)
447                 if (p->device_id == device_id) {
448                         priv->dev = p;
449                         break;
450                 }
451
452         if (!priv->dev) {
453                 LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", device_id);
454                 return ERROR_FAIL;
455         }
456
457         LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")",
458                 priv->dev->name, priv->dev->device_id);
459
460         /* the Boot ROM flash_range_program() routine requires page alignment */
461         bank->write_start_alignment = priv->dev->pagesize;
462         bank->write_end_alignment = priv->dev->pagesize;
463
464         bank->size = priv->dev->size_in_bytes;
465
466         bank->num_sectors = bank->size / priv->dev->sectorsize;
467         LOG_INFO("RP2040 B0 Flash Probe: %d bytes @" TARGET_ADDR_FMT ", in %d sectors\n",
468                 bank->size, bank->base, bank->num_sectors);
469         bank->sectors = alloc_block_array(0, priv->dev->sectorsize, bank->num_sectors);
470         if (!bank->sectors)
471                 return ERROR_FAIL;
472
473         if (err == ERROR_OK)
474                 priv->probed = true;
475
476         return err;
477 }
478
479 static int rp2040_flash_auto_probe(struct flash_bank *bank)
480 {
481         struct rp2040_flash_bank *priv = bank->driver_priv;
482
483         if (priv->probed)
484                 return ERROR_OK;
485
486         return rp2040_flash_probe(bank);
487 }
488
489 static void rp2040_flash_free_driver_priv(struct flash_bank *bank)
490 {
491         free(bank->driver_priv);
492         bank->driver_priv = NULL;
493 }
494
495 /* -----------------------------------------------------------------------------
496    Driver boilerplate */
497
498 FLASH_BANK_COMMAND_HANDLER(rp2040_flash_bank_command)
499 {
500         struct rp2040_flash_bank *priv;
501         priv = malloc(sizeof(struct rp2040_flash_bank));
502         priv->probed = false;
503
504         /* Set up driver_priv */
505         bank->driver_priv = priv;
506
507         return ERROR_OK;
508 }
509
510 struct flash_driver rp2040_flash = {
511         .name = "rp2040_flash",
512         .flash_bank_command = rp2040_flash_bank_command,
513         .erase =  rp2040_flash_erase,
514         .write = rp2040_flash_write,
515         .read = default_flash_read,
516         .probe = rp2040_flash_probe,
517         .auto_probe = rp2040_flash_auto_probe,
518         .erase_check = default_flash_blank_check,
519         .free_driver_priv = rp2040_flash_free_driver_priv
520 };