diff --git a/boards/arm/arty/CMakeLists.txt b/boards/arm/arty/CMakeLists.txt index b52b7027709..1c060b9bbac 100644 --- a/boards/arm/arty/CMakeLists.txt +++ b/boards/arm/arty/CMakeLists.txt @@ -1,5 +1,8 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_library() +zephyr_library_sources(board.c) + if((CONFIG_BOARD_ARTY_A7_ARM_DESIGNSTART_M1) AND (CONFIG_BUILD_OUTPUT_BIN)) # Generate zephyr.mem verilog memory hex dump file for initialising ITCM in # Xilinx Vivado. diff --git a/boards/arm/arty/Kconfig b/boards/arm/arty/Kconfig new file mode 100644 index 00000000000..78b1d148b51 --- /dev/null +++ b/boards/arm/arty/Kconfig @@ -0,0 +1,13 @@ +# Digilent Arty board configuration + +# Copyright (c) 2020 Henrik Brix Andersen +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_INIT_PRIORITY + int "Board initialization priority" + default 50 + depends on BOARD_ARTY_A7_ARM_DESIGNSTART_M1 || BOARD_ARTY_A7_ARM_DESIGNSTART_M3 + depends on "$(dt_nodelabel_enabled,daplink_qspi_mux)" + help + Board initialization priority. The board initialization must take + place after the GPIO driver is initialized. diff --git a/boards/arm/arty/Kconfig.defconfig b/boards/arm/arty/Kconfig.defconfig index 4cb802fcf82..a4dd1e747b3 100644 --- a/boards/arm/arty/Kconfig.defconfig +++ b/boards/arm/arty/Kconfig.defconfig @@ -25,6 +25,9 @@ config UART_XLNX_UARTLITE endif # SERIAL +config GPIO + default y if "$(dt_nodelabel_enabled,daplink_qspi_mux)" + if GPIO config GPIO_XLNX_AXI diff --git a/boards/arm/arty/board.c b/boards/arm/arty/board.c new file mode 100644 index 00000000000..04a46800483 --- /dev/null +++ b/boards/arm/arty/board.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2020 Henrik Brix Andersen + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +LOG_MODULE_REGISTER(board, CONFIG_LOG_DEFAULT_LEVEL); + +#include "board.h" + +#define DAPLINK_QSPI_MUX_NODE DT_NODELABEL(daplink_qspi_mux) + +#if DT_NODE_HAS_STATUS(DAPLINK_QSPI_MUX_NODE, okay) +int board_daplink_qspi_mux_select(enum board_daplink_qspi_mux_mode mode) +{ + const struct device *gpio; + gpio_flags_t flags; + int err; + + switch (mode) { + case BOARD_DAPLINK_QSPI_MUX_MODE_XIP: + flags = GPIO_OUTPUT_LOW; + break; + case BOARD_DAPLINK_QSPI_MUX_MODE_NORMAL: + flags = GPIO_OUTPUT_HIGH; + break; + default: + __ASSERT(0, "invalid mode"); + return -EINVAL; + }; + + gpio = device_get_binding(DT_GPIO_LABEL(DAPLINK_QSPI_MUX_NODE, + mux_gpios)); + if (!gpio) { + LOG_ERR("DAPLink QSPI MUX GPIO device '%s' not found", + DT_GPIO_LABEL(DAPLINK_QSPI_MUX_NODE, mux_gpios)); + return -EINVAL; + } + + err = gpio_config(gpio, DT_GPIO_PIN(DAPLINK_QSPI_MUX_NODE, mux_gpios), + DT_GPIO_FLAGS(DAPLINK_QSPI_MUX_NODE, mux_gpios) | + flags); + if (err) { + LOG_ERR("failed to configure DAPLink QSPI MUX GPIO (err %d)", + err); + return err; + } + + return 0; +} + +bool board_daplink_is_fitted(void) +{ + /* + * The DAPLINK_fitted_n signal is routed to an IRQ line. It is used as a + * level-detect non-interrupt signal to determine if the DAPLink shield + * is fitted. + */ + return !NVIC_GetPendingIRQ(DT_IRQN(DAPLINK_QSPI_MUX_NODE)); +} + +static int board_init(const struct device *dev) +{ + ARG_UNUSED(dev); + + /* + * Automatically select normal mode unless the DAPLink shield is fitted + * in which case the CPU will have the off-board QSPI NOR flash + * memory-mapped at 0x0. + */ + if (!board_daplink_is_fitted()) { + board_daplink_qspi_mux_select( + BOARD_DAPLINK_QSPI_MUX_MODE_NORMAL); + } + + return 0; +} + +SYS_INIT(board_init, POST_KERNEL, CONFIG_BOARD_INIT_PRIORITY); +#endif /* DT_NODE_HAS_STATUS(DAPLINK_QSPI_MUX_NODE, okay) */ diff --git a/boards/arm/arty/board.h b/boards/arm/arty/board.h new file mode 100644 index 00000000000..3cee697ec4d --- /dev/null +++ b/boards/arm/arty/board.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020 Henrik Brix Andersen + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __INC_BOARD_H +#define __INC_BOARD_H + +enum board_daplink_qspi_mux_mode { + /* eXecute-In-Place mode */ + BOARD_DAPLINK_QSPI_MUX_MODE_XIP, + /* Normal mode */ + BOARD_DAPLINK_QSPI_MUX_MODE_NORMAL, +}; + +/** + * @brief Select the mode of the DAPlink QSPI multiplexer. + * + * Note: The multiplexer mode must not be changed while executing code from the + * off-board QSPI flash in XIP mode. + * + * @param mode The multiplexer mode to be selected. + * + * @retval 0 If successful, negative errno otherwise. + */ +int board_daplink_qspi_mux_select(enum board_daplink_qspi_mux_mode mode); + +/** + * @brief Determine if the DAPlink shield is fitted. + * + * Determine if the DAPlink shield is fitted based on the state of the + * DAPLINK_fitted_n signal. + * + * @retval true If the DAPlink shield is fitted. + * @retval false If the DAPlink shield is not fitted. + */ +bool board_daplink_is_fitted(void); + +#endif /* __INC_BOARD_H */ diff --git a/boards/arm/arty/dts/arty_a7_arm_designstart.dtsi b/boards/arm/arty/dts/arty_a7_arm_designstart.dtsi index 42eff02b0ed..72214eeb2b0 100644 --- a/boards/arm/arty/dts/arty_a7_arm_designstart.dtsi +++ b/boards/arm/arty/dts/arty_a7_arm_designstart.dtsi @@ -135,7 +135,31 @@ }; }; + daplink_qspi_mux: daplink_qspi_mux { + compatible = "arm,daplink-qspi-mux"; + status = "disabled"; + interrupt-parent = <&nvic>; + interrupts = <7 0>; + mux-gpios = <&daplink_gpio0 0 GPIO_ACTIVE_HIGH>; + }; + soc { + daplink_gpio0: gpio@40010000 { + compatible = "xlnx,xps-gpio-1.00.a"; + status = "disabled"; + reg = <0x40010000 0x10000>; + label = "DAPLINK_GPIO_0"; + gpio-controller; + #gpio-cells = <2>; + + xlnx,all-inputs = <0x0>; + xlnx,all-outputs = <0x0>; + xlnx,dout-default = <0x0>; + xlnx,gpio-width = <0x20>; + xlnx,is-dual = <0x0>; + xlnx,tri-default = <0xffffffff>; + }; + daplink_quad_spi0: spi@40020000 { compatible = "xlnx,xps-spi-2.00.a"; status = "disabled"; diff --git a/boards/arm/arty/dts/bindings/arm,daplink-qspi-mux.yaml b/boards/arm/arty/dts/bindings/arm,daplink-qspi-mux.yaml new file mode 100644 index 00000000000..99392bf8829 --- /dev/null +++ b/boards/arm/arty/dts/bindings/arm,daplink-qspi-mux.yaml @@ -0,0 +1,21 @@ +# Copyright (c) 2020 Henrik Brix Andersen +# SPDX-License-Identifier: Apache-2.0 + +description: ARM DesignStart FPGA DAPLink QSPI bus multiplexer + +compatible: "arm,daplink-qspi-mux" + +include: base.yaml + +properties: + interrupts: + required: true + description: | + IRQ line connected to the level-detect non-interrupt DAPLink shield + fitted signal + + mux-gpios: + type: phandle-array + required: true + description: | + GPIO for controlling the DAPLink QSPI bus multiplexer