openocd: fix SPDX tag format for files .c
[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)
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                 3000, /* 3s timeout */
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 static int stack_grab_and_prep(struct flash_bank *bank)
142 {
143         struct rp2040_flash_bank *priv = bank->driver_priv;
144
145         /* target_alloc_working_area always allocates multiples of 4 bytes, so no worry about alignment */
146         const int STACK_SIZE = 256;
147         int err = target_alloc_working_area(bank->target, STACK_SIZE, &priv->stack);
148         if (err != ERROR_OK) {
149                 LOG_ERROR("Could not allocate stack for flash programming code");
150                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
151         }
152
153         LOG_DEBUG("Connecting internal flash");
154         err = rp2040_call_rom_func(bank->target, priv, priv->jump_connect_internal_flash, NULL, 0);
155         if (err != ERROR_OK) {
156                 LOG_ERROR("RP2040 erase: failed to connect internal flash");
157                 return err;
158         }
159
160         LOG_DEBUG("Kicking flash out of XIP mode");
161         err = rp2040_call_rom_func(bank->target, priv, priv->jump_flash_exit_xip, NULL, 0);
162         if (err != ERROR_OK) {
163                 LOG_ERROR("RP2040 erase: failed to exit flash XIP mode");
164                 return err;
165         }
166
167         return ERROR_OK;
168 }
169
170 static int rp2040_flash_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
171 {
172         LOG_DEBUG("Writing %d bytes starting at 0x%" PRIx32, count, offset);
173
174         struct rp2040_flash_bank *priv = bank->driver_priv;
175         struct target *target = bank->target;
176         struct working_area *bounce;
177
178         int err = stack_grab_and_prep(bank);
179         if (err != ERROR_OK)
180                 return err;
181
182         const unsigned int chunk_size = target_get_working_area_avail(target);
183         if (target_alloc_working_area(target, chunk_size, &bounce) != ERROR_OK) {
184                 LOG_ERROR("Could not allocate bounce buffer for flash programming. Can't continue");
185                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
186         }
187
188         LOG_DEBUG("Allocated flash bounce buffer @" TARGET_ADDR_FMT, bounce->address);
189
190         while (count > 0) {
191                 uint32_t write_size = count > chunk_size ? chunk_size : count;
192                 LOG_DEBUG("Writing %d bytes to offset 0x%" PRIx32, write_size, offset);
193                 err = target_write_buffer(target, bounce->address, write_size, buffer);
194                 if (err != ERROR_OK) {
195                         LOG_ERROR("Could not load data into target bounce buffer");
196                         break;
197                 }
198                 uint32_t args[3] = {
199                         offset, /* addr */
200                         bounce->address, /* data */
201                         write_size /* count */
202                 };
203                 err = rp2040_call_rom_func(target, priv, priv->jump_flash_range_program, args, ARRAY_SIZE(args));
204                 if (err != ERROR_OK) {
205                         LOG_ERROR("Failed to invoke flash programming code on target");
206                         break;
207                 }
208
209                 buffer += write_size;
210                 offset += write_size;
211                 count -= write_size;
212         }
213         target_free_working_area(target, bounce);
214
215         if (err != ERROR_OK)
216                 return err;
217
218         /* Flash is successfully programmed. We can now do a bit of poking to make the flash
219            contents visible to us via memory-mapped (XIP) interface in the 0x1... memory region */
220         LOG_DEBUG("Flushing flash cache after write behind");
221         err = rp2040_call_rom_func(bank->target, priv, priv->jump_flush_cache, NULL, 0);
222         if (err != ERROR_OK) {
223                 LOG_ERROR("RP2040 write: failed to flush flash cache");
224                 return err;
225         }
226         LOG_DEBUG("Configuring SSI for execute-in-place");
227         err = rp2040_call_rom_func(bank->target, priv, priv->jump_enter_cmd_xip, NULL, 0);
228         if (err != ERROR_OK)
229                 LOG_ERROR("RP2040 write: failed to flush flash cache");
230         return err;
231 }
232
233 static int rp2040_flash_erase(struct flash_bank *bank, unsigned int first, unsigned int last)
234 {
235         struct rp2040_flash_bank *priv = bank->driver_priv;
236         uint32_t start_addr = bank->sectors[first].offset;
237         uint32_t length = bank->sectors[last].offset + bank->sectors[last].size - start_addr;
238         LOG_DEBUG("RP2040 erase %d bytes starting at 0x%" PRIx32, length, start_addr);
239
240         int err = stack_grab_and_prep(bank);
241         if (err != ERROR_OK)
242                 return err;
243
244         LOG_DEBUG("Remote call flash_range_erase");
245
246         uint32_t args[4] = {
247                 bank->sectors[first].offset, /* addr */
248                 bank->sectors[last].offset + bank->sectors[last].size - bank->sectors[first].offset, /* count */
249                 priv->dev->sectorsize, /* block_size */
250                 priv->dev->erase_cmd /* block_cmd */
251         };
252
253         /*
254         The RP2040 Boot ROM provides a _flash_range_erase() API call documented in Section 2.8.3.1.3:
255         https://datasheets.raspberrypi.org/rp2040/rp2040-datasheet.pdf
256         and the particular source code for said Boot ROM function can be found here:
257         https://github.com/raspberrypi/pico-bootrom/blob/master/bootrom/program_flash_generic.c
258
259         In theory, the function algorithm provides for erasing both a smaller "sector" (4096 bytes) and
260         an optional larger "block" (size and command provided in args).  OpenOCD's spi.c only uses "block" sizes.
261         */
262
263         err = rp2040_call_rom_func(bank->target, priv, priv->jump_flash_range_erase, args, ARRAY_SIZE(args));
264
265         return err;
266 }
267
268 /* -----------------------------------------------------------------------------
269    Driver probing etc */
270
271 static int rp2040_ssel_active(struct target *target, bool active)
272 {
273         const target_addr_t qspi_ctrl_addr = 0x4001800c;
274         const uint32_t qspi_ctrl_outover_low  = 2UL << 8;
275         const uint32_t qspi_ctrl_outover_high = 3UL << 8;
276         uint32_t state = (active) ? qspi_ctrl_outover_low : qspi_ctrl_outover_high;
277         uint32_t val;
278
279         int err = target_read_u32(target, qspi_ctrl_addr, &val);
280         if (err != ERROR_OK)
281                 return err;
282
283         val = (val & ~qspi_ctrl_outover_high) | state;
284
285         err = target_write_u32(target, qspi_ctrl_addr, val);
286         if (err != ERROR_OK)
287                 return err;
288
289         return ERROR_OK;
290 }
291
292 static int rp2040_flash_probe(struct flash_bank *bank)
293 {
294         struct rp2040_flash_bank *priv = bank->driver_priv;
295         struct target *target = bank->target;
296
297         int err = rp2040_lookup_symbol(target, FUNC_DEBUG_TRAMPOLINE, &priv->jump_debug_trampoline);
298         if (err != ERROR_OK) {
299                 LOG_ERROR("Debug trampoline not found in RP2040 ROM.");
300                 return err;
301         }
302         priv->jump_debug_trampoline &= ~1u; /* mask off thumb bit */
303
304         err = rp2040_lookup_symbol(target, FUNC_DEBUG_TRAMPOLINE_END, &priv->jump_debug_trampoline_end);
305         if (err != ERROR_OK) {
306                 LOG_ERROR("Debug trampoline end not found in RP2040 ROM.");
307                 return err;
308         }
309         priv->jump_debug_trampoline_end &= ~1u; /* mask off thumb bit */
310
311         err = rp2040_lookup_symbol(target, FUNC_FLASH_EXIT_XIP, &priv->jump_flash_exit_xip);
312         if (err != ERROR_OK) {
313                 LOG_ERROR("Function FUNC_FLASH_EXIT_XIP not found in RP2040 ROM.");
314                 return err;
315         }
316
317         err = rp2040_lookup_symbol(target, FUNC_CONNECT_INTERNAL_FLASH, &priv->jump_connect_internal_flash);
318         if (err != ERROR_OK) {
319                 LOG_ERROR("Function FUNC_CONNECT_INTERNAL_FLASH not found in RP2040 ROM.");
320                 return err;
321         }
322
323         err = rp2040_lookup_symbol(target, FUNC_FLASH_RANGE_ERASE, &priv->jump_flash_range_erase);
324         if (err != ERROR_OK) {
325                 LOG_ERROR("Function FUNC_FLASH_RANGE_ERASE not found in RP2040 ROM.");
326                 return err;
327         }
328
329         err = rp2040_lookup_symbol(target, FUNC_FLASH_RANGE_PROGRAM, &priv->jump_flash_range_program);
330         if (err != ERROR_OK) {
331                 LOG_ERROR("Function FUNC_FLASH_RANGE_PROGRAM not found in RP2040 ROM.");
332                 return err;
333         }
334
335         err = rp2040_lookup_symbol(target, FUNC_FLASH_FLUSH_CACHE, &priv->jump_flush_cache);
336         if (err != ERROR_OK) {
337                 LOG_ERROR("Function FUNC_FLASH_FLUSH_CACHE not found in RP2040 ROM.");
338                 return err;
339         }
340
341         err = rp2040_lookup_symbol(target, FUNC_FLASH_ENTER_CMD_XIP, &priv->jump_enter_cmd_xip);
342         if (err != ERROR_OK) {
343                 LOG_ERROR("Function FUNC_FLASH_ENTER_CMD_XIP not found in RP2040 ROM.");
344                 return err;
345         }
346
347         err = stack_grab_and_prep(bank);
348         if (err != ERROR_OK)
349                 return err;
350
351         uint32_t device_id = 0;
352         const target_addr_t ssi_dr0 = 0x18000060;
353
354         err = rp2040_ssel_active(target, true);
355
356         /* write RDID request into SPI peripheral's FIFO */
357         for (int count = 0; (count < 4) && (err == ERROR_OK); count++)
358                 err = target_write_u32(target, ssi_dr0, SPIFLASH_READ_ID);
359
360         /* by this time, there is a receive FIFO entry for every write */
361         for (int count = 0; (count < 4) && (err == ERROR_OK); count++) {
362                 uint32_t status;
363                 err = target_read_u32(target, ssi_dr0, &status);
364
365                 device_id >>= 8;
366                 device_id |= (status & 0xFF) << 24;
367         }
368         device_id >>= 8;
369
370         err = rp2040_ssel_active(target, false);
371         if (err != ERROR_OK) {
372                 LOG_ERROR("SSEL inactive failed");
373                 return err;
374         }
375
376         /* search for a SPI flash Device ID match */
377         priv->dev = NULL;
378         for (const struct flash_device *p = flash_devices; p->name ; p++)
379                 if (p->device_id == device_id) {
380                         priv->dev = p;
381                         break;
382                 }
383
384         if (!priv->dev) {
385                 LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", device_id);
386                 return ERROR_FAIL;
387         }
388
389         LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")",
390                 priv->dev->name, priv->dev->device_id);
391
392         /* the Boot ROM flash_range_program() routine requires page alignment */
393         bank->write_start_alignment = priv->dev->pagesize;
394         bank->write_end_alignment = priv->dev->pagesize;
395
396         bank->size = priv->dev->size_in_bytes;
397
398         bank->num_sectors = bank->size / priv->dev->sectorsize;
399         LOG_INFO("RP2040 B0 Flash Probe: %d bytes @" TARGET_ADDR_FMT ", in %d sectors\n",
400                 bank->size, bank->base, bank->num_sectors);
401         bank->sectors = alloc_block_array(0, priv->dev->sectorsize, bank->num_sectors);
402         if (!bank->sectors)
403                 return ERROR_FAIL;
404
405         if (err == ERROR_OK)
406                 priv->probed = true;
407
408         return err;
409 }
410
411 static int rp2040_flash_auto_probe(struct flash_bank *bank)
412 {
413         struct rp2040_flash_bank *priv = bank->driver_priv;
414
415         if (priv->probed)
416                 return ERROR_OK;
417
418         return rp2040_flash_probe(bank);
419 }
420
421 static void rp2040_flash_free_driver_priv(struct flash_bank *bank)
422 {
423         free(bank->driver_priv);
424         bank->driver_priv = NULL;
425 }
426
427 /* -----------------------------------------------------------------------------
428    Driver boilerplate */
429
430 FLASH_BANK_COMMAND_HANDLER(rp2040_flash_bank_command)
431 {
432         struct rp2040_flash_bank *priv;
433         priv = malloc(sizeof(struct rp2040_flash_bank));
434         priv->probed = false;
435
436         /* Set up driver_priv */
437         bank->driver_priv = priv;
438
439         return ERROR_OK;
440 }
441
442 struct flash_driver rp2040_flash = {
443         .name = "rp2040_flash",
444         .flash_bank_command = rp2040_flash_bank_command,
445         .erase =  rp2040_flash_erase,
446         .write = rp2040_flash_write,
447         .read = default_flash_read,
448         .probe = rp2040_flash_probe,
449         .auto_probe = rp2040_flash_auto_probe,
450         .erase_check = default_flash_blank_check,
451         .free_driver_priv = rp2040_flash_free_driver_priv
452 };