1 /*
2  * Copyright (c) 2020 Henrik Brix Andersen <henrik@brixandersen.dk>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <cmsis_core.h>
8 #include <zephyr/device.h>
9 #include <zephyr/devicetree.h>
10 #include <zephyr/drivers/gpio.h>
11 #include <zephyr/init.h>
12 #include <zephyr/logging/log.h>
13 LOG_MODULE_REGISTER(board, CONFIG_LOG_DEFAULT_LEVEL);
14 
15 #include "board.h"
16 
17 #define DAPLINK_QSPI_MUX_NODE DT_NODELABEL(daplink_qspi_mux)
18 
19 #if DT_NODE_HAS_STATUS_OKAY(DAPLINK_QSPI_MUX_NODE)
board_daplink_qspi_mux_select(enum board_daplink_qspi_mux_mode mode)20 int board_daplink_qspi_mux_select(enum board_daplink_qspi_mux_mode mode)
21 {
22 	struct gpio_dt_spec mux = GPIO_DT_SPEC_GET(DAPLINK_QSPI_MUX_NODE, mux_gpios);
23 	gpio_flags_t flags = 0;
24 	int err;
25 
26 	switch (mode) {
27 	case BOARD_DAPLINK_QSPI_MUX_MODE_XIP:
28 		flags = GPIO_OUTPUT_LOW;
29 		break;
30 	case BOARD_DAPLINK_QSPI_MUX_MODE_NORMAL:
31 		flags = GPIO_OUTPUT_HIGH;
32 		break;
33 	default:
34 		__ASSERT(0, "invalid mode");
35 		return -EINVAL;
36 	}
37 
38 	if (!gpio_is_ready_dt(&mux)) {
39 		LOG_ERR("DAPLink QSPI MUX GPIO device not ready");
40 		return -EINVAL;
41 	}
42 
43 	err = gpio_pin_configure_dt(&mux, flags);
44 	if (err) {
45 		LOG_ERR("failed to configure DAPLink QSPI MUX GPIO (err %d)",
46 			err);
47 		return err;
48 	}
49 
50 	return 0;
51 }
52 
board_daplink_is_fitted(void)53 bool board_daplink_is_fitted(void)
54 {
55 	/*
56 	 * The DAPLINK_fitted_n signal is routed to an IRQ line. It is used as a
57 	 * level-detect non-interrupt signal to determine if the DAPLink shield
58 	 * is fitted.
59 	 */
60 	return !NVIC_GetPendingIRQ(DT_IRQN(DAPLINK_QSPI_MUX_NODE));
61 }
62 
board_init(void)63 static int board_init(void)
64 {
65 
66 	/*
67 	 * Automatically select normal mode unless the DAPLink shield is fitted
68 	 * in which case the CPU will have the off-board QSPI NOR flash
69 	 * memory-mapped at 0x0.
70 	 */
71 	if (!board_daplink_is_fitted()) {
72 		board_daplink_qspi_mux_select(
73 			BOARD_DAPLINK_QSPI_MUX_MODE_NORMAL);
74 	}
75 
76 	return 0;
77 }
78 
79 SYS_INIT(board_init, POST_KERNEL, CONFIG_BOARD_INIT_PRIORITY);
80 #endif /* DT_NODE_HAS_STATUS_OKAY(DAPLINK_QSPI_MUX_NODE) */
81