1 /*
2  * Copyright (c) 2020 Google LLC.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <soc.h>
8 #include <zephyr/drivers/uart/cdc_acm.h>
9 #include <zephyr/drivers/usb/usb_dc.h>
10 #include <zephyr/init.h>
11 #include <zephyr/usb/class/usb_cdc.h>
12 
13 /*
14  * Magic value that causes the bootloader to stay in bootloader mode instead of
15  * starting the application.
16  */
17 #if CONFIG_BOOTLOADER_BOSSA_ADAFRUIT_UF2
18 #define DOUBLE_TAP_MAGIC 0xf01669ef
19 #elif CONFIG_BOOTLOADER_BOSSA_ARDUINO
20 #define DOUBLE_TAP_MAGIC 0x07738135
21 #else
22 #error Unsupported BOSSA bootloader variant
23 #endif
24 
25 #if defined(CONFIG_BOOTLOADER_BOSSA_DEVICE_NAME)
26 
bossa_reset(const struct device * dev,uint32_t rate)27 static void bossa_reset(const struct device *dev, uint32_t rate)
28 {
29 	uint32_t *top;
30 
31 	if (rate != 1200) {
32 		return;
33 	}
34 
35 	/* The programmer set the baud rate to 1200 baud.  Reset into the
36 	 * bootloader.
37 	 */
38 	usb_dc_detach();
39 
40 	top = (uint32_t *)(DT_REG_ADDR(DT_NODELABEL(sram0)) +
41 			   DT_REG_SIZE(DT_NODELABEL(sram0)));
42 	top[-1] = DOUBLE_TAP_MAGIC;
43 
44 	NVIC_SystemReset();
45 }
46 
bossa_init(void)47 static int bossa_init(void)
48 {
49 	const struct device *dev =
50 		device_get_binding(CONFIG_BOOTLOADER_BOSSA_DEVICE_NAME);
51 
52 	if (dev == NULL) {
53 		return -ENODEV;
54 	}
55 
56 	return cdc_acm_dte_rate_callback_set(dev, bossa_reset);
57 }
58 
59 SYS_INIT(bossa_init, APPLICATION, 0);
60 
61 #endif /* CONFIG_BOOTLOADER_BOSSA_DEVICE_NAME */
62