diff --git a/applications/hpf/gpio/src/main.c b/applications/hpf/gpio/src/main.c index d3fc7b8764c1..7a4694418084 100644 --- a/applications/hpf/gpio/src/main.c +++ b/applications/hpf/gpio/src/main.c @@ -25,45 +25,6 @@ #define VEVIF_IRQN(vevif) VEVIF_IRQN_1(vevif) #define VEVIF_IRQN_1(vevif) VPRCLIC_##vevif##_IRQn -#if defined(CONFIG_SOC_NRF54L15) || defined(CONFIG_SOC_NRF54LM20A) || defined(CONFIG_SOC_NRF54LM20B) -static const uint8_t pin_to_vio_map[] = { - 4, /* Physical pin 0 */ - 0, /* Physical pin 1 */ - 1, /* Physical pin 2 */ - 3, /* Physical pin 3 */ - 2, /* Physical pin 4 */ - 5, /* Physical pin 5 */ - 6, /* Physical pin 6 */ - 7, /* Physical pin 7 */ - 8, /* Physical pin 8 */ - 9, /* Physical pin 9 */ - 10, /* Physical pin 10 */ -}; - -#define VIO_PORT 2 -#define VIO_PIN_OFFSET 0 - -#elif defined(CONFIG_SOC_NRF54LV10A) -static const uint8_t pin_to_vio_map[] = { - 4, /* Physical pin 15 */ - 0, /* Physical pin 16 */ - 1, /* Physical pin 17 */ - 3, /* Physical pin 18 */ - 2, /* Physical pin 19 */ - 5, /* Physical pin 20 */ - 6, /* Physical pin 21 */ - 7, /* Physical pin 22 */ - 8, /* Physical pin 23 */ - 9, /* Physical pin 24 */ -}; - -#define VIO_PORT 1 -#define VIO_PIN_OFFSET 15 - -#else -#error "Unsupported target" -#endif - #define VIO_INDEX_INVALID UINT8_MAX #define VIO_PIN_MASK_INVALID UINT16_MAX diff --git a/applications/hpf/mspi/Kconfig b/applications/hpf/mspi/Kconfig index 4394abc13667..2f73db4aacb5 100644 --- a/applications/hpf/mspi/Kconfig +++ b/applications/hpf/mspi/Kconfig @@ -5,7 +5,7 @@ config HPF_MSPI_MAX_RESPONSE_SIZE config HPF_MSPI_IPC_NO_COPY bool "IPC no copy mode" default y - depends on SOC_NRF54L15 || SOC_NRF54LM20A || SOC_NRF54LM20B + depends on SOC_NRF54L15 || SOC_NRF54LM20A || SOC_NRF54LM20B || SOC_NRF54LV10A help If y Data is passed through IPC by reference, this requires both cores to be able to access each others memory spaces. @@ -18,6 +18,14 @@ config HPF_MSPI_FAULT_TIMER Timer is used to detect application faults. If the timer expires, the application is considered to be in a fault state. +config HPF_MSPI_CORRECT_FOR_EXTRA_VTIM_CYCLE + bool "HPF MSPI application should take into account an extra clock cycle output by VTIM." + default y if SOC_NRF54L15 + default n + help + If enabled, HPF MSPI application corrects for an extra clock cycle generated by VTIM + real-time peripheral. + config HPF_DEVELOPER_MODE bool "HPF developer mode" help diff --git a/applications/hpf/mspi/README.rst b/applications/hpf/mspi/README.rst index 38978308cd59..801ad33ac503 100644 --- a/applications/hpf/mspi/README.rst +++ b/applications/hpf/mspi/README.rst @@ -9,7 +9,7 @@ High-Performance Framework MSPI .. caution:: - The High-Performance Framework (HPF) support in the |NCS| is :ref:`experimental ` and is limited to the nRF54L15 and nRF54LM20A/B devices. + The High-Performance Framework (HPF) support in the |NCS| is :ref:`experimental ` and is limited to the nRF54L15, nRF54LM20A/B, and nRF54LV10A devices. This application demonstrates how to write a :ref:`High-Performance Framework (HPF) ` application and communicate with it. The application implements a subset of the Zephyr MSPI API. @@ -361,7 +361,7 @@ The following tests utilize the MSPI driver along with this application: * ``nrf/tests/zephyr/drivers/mspi/flash`` * ``nrf/tests/zephyr/drivers/flash/common`` -These tests report results through serial port (the USB debug port on the nRF54L15 or nRF54LM20 DK). +These tests report results over the serial port, using the USB debug port on the nRF54L15, nRF54LM20, or nRF54LV10 DK. Dependencies ************ @@ -398,3 +398,4 @@ FLPR application HRT * :file:`applications/hpf/mspi/src/hrt/hrt-nrf54l15.s` * :file:`applications/hpf/mspi/src/hrt/hrt-nrf54lm20a.s` * :file:`applications/hpf/mspi/src/hrt/hrt-nrf54lm20b.s` + * :file:`applications/hpf/mspi/src/hrt/hrt-nrf54lv10a.s` diff --git a/applications/hpf/mspi/boards/nrf54lv10dk_nrf54lv10a_cpuflpr.overlay b/applications/hpf/mspi/boards/nrf54lv10dk_nrf54lv10a_cpuflpr.overlay new file mode 100644 index 000000000000..199d156dda2e --- /dev/null +++ b/applications/hpf/mspi/boards/nrf54lv10dk_nrf54lv10a_cpuflpr.overlay @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/ { + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + + sram_tx: memory@2002b000 { + reg = <0x2002b000 0x07f0>; + }; + + sram_rx: memory@2002b7f0 { + reg = <0x2002b7f0 0x07f0>; + }; + + cpuflpr_error_code: memory@2002bfe0 { + reg = <0x2002bfe0 0x0020>; /* 32 bytes */ + }; + }; + + ipc { + ipc0: ipc0 { + compatible = "zephyr,ipc-icmsg"; + tx-region = <&sram_tx>; + rx-region = <&sram_rx>; + mboxes = <&cpuflpr_vevif_rx 16>, <&cpuflpr_vevif_tx 20>; + mbox-names = "rx", "tx"; + status = "okay"; + }; + }; +}; + +&cpuflpr_rram { + reg = <0xf9400 DT_SIZE_K(15)>; + ranges = <0x0 0xf9400 DT_SIZE_K(15)>; +}; + +&cpuflpr_code_partition { + reg = <0x0 DT_SIZE_K(15)>; +}; + +&cpuflpr_sram { + reg = <0x2002c000 DT_SIZE_K(15)>; + ranges = <0x0 0x2002c000 0x3c00>; +}; + +&cpuflpr_vevif_rx { + status = "okay"; + interrupts = <16 NRF_DEFAULT_IRQ_PRIORITY>; + nordic,tasks = <1>; + nordic,tasks-mask = <0x00010000>; +}; + +&cpuflpr_vevif_tx { + status = "okay"; +}; + +&gpio0 { + status = "disabled"; +}; + +&gpio1 { + status = "disabled"; +}; + +&gpiote20 { + status = "disabled"; +}; + +&gpiote30 { + status = "disabled"; +}; + +&grtc { + status = "disabled"; +}; + +&uart20 { + status = "disabled"; +}; + +&uart30 { + status = "disabled"; +}; diff --git a/applications/hpf/mspi/sample.yaml b/applications/hpf/mspi/sample.yaml index 2ada8576bc0a..e5739c2fd5d0 100644 --- a/applications/hpf/mspi/sample.yaml +++ b/applications/hpf/mspi/sample.yaml @@ -12,6 +12,7 @@ tests: - nrf54l15dk/nrf54l15/cpuflpr - nrf54lm20dk/nrf54lm20a/cpuflpr - nrf54lm20dk/nrf54lm20b/cpuflpr + - nrf54lv10dk/nrf54lv10a/cpuflpr tags: - ci_build - sysbuild diff --git a/applications/hpf/mspi/src/hrt/hrt-nrf54lv10a.s b/applications/hpf/mspi/src/hrt/hrt-nrf54lv10a.s new file mode 100644 index 000000000000..cf09170e3dcf --- /dev/null +++ b/applications/hpf/mspi/src/hrt/hrt-nrf54lv10a.s @@ -0,0 +1,656 @@ + .file "hrt.c" + .option nopic + .attribute arch, "rv32e1p9_m2p0_c2p0_zicsr2p0" + .attribute unaligned_access, 0 + .attribute stack_align, 4 + .text + .section .text.hrt_tx,"ax",@progbits + .align 1 + .type hrt_tx, @function +hrt_tx: + lw a5,4(a0) + addi sp,sp,-16 + sw s0,12(sp) + sw s1,8(sp) + sw a2,0(sp) + beq a5,zero,.L1 + li a4,32 + div a4,a4,a1 + lui t2,%hi(xfer_shift_ctrl) + addi a2,t2,%lo(xfer_shift_ctrl) + lbu s1,2(a2) + lbu a5,1(a2) + sb a1,2(a2) + lbu a2,3(a2) + li t1,3145728 + slli a5,a5,8 + slli a2,a2,20 + and a2,a2,t1 + andi a5,a5,1792 + or a5,a5,a2 + li t1,126976 + slli a2,a1,12 + and a2,a2,t1 + or a5,a5,a2 + addi a4,a4,-1 + andi a4,a4,0xff + sb a4,%lo(xfer_shift_ctrl)(t2) + andi a4,a4,63 + or a5,a5,a4 + #APP + csrw 3019, a5 + #NO_APP + li a4,2031616 + slli a5,a1,16 + and a5,a5,a4 + ori a5,a5,4 + sw a5,4(sp) + li t1,0 + addi t0,t2,%lo(xfer_shift_ctrl) +.L3: + lw a5,4(a0) + bltu t1,a5,.L14 +.L1: + lw s0,12(sp) + lw s1,8(sp) + addi sp,sp,16 + jr ra +.L14: + lw a5,4(a0) + li a4,1 + sub a5,a5,t1 + beq a5,a4,.L4 + li a4,2 + beq a5,a4,.L5 +.L6: + lw a4,0(a0) + li a5,0 + beq a4,zero,.L7 + lw a5,0(a0) + slli a4,t1,2 + add a5,a5,a4 + lw a5,0(a5) + j .L7 +.L4: + lbu a2,1(t0) + lbu a5,2(t0) + li s0,126976 + slli a2,a2,8 + slli a5,a5,12 + and a5,a5,s0 + andi a2,a2,1792 + or a2,a2,a5 + lbu a4,8(a0) + lbu a5,3(t0) + li s0,3145728 + addi a4,a4,-1 + slli a5,a5,20 + andi a4,a4,0xff + and a5,a5,s0 + sb a4,%lo(xfer_shift_ctrl)(t2) + or a5,a2,a5 + andi a4,a4,63 + or a5,a5,a4 + #APP + csrw 3019, a5 + #NO_APP + lw a5,12(a0) +.L7: + beq a1,s1,.L8 +.L9: + #APP + csrr a4, 3022 + #NO_APP + andi a4,a4,0xff + bne a4,zero,.L9 + lw a4,4(sp) + #APP + csrw 3043, a4 + #NO_APP + mv s1,a1 +.L8: + lbu a4,16(a0) + andi a2,a4,0xff + beq a4,zero,.L10 + li a4,1 + bne a2,a4,.L11 + #APP + csrw 3017, a5 + #NO_APP +.L11: + bne t1,zero,.L12 + lw a5,0(sp) + lbu a5,0(a5) + bne a5,zero,.L12 + mv a5,a3 + bne a3,zero,.L13 + li a5,1 +.L13: + slli a3,a5,16 + srli a3,a3,16 + #APP + csrw 2005, a3 + #NO_APP + lw a5,0(sp) + li a4,1 + sb a4,0(a5) +.L12: + addi t1,t1,1 + j .L3 +.L5: + lbu a2,1(t0) + lbu a5,2(t0) + li s0,126976 + slli a2,a2,8 + slli a5,a5,12 + and a5,a5,s0 + andi a2,a2,1792 + or a2,a2,a5 + lbu a4,9(a0) + lbu a5,3(t0) + li s0,3145728 + addi a4,a4,-1 + slli a5,a5,20 + andi a4,a4,0xff + and a5,a5,s0 + sb a4,%lo(xfer_shift_ctrl)(t2) + or a5,a2,a5 + andi a4,a4,63 + or a5,a5,a4 + #APP + csrw 3019, a5 + #NO_APP + j .L6 +.L10: + #APP + csrw 3016, a5 + #NO_APP + j .L11 + .size hrt_tx, .-hrt_tx + .section .text.hrt_write,"ax",@progbits + .align 1 + .globl hrt_write + .type hrt_write, @function +hrt_write: + addi sp,sp,-16 + sw s0,8(sp) + sw ra,12(sp) + sw s1,4(sp) + mv s0,a0 + sb zero,3(sp) + lhu a5,90(a0) + #APP + csrw 3009, a5 + #NO_APP + li a5,0 + li a2,20 + li a3,4 +.L21: + mul a4,a5,a2 + add a4,s0,a4 + lw a4,4(a4) + bne a4,zero,.L20 + addi a5,a5,1 + bne a5,a3,.L21 + li a5,3 +.L22: + li a4,1 + beq a5,a4,.L23 + li a4,3 + beq a5,a4,.L24 + li a3,0 + bne a5,zero,.L25 + lbu a3,80(s0) +.L43: + andi a3,a3,0xff +.L25: + lui a4,%hi(xfer_shift_ctrl+2) + sb a3,%lo(xfer_shift_ctrl+2)(a4) + #APP + csrw 2000, 2 + #NO_APP + lhu a4,84(s0) + slli a4,a4,16 + srli a4,a4,16 + #APP + csrr a2, 2003 + #NO_APP + li a1,-65536 + and a2,a2,a1 + or a4,a4,a2 + #APP + csrw 2003, a4 + csrw 3011, 0 + #NO_APP + li a2,2031616 + slli a4,a3,16 + and a4,a4,a2 + ori a4,a4,4 + #APP + csrw 3043, a4 + #NO_APP + li a4,20 + mul a5,a5,a4 + li a2,1 + add a5,s0,a5 + lw a4,4(a5) + beq a4,a2,.L26 + li a2,2 + beq a4,a2,.L27 + li a5,32 + div a5,a5,a3 + j .L44 +.L20: + andi a5,a5,0xff + j .L22 +.L23: + lbu a3,81(s0) + j .L43 +.L24: + lbu a3,83(s0) + j .L43 +.L26: + lbu a5,8(a5) +.L44: + #APP + csrw 3022, a5 + #NO_APP + lbu a5,88(s0) + lbu a4,86(s0) + bne a5,zero,.L30 + li a5,1 + sll a5,a5,a4 + slli a5,a5,16 + srli a5,a5,16 + #APP + csrc 3008, a5 + #NO_APP +.L31: + #APP + csrr s1, 3008 + #NO_APP + lbu a1,80(s0) + lhu a3,84(s0) + addi a2,sp,3 + mv a0,s0 + call hrt_tx + lbu a1,81(s0) + lhu a3,84(s0) + addi a2,sp,3 + addi a0,s0,20 + call hrt_tx + lbu a1,82(s0) + lhu a3,84(s0) + addi a2,sp,3 + addi a0,s0,40 + call hrt_tx + lbu a1,83(s0) + lhu a3,84(s0) + addi a2,sp,3 + addi a0,s0,60 + call hrt_tx + lbu a5,92(s0) + bne a5,zero,.L32 + li a5,4096 + addi a5,a5,1 + #APP + csrw 3019, a5 + #NO_APP + li a4,131072 + slli a5,s1,1 + addi a4,a4,-2 + and a5,a5,a4 + #APP + csrw 3012, a5 + csrw 2000, 0 + #NO_APP +.L33: + #APP + csrw 2005, 0 + #NO_APP + lbu a5,87(s0) + bne a5,zero,.L19 + lbu a5,88(s0) + lbu a4,86(s0) + bne a5,zero,.L36 + li a5,1 + sll a5,a5,a4 + slli a5,a5,16 + srli a5,a5,16 + #APP + csrs 3008, a5 + #NO_APP +.L19: + lw ra,12(sp) + lw s0,8(sp) + lw s1,4(sp) + addi sp,sp,16 + jr ra +.L27: + lbu a5,9(a5) + j .L44 +.L30: + li a5,1 + sll a5,a5,a4 + slli a5,a5,16 + srli a5,a5,16 + #APP + csrs 3008, a5 + #NO_APP + j .L31 +.L32: + #APP + csrr a5, 3022 + #NO_APP + andi a5,a5,0xff + bne a5,zero,.L32 + #APP + csrw 2000, 0 + #NO_APP + li a5,4096 + addi a5,a5,1 + #APP + csrw 3019, a5 + #NO_APP + lbu a4,92(s0) + li a5,1 + bne a4,a5,.L34 + #APP + csrc 3008, 1 + #NO_APP + j .L33 +.L34: + lbu a4,92(s0) + li a5,3 + bne a4,a5,.L33 + #APP + csrs 3008, 1 + #NO_APP + j .L33 +.L36: + li a5,1 + sll a5,a5,a4 + slli a5,a5,16 + srli a5,a5,16 + #APP + csrc 3008, a5 + #NO_APP + j .L19 + .size hrt_write, .-hrt_write + .section .text.hrt_read,"ax",@progbits + .align 1 + .globl hrt_read + .type hrt_read, @function +hrt_read: + addi sp,sp,-24 + sw s0,16(sp) + sw ra,20(sp) + sw s1,12(sp) + lbu a5,83(a0) + lbu a5,83(a0) + lbu a4,83(a0) + lw s1,64(a0) + lbu a3,87(a0) + lw a2,60(a0) + lbu a5,88(a0) + lbu a1,86(a0) + mv s0,a0 + andi a4,a4,0xff + andi a3,a3,0xff + bne a5,zero,.L46 + li a5,1 + sll a5,a5,a1 + slli a5,a5,16 + srli a5,a5,16 + #APP + csrc 3008, a5 + #NO_APP +.L47: + #APP + csrr a5, 3008 + #NO_APP + lw a5,4(s0) + bne a5,zero,.L48 + lw a5,24(s0) + bne a5,zero,.L48 + lw a5,44(s0) + beq a5,zero,.L49 +.L48: + sw zero,64(s0) + li a5,1 + sb a5,87(s0) + mv a0,s0 + sw a2,8(sp) + sw a3,4(sp) + sw a4,0(sp) + call hrt_write + lw a2,8(sp) + lw a3,4(sp) + lw a4,0(sp) +.L49: + sw s1,64(s0) + sb a3,87(s0) + #APP + csrw 3022, 0 + csrw 2010, 0 + #NO_APP + lbu a1,83(s0) + li a3,1 + li a5,4 + bleu a1,a3,.L50 + lbu a3,83(s0) + beq a3,a5,.L70 + li a5,6 +.L50: + #APP + csrr a3, 3009 + #NO_APP + not a5,a5 + and a5,a5,a3 + slli a5,a5,16 + srli a5,a5,16 + #APP + csrw 3009, a5 + #NO_APP + li a5,-1 + #APP + csrw 2002, a5 + #NO_APP + li a5,2031616 + slli a4,a4,16 + and a4,a4,a5 + ori a5,a4,4 + #APP + csrw 3043, a5 + #NO_APP + li a5,1 + beq s1,a5,.L51 + li a5,2 + beq s1,a5,.L52 + lbu a3,83(s0) + li a5,32 + div a5,a5,a3 + j .L81 +.L46: + li a5,1 + sll a5,a5,a1 + slli a5,a5,16 + srli a5,a5,16 + #APP + csrs 3008, a5 + #NO_APP + j .L47 +.L70: + li a5,30 + j .L50 +.L51: + lbu a5,68(s0) +.L81: + addi a5,a5,-1 + andi a5,a5,255 + #APP + csrw 3023, a5 + csrw 3022, 0 + csrw 3021, 0 + csrw 3011, 2 + csrw 2000, 2 + csrw 2001, 2 + #NO_APP + lhu a5,84(s0) + slli a5,a5,16 + srli a5,a5,16 + #APP + csrr a3, 2003 + #NO_APP + li a1,-65536 + and a3,a3,a1 + or a5,a5,a3 + #APP + csrw 2003, a5 + #NO_APP + lhu a5,84(s0) + slli a5,a5,16 + srli a5,a5,16 + #APP + csrr a3, 2003 + #NO_APP + slli a5,a5,1 + slli a3,a3,16 + addi a5,a5,1 + srli a3,a3,16 + slli a5,a5,16 + or a5,a5,a3 + #APP + csrw 2003, a5 + #NO_APP + lhu a5,84(s0) + li a3,65536 + or a5,a5,a3 + #APP + csrw 2002, a5 + csrw 2010, 0 + csrr a5, 3018 + #NO_APP + li a1,1 + addi a3,s1,-1 + li a0,2 + li t1,32 +.L55: + bne a3,zero,.L60 + #APP + csrw 3023, 0 + #NO_APP +.L61: + #APP + csrr a5, 3021 + #NO_APP + andi a5,a5,0xff + bne a5,zero,.L61 + #APP + csrw 2010, 0 + #NO_APP + lbu a5,92(s0) + beq a5,zero,.L62 + lbu a3,92(s0) + li a5,2 + bne a3,a5,.L63 +.L62: + #APP + csrw 2010, 0 + #NO_APP +.L63: + #APP + csrw 2000, 0 + csrw 2001, 0 + csrr a5, 3018 + #NO_APP + li a3,1 + bne s1,a3,.L64 + lbu a2,68(s0) + li a3,2 + bne a2,a3,.L64 + lbu a2,83(s0) + li a3,8 + bne a2,a3,.L65 + srli a5,a5,16 +.L83: + sw a5,72(s0) + #APP + csrw 2010, 0 + csrw 3022, 0 + csrw 3043, a4 + csrw 3011, 0 + #NO_APP + lbu a5,87(s0) + bne a5,zero,.L45 + lbu a5,88(s0) + lbu a4,86(s0) + bne a5,zero,.L68 + li a5,1 + sll a5,a5,a4 + slli a5,a5,16 + srli a5,a5,16 + #APP + csrs 3008, a5 + #NO_APP +.L45: + lw ra,20(sp) + lw s0,16(sp) + lw s1,12(sp) + addi sp,sp,24 + jr ra +.L52: + lbu a5,69(s0) + j .L81 +.L60: + beq a3,a1,.L56 + beq a3,a0,.L57 + lbu a5,83(s0) + div a5,t1,a5 + j .L82 +.L56: + lbu a5,68(s0) +.L82: + addi a5,a5,-1 + andi a5,a5,255 + #APP + csrw 3023, a5 + csrr a5, 3018 + #NO_APP + sw a5,0(a2) + addi a3,a3,-1 + addi a2,a2,4 + j .L55 +.L57: + lbu a5,69(s0) + j .L82 +.L65: + srli a5,a5,24 + j .L83 +.L64: + lbu a2,68(s0) + lbu a3,83(s0) + mul a2,a2,a3 + li a3,32 + sub a3,a3,a2 + srl a5,a5,a3 + j .L83 +.L68: + li a5,1 + sll a5,a5,a4 + slli a5,a5,16 + srli a5,a5,16 + #APP + csrc 3008, a5 + #NO_APP + j .L45 + .size hrt_read, .-hrt_read + .section .sdata.xfer_shift_ctrl,"aw" + .align 2 + .type xfer_shift_ctrl, @object + .size xfer_shift_ctrl, 4 +xfer_shift_ctrl: + .byte 31 + .byte 4 + .byte 1 + .byte 0 diff --git a/applications/hpf/mspi/src/hrt/hrt.c b/applications/hpf/mspi/src/hrt/hrt.c index 0254f3b20762..980999302e92 100644 --- a/applications/hpf/mspi/src/hrt/hrt.c +++ b/applications/hpf/mspi/src/hrt/hrt.c @@ -57,7 +57,7 @@ static nrf_vpr_csr_vio_shift_ctrl_t xfer_shift_ctrl = { .in_mode = NRF_VPR_CSR_VIO_MODE_IN_CONTINUOUS, }; -NRF_STATIC_INLINE bool is_counter_running(uint8_t counter) +static bool is_counter_running(uint8_t counter) { /* This may not work for higher frequencies but * there is no other way to check if timer is running. @@ -68,7 +68,7 @@ NRF_STATIC_INLINE bool is_counter_running(uint8_t counter) return cnt != nrf_vpr_csr_vtim_simple_counter_get(counter); } -NRF_STATIC_INLINE uint32_t get_next_shift_count(volatile hrt_xfer_t *hrt_xfer_params, +static uint32_t get_next_shift_count(volatile hrt_xfer_t *hrt_xfer_params, uint32_t word_count, uint32_t index) { switch (word_count - index) { @@ -82,7 +82,7 @@ NRF_STATIC_INLINE uint32_t get_next_shift_count(volatile hrt_xfer_t *hrt_xfer_pa } } -NRF_STATIC_INLINE void rx_end_procedure_mode_3(volatile hrt_xfer_t *hrt_xfer_params) +static void rx_end_procedure_mode_3(volatile hrt_xfer_t *hrt_xfer_params) { uint32_t last_word; uint16_t in; @@ -206,6 +206,59 @@ static void hrt_tx(volatile hrt_xfer_data_t *xfer_data, uint8_t frame_width, boo } } +static void set_ce_state(volatile hrt_xfer_t *hrt_xfer_params, bool active) +{ + if (hrt_xfer_params->ce_polarity == MSPI_CE_ACTIVE_LOW) { + if (active) { + nrf_vpr_csr_vio_out_clear_set(BIT(hrt_xfer_params->ce_vio)); + } else { + nrf_vpr_csr_vio_out_or_set(BIT(hrt_xfer_params->ce_vio)); + } + } else { + if (active) { + nrf_vpr_csr_vio_out_or_set(BIT(hrt_xfer_params->ce_vio)); + } else { + nrf_vpr_csr_vio_out_clear_set(BIT(hrt_xfer_params->ce_vio)); + } + } +} + +static void configure_rx_data_pins(volatile hrt_xfer_t *hrt_xfer_params, uint16_t *rx_pin_mask) +{ + *rx_pin_mask = 0; + + /* Set all needed data pins as inputs */ + WRITE_BIT(*rx_pin_mask, D1_VIO, VPRCSR_NORDIC_PIN_USED); + if (hrt_xfer_params->bus_widths.data >= 2) { + WRITE_BIT(*rx_pin_mask, D0_VIO, VPRCSR_NORDIC_PIN_USED); + if (hrt_xfer_params->bus_widths.data == 4) { + WRITE_BIT(*rx_pin_mask, D2_VIO, VPRCSR_NORDIC_PIN_USED); + WRITE_BIT(*rx_pin_mask, D3_VIO, VPRCSR_NORDIC_PIN_USED); + } + } + nrf_vpr_csr_vio_dir_set(nrf_vpr_csr_vio_dir_get() & ~(*rx_pin_mask)); +} + +static void prepare_read_phase(volatile hrt_xfer_t *hrt_xfer_params, uint32_t *word_count, + bool *hold) +{ + *word_count = hrt_xfer_params->xfer_data[HRT_FE_DATA].word_count; + *hold = hrt_xfer_params->ce_hold; + + if ((hrt_xfer_params->xfer_data[HRT_FE_COMMAND].word_count != 0) || + (hrt_xfer_params->xfer_data[HRT_FE_ADDRESS].word_count != 0) || + (hrt_xfer_params->xfer_data[HRT_FE_DUMMY_CYCLES].word_count != 0)) { + /* Write command, address and/or dummy cycles and keep CS active. */ + hrt_xfer_params->xfer_data[HRT_FE_DATA].word_count = 0; + hrt_xfer_params->ce_hold = true; + hrt_write(hrt_xfer_params); + } + + /* Restore variables values for read phase. */ + hrt_xfer_params->xfer_data[HRT_FE_DATA].word_count = *word_count; + hrt_xfer_params->ce_hold = *hold; +} + void hrt_write(volatile hrt_xfer_t *hrt_xfer_params) { hrt_frame_element_t first_element = HRT_FE_DATA; @@ -259,11 +312,7 @@ void hrt_write(volatile hrt_xfer_t *hrt_xfer_params) } /* Enable CE */ - if (hrt_xfer_params->ce_polarity == MSPI_CE_ACTIVE_LOW) { - nrf_vpr_csr_vio_out_clear_set(BIT(hrt_xfer_params->ce_vio)); - } else { - nrf_vpr_csr_vio_out_or_set(BIT(hrt_xfer_params->ce_vio)); - } + set_ce_state(hrt_xfer_params, true); prev_out = nrf_vpr_csr_vio_out_get(); @@ -315,16 +364,10 @@ void hrt_write(volatile hrt_xfer_t *hrt_xfer_params) /* Disable CE */ if (!hrt_xfer_params->ce_hold) { - - if (hrt_xfer_params->ce_polarity == MSPI_CE_ACTIVE_LOW) { - nrf_vpr_csr_vio_out_or_set(BIT(hrt_xfer_params->ce_vio)); - } else { - nrf_vpr_csr_vio_out_clear_set(BIT(hrt_xfer_params->ce_vio)); - } + set_ce_state(hrt_xfer_params, false); } } -#if defined(CONFIG_SOC_NRF54LM20A) || defined(CONFIG_SOC_NRF54LM20B) void hrt_read(volatile hrt_xfer_t *hrt_xfer_params) { nrf_vpr_csr_vio_shift_ctrl_t rx_shift_ctrl = { @@ -337,48 +380,45 @@ void hrt_read(volatile hrt_xfer_t *hrt_xfer_params) .mode = NRF_VPR_CSR_VIO_SHIFT_OUTB_TOGGLE, .frame_width = hrt_xfer_params->bus_widths.data, }; - uint32_t word_count = hrt_xfer_params->xfer_data[HRT_FE_DATA].word_count; - bool hold = hrt_xfer_params->ce_hold; + uint32_t word_count = 0; + bool hold = false; uint32_t *data = (uint32_t *)hrt_xfer_params->xfer_data[HRT_FE_DATA].data; + uint32_t last_word; uint16_t prev_out; uint16_t rx_pin_mask = 0; - /* Enable CE */ - if (hrt_xfer_params->ce_polarity == MSPI_CE_ACTIVE_LOW) { - nrf_vpr_csr_vio_out_clear_set(BIT(hrt_xfer_params->ce_vio)); - } else { - nrf_vpr_csr_vio_out_or_set(BIT(hrt_xfer_params->ce_vio)); + /* Workaround for hw issue: in modes 1-3 clock does 1 extra edge after being stopped. + * To fix it, rx transfer is set up to do 1 clock cycle less and last clock edge is done, + * by writing directly to out register and reading in register. + */ +#if IS_ENABLED(CONFIG_HPF_MSPI_CORRECT_FOR_EXTRA_VTIM_CYCLE) + if (hrt_xfer_params->cpp_mode == MSPI_CPP_MODE_3) { + hrt_xfer_params->xfer_data[HRT_FE_DATA].last_word_clocks -= 1; } +#endif + + /* Enable CE */ + set_ce_state(hrt_xfer_params, true); /* Get state of all VIO to reset it correctly after transfer. */ prev_out = nrf_vpr_csr_vio_out_get(); - if ((hrt_xfer_params->xfer_data[HRT_FE_COMMAND].word_count != 0) || - (hrt_xfer_params->xfer_data[HRT_FE_ADDRESS].word_count != 0) || - (hrt_xfer_params->xfer_data[HRT_FE_DUMMY_CYCLES].word_count != 0)) { - /* Write command, address and/or dummy cycles and keep CS active. */ - hrt_xfer_params->xfer_data[HRT_FE_DATA].word_count = 0; - hrt_xfer_params->ce_hold = true; - hrt_write(hrt_xfer_params); - } - /* Restore variables values for read phase. */ - hrt_xfer_params->xfer_data[HRT_FE_DATA].word_count = word_count; - hrt_xfer_params->ce_hold = hold; + prepare_read_phase(hrt_xfer_params, &word_count, &hold); + configure_rx_data_pins(hrt_xfer_params, &rx_pin_mask); + /* Counter settings */ + nrf_vpr_csr_vtim_count_mode_set(0, NRF_VPR_CSR_VTIM_COUNT_RELOAD); + nrf_vpr_csr_vtim_count_mode_set(1, NRF_VPR_CSR_VTIM_COUNT_RELOAD); + + /* Set top counters value. */ + nrf_vpr_csr_vtim_simple_counter_top_set(0, hrt_xfer_params->counter_value); + nrf_vpr_csr_vtim_simple_counter_top_set(1, + CNT1_TOP_CALCULATE(hrt_xfer_params->counter_value)); + +#if !IS_ENABLED(CONFIG_HPF_MSPI_CORRECT_FOR_EXTRA_VTIM_CYCLE) nrf_vpr_csr_vio_shift_cnt_out_set(0); nrf_vpr_csr_vtim_simple_wait_set(0, false, 0); - /* Set all needed data pins as inputs */ - WRITE_BIT(rx_pin_mask, D1_VIO, VPRCSR_NORDIC_PIN_USED); - if (hrt_xfer_params->bus_widths.data >= 2) { - WRITE_BIT(rx_pin_mask, D0_VIO, VPRCSR_NORDIC_PIN_USED); - if (hrt_xfer_params->bus_widths.data == 4) { - WRITE_BIT(rx_pin_mask, D2_VIO, VPRCSR_NORDIC_PIN_USED); - WRITE_BIT(rx_pin_mask, D3_VIO, VPRCSR_NORDIC_PIN_USED); - } - } - nrf_vpr_csr_vio_dir_set(nrf_vpr_csr_vio_dir_get() & ~rx_pin_mask); - /* Start counters prior setting OutBBufToggleClk mode to avoid CNT1 stall */ nrf_vpr_csr_vtim_combined_counter_set(UINT32_MAX); @@ -395,15 +435,6 @@ void hrt_read(volatile hrt_xfer_t *hrt_xfer_params) /* The workaround is to use direct registers */ nrf_vpr_csr_vio_mode_in_set(NRF_VPR_CSR_VIO_MODE_IN_SHIFT); - /* Counter settings */ - nrf_vpr_csr_vtim_count_mode_set(0, NRF_VPR_CSR_VTIM_COUNT_RELOAD); - nrf_vpr_csr_vtim_count_mode_set(1, NRF_VPR_CSR_VTIM_COUNT_RELOAD); - - /* Set top counters value. */ - nrf_vpr_csr_vtim_simple_counter_top_set(0, hrt_xfer_params->counter_value); - nrf_vpr_csr_vtim_simple_counter_top_set(1, - CNT1_TOP_CALCULATE(hrt_xfer_params->counter_value)); - /* CNT1 period should be double the CNT0 period according to IPS. * CNT1 has lowest possible value to generate CNT1 event as soon as possible. At that * time, SHIFTCNTIN should be automatically written with SHIFTCNTB. Some time after @@ -421,14 +452,13 @@ void hrt_read(volatile hrt_xfer_t *hrt_xfer_params) /* Make dummy INB read, because first access will not stall VPR */ nrf_vpr_csr_vio_in_buffered_reversed_byte_get(); - for (uint32_t i = 0; i < word_count-1; i++) { - rx_shift_ctrl.shift_count = get_next_shift_count(hrt_xfer_params, word_count, i+1); + for (uint32_t i = 0; i < word_count - 1; i++) { + rx_shift_ctrl.shift_count = get_next_shift_count(hrt_xfer_params, word_count, i + 1); nrf_vpr_csr_vio_shift_cnt_out_buffered_set(rx_shift_ctrl.shift_count); data[i] = nrf_vpr_csr_vio_in_buffered_reversed_byte_get(); } nrf_vpr_csr_vio_shift_cnt_out_buffered_set(0); - /* Wait until the last frame is to be received */ while (nrf_vpr_csr_vio_shift_cnt_in_get() > 0) { } @@ -445,7 +475,7 @@ void hrt_read(volatile hrt_xfer_t *hrt_xfer_params) nrf_vpr_csr_vtim_count_mode_set(0, NRF_VPR_CSR_VTIM_COUNT_STOP); nrf_vpr_csr_vtim_count_mode_set(1, NRF_VPR_CSR_VTIM_COUNT_STOP); - uint32_t last_word = nrf_vpr_csr_vio_in_buffered_reversed_byte_get(); + last_word = nrf_vpr_csr_vio_in_buffered_reversed_byte_get(); /* Special case when only 2 clocks are required. */ if ((word_count == 1) && (hrt_xfer_params->xfer_data[HRT_FE_DATA].last_word_clocks == 2)) { @@ -470,79 +500,7 @@ void hrt_read(volatile hrt_xfer_t *hrt_xfer_params) rx_out_mode.mode = NRF_VPR_CSR_VIO_SHIFT_NONE; nrf_vpr_csr_vio_mode_out_set(&rx_out_mode); nrf_vpr_csr_vio_mode_in_set(NRF_VPR_CSR_VIO_MODE_IN_CONTINUOUS); - - /* Disable CS */ - if (!hrt_xfer_params->ce_hold) { - - if (hrt_xfer_params->ce_polarity == MSPI_CE_ACTIVE_LOW) { - nrf_vpr_csr_vio_out_or_set(BIT(hrt_xfer_params->ce_vio)); - } else { - nrf_vpr_csr_vio_out_clear_set(BIT(hrt_xfer_params->ce_vio)); - } - } -} #else -void hrt_read(volatile hrt_xfer_t *hrt_xfer_params) -{ - nrf_vpr_csr_vio_shift_ctrl_t rx_shift_ctrl = { - .shift_count = SHIFTCNTB_VALUE(BITS_IN_WORD / hrt_xfer_params->bus_widths.data), - .out_mode = NRF_VPR_CSR_VIO_SHIFT_OUTB_TOGGLE, - .frame_width = hrt_xfer_params->bus_widths.data, - .in_mode = NRF_VPR_CSR_VIO_MODE_IN_SHIFT, - }; - nrf_vpr_csr_vio_mode_out_t rx_out_mode = { - .mode = NRF_VPR_CSR_VIO_SHIFT_OUTB_TOGGLE, - .frame_width = hrt_xfer_params->bus_widths.data, - }; - uint32_t word_count = hrt_xfer_params->xfer_data[HRT_FE_DATA].word_count; - bool hold = hrt_xfer_params->ce_hold; - uint32_t *data = (uint32_t *)hrt_xfer_params->xfer_data[HRT_FE_DATA].data; - uint32_t last_word; - uint16_t prev_out; - uint16_t rx_pin_mask = 0; - - /* Workaround for hw issue: in modes 1-3 clock does 1 extra edge after being stopped. - * To fix it, rx transfer is set up to do 1 clock cycle less and last clock edge is done, - * by writing directly to out register and reading in register. - */ - if (hrt_xfer_params->cpp_mode == MSPI_CPP_MODE_3) { - hrt_xfer_params->xfer_data[HRT_FE_DATA].last_word_clocks -= 1; - } - - /* Enable CE */ - if (hrt_xfer_params->ce_polarity == MSPI_CE_ACTIVE_LOW) { - nrf_vpr_csr_vio_out_clear_set(BIT(hrt_xfer_params->ce_vio)); - } else { - nrf_vpr_csr_vio_out_or_set(BIT(hrt_xfer_params->ce_vio)); - } - - /* Get state of all VIO to reset it correctly after transfer. */ - prev_out = nrf_vpr_csr_vio_out_get(); - - if ((hrt_xfer_params->xfer_data[HRT_FE_COMMAND].word_count != 0) || - (hrt_xfer_params->xfer_data[HRT_FE_ADDRESS].word_count != 0) || - (hrt_xfer_params->xfer_data[HRT_FE_DUMMY_CYCLES].word_count != 0)) { - /* Write command, address and/or dummy cycles and keep CS active. */ - hrt_xfer_params->xfer_data[HRT_FE_DATA].word_count = 0; - hrt_xfer_params->ce_hold = true; - hrt_write(hrt_xfer_params); - } - - /* Restore variables values for read phase. */ - hrt_xfer_params->xfer_data[HRT_FE_DATA].word_count = word_count; - hrt_xfer_params->ce_hold = hold; - - /* Set all needed data pins as inputs */ - WRITE_BIT(rx_pin_mask, D1_VIO, VPRCSR_NORDIC_PIN_USED); - if (hrt_xfer_params->bus_widths.data >= 2) { - WRITE_BIT(rx_pin_mask, D0_VIO, VPRCSR_NORDIC_PIN_USED); - if (hrt_xfer_params->bus_widths.data == 4) { - WRITE_BIT(rx_pin_mask, D2_VIO, VPRCSR_NORDIC_PIN_USED); - WRITE_BIT(rx_pin_mask, D3_VIO, VPRCSR_NORDIC_PIN_USED); - } - } - nrf_vpr_csr_vio_dir_set(nrf_vpr_csr_vio_dir_get() & ~rx_pin_mask); - /* Initial configuration */ nrf_vpr_csr_vio_mode_in_set(NRF_VPR_CSR_VIO_MODE_IN_SHIFT); nrf_vpr_csr_vio_mode_out_set(&rx_out_mode); @@ -559,15 +517,6 @@ void hrt_read(volatile hrt_xfer_t *hrt_xfer_params) */ nrf_vpr_csr_vio_shift_cnt_out_set(1); - /* Counter settings */ - nrf_vpr_csr_vtim_count_mode_set(0, NRF_VPR_CSR_VTIM_COUNT_RELOAD); - nrf_vpr_csr_vtim_count_mode_set(1, NRF_VPR_CSR_VTIM_COUNT_RELOAD); - - /* Set top counters value. CNT1 - trigger data capture every two clock cycles */ - nrf_vpr_csr_vtim_simple_counter_top_set(0, hrt_xfer_params->counter_value); - nrf_vpr_csr_vtim_simple_counter_top_set(1, - CNT1_TOP_CALCULATE(hrt_xfer_params->counter_value)); - nrf_vpr_csr_vio_shift_ctrl_buffered_set(&rx_shift_ctrl); /* Make sure that there is no data leftover in output register. */ @@ -699,15 +648,10 @@ void hrt_read(volatile hrt_xfer_t *hrt_xfer_params) rx_shift_ctrl.out_mode = NRF_VPR_CSR_VIO_SHIFT_NONE; rx_shift_ctrl.in_mode = NRF_VPR_CSR_VIO_MODE_IN_CONTINUOUS; nrf_vpr_csr_vio_shift_ctrl_buffered_set(&rx_shift_ctrl); +#endif /* Disable CS */ if (!hrt_xfer_params->ce_hold) { - - if (hrt_xfer_params->ce_polarity == MSPI_CE_ACTIVE_LOW) { - nrf_vpr_csr_vio_out_or_set(BIT(hrt_xfer_params->ce_vio)); - } else { - nrf_vpr_csr_vio_out_clear_set(BIT(hrt_xfer_params->ce_vio)); - } + set_ce_state(hrt_xfer_params, false); } } -#endif diff --git a/applications/hpf/mspi/src/main.c b/applications/hpf/mspi/src/main.c index ccc0d286c68c..2f81e2c901e6 100644 --- a/applications/hpf/mspi/src/main.c +++ b/applications/hpf/mspi/src/main.c @@ -16,12 +16,22 @@ #include #include +#include + #include +#if defined(NRF_GPIOHSPADCTRL) +#include +#define HPF_MSPI_USE_HS_PADCTRL 1 +#define PAD_BIAS_VALUE 1 +#else +#define HPF_MSPI_USE_HS_PADCTRL 0 +#endif + #define SUPPORTED_IO_MODES_COUNT 7 #define DEVICES_MAX 5 -#define DATA_PINS_MAX 8 +#define DATA_PINS_MAX 4 /* Bellow this CNT0 period pin steering force has to be increased to produce correct waveform. * CNT0 value 1 generates 32MHz clock. @@ -33,8 +43,6 @@ #define MODE_3_RX_MIN_CLOCKS 3 -#define PAD_BIAS_VALUE 1 - #define MAX_SHIFT_COUNT 63 #define DATA_PIN_UNUSED UINT8_MAX @@ -47,31 +55,12 @@ #define VEVIF_IRQN(vevif) VEVIF_IRQN_1(vevif) #define VEVIF_IRQN_1(vevif) VPRCLIC_##vevif##_IRQn -#if !defined(CONFIG_SOC_NRF54L15) && !defined(CONFIG_SOC_NRF54LM20A) && \ - !defined(CONFIG_SOC_NRF54LM20B) -#error "Unsupported SoC for HPF MSPI" -#endif - #define DATA_LINE_INDEX(pinctr_fun) (pinctr_fun - NRF_FUN_HPF_MSPI_DQ0) #ifndef CONFIG_HPF_MSPI_IPC_NO_COPY BUILD_ASSERT(CONFIG_HPF_MSPI_MAX_RESPONSE_SIZE > 0, "Response max size should be greater that 0"); #endif -static const uint8_t pin_to_vio_map[HPF_MSPI_PINS_MAX] = { - 4, /* Physical pin 0 */ - 0, /* Physical pin 1 */ - 1, /* Physical pin 2 */ - 3, /* Physical pin 3 */ - 2, /* Physical pin 4 */ - 5, /* Physical pin 5 */ - 6, /* Physical pin 6 */ - 7, /* Physical pin 7 */ - 8, /* Physical pin 8 */ - 9, /* Physical pin 9 */ - 10, /* Physical pin 10 */ -}; - static const hrt_xfer_bus_widths_t io_modes[SUPPORTED_IO_MODES_COUNT] = { {1, 1, 1, 1}, /* MSPI_IO_MODE_SINGLE */ {2, 2, 2, 2}, /* MSPI_IO_MODE_DUAL */ @@ -195,7 +184,7 @@ static void configure_clock(enum mspi_cpp_mode cpp_mode) { nrf_vpr_csr_vio_config_t vio_config = { .input_sel = false, -#if defined(CONFIG_SOC_NRF54LM20A) || defined(CONFIG_SOC_NRF54LM20B) +#if !IS_ENABLED(HPF_MSPI_CORRECT_FOR_EXTRA_VTIM_CYCLE) .stop_cnt = false, #else .stop_cnt = true, @@ -373,11 +362,9 @@ static void config_pins(hpf_mspi_pinctrl_soc_pin_msg_t *pins_cfg) uint8_t pin_number = NRF_PIN_NUMBER_TO_PIN(psel); - NRFX_ASSERT(pin_number < HPF_MSPI_PINS_MAX); - if ((fun >= NRF_FUN_HPF_MSPI_CS0) && (fun <= NRF_FUN_HPF_MSPI_CS4)) { - ce_vios[ce_vios_count] = pin_to_vio_map[pin_number]; + ce_vios[ce_vios_count] = nrf_vpr_vio_pin_index_get(pin_number); WRITE_BIT(xfer_params.used_pins_mask, ce_vios[ce_vios_count], VPRCSR_NORDIC_PIN_USED); ce_vios_count++; @@ -387,12 +374,12 @@ static void config_pins(hpf_mspi_pinctrl_soc_pin_msg_t *pins_cfg) NRFX_ASSERT(DATA_LINE_INDEX(fun) < DATA_PINS_MAX); NRFX_ASSERT(data_vios[DATA_LINE_INDEX(fun)] == DATA_PIN_UNUSED); - data_vios[DATA_LINE_INDEX(fun)] = pin_to_vio_map[pin_number]; + data_vios[DATA_LINE_INDEX(fun)] = nrf_vpr_vio_pin_index_get(pin_number); WRITE_BIT(xfer_params.used_pins_mask, data_vios[DATA_LINE_INDEX(fun)], VPRCSR_NORDIC_PIN_USED); data_vios_count++; } else if (fun == NRF_FUN_HPF_MSPI_SCK) { - clk_vio = pin_to_vio_map[pin_number]; + clk_vio = nrf_vpr_vio_pin_index_get(pin_number); WRITE_BIT(xfer_params.used_pins_mask, clk_vio, VPRCSR_NORDIC_PIN_USED); } } @@ -466,7 +453,7 @@ static void ep_recv(const void *data, size_t len, void *priv) } /* Set unshifted parts of OUT to high state */ -#if defined(CONFIG_SOC_NRF54LM20A) || defined(CONFIG_SOC_NRF54LM20B) +#if !IS_ENABLED(HPF_MSPI_CORRECT_FOR_EXTRA_VTIM_CYCLE) nrf_csr_write(VPRCSR_NORDIC_OUTUB, BIT(data_vios[DATA_LINE_INDEX(NRF_FUN_HPF_MSPI_DQ1)]) | BIT(data_vios[DATA_LINE_INDEX(NRF_FUN_HPF_MSPI_DQ2)]) | @@ -508,12 +495,14 @@ static void ep_recv(const void *data, size_t len, void *priv) #endif configure_clock(hpf_mspi_devices[hpf_mspi_xfer_config_ptr->device_index].cpp); +#if HPF_MSPI_USE_HS_PADCTRL /* Tune up pad bias for frequencies above 32MHz */ - if (hpf_mspi_devices[hpf_mspi_xfer_config_ptr->device_index].cnt0_value <= - STD_PAD_BIAS_CNT0_THRESHOLD) { - NRF_GPIOHSPADCTRL->BIAS = PAD_BIAS_VALUE; + if (hpf_mspi_devices[hpf_mspi_xfer_config_ptr->device_index].cnt0_value <= STD_PAD_BIAS_CNT0_THRESHOLD) { + nrf_gpiohspadctrl_hs_bias_set(NRF_GPIOHSPADCTRL, PAD_BIAS_VALUE); + } else { + nrf_gpiohspadctrl_hs_bias_set(NRF_GPIOHSPADCTRL, 0); } - +#endif break; } case HPF_MSPI_TX: @@ -548,7 +537,6 @@ static void ep_recv(const void *data, size_t len, void *priv) #else ); #endif - #if defined(CONFIG_HPF_MSPI_FAULT_TIMER) if (fault_timer != NULL) { nrf_timer_task_trigger(fault_timer, NRF_TIMER_TASK_CLEAR); diff --git a/doc/nrf/includes/sample_board_rows.txt b/doc/nrf/includes/sample_board_rows.txt index 34c2d60c3457..d6d278b460bc 100644 --- a/doc/nrf/includes/sample_board_rows.txt +++ b/doc/nrf/includes/sample_board_rows.txt @@ -279,6 +279,10 @@ | nRF54LV10 DK | PCA10188 | :ref:`nrf54lv10dk ` | ``nrf54lv10dk/nrf54lv10a/cpuapp/ns`` | +.. nrf54lv10dk_nrf54lv10a_cpuflpr + +| nRF54LV10 DK | PCA10188 | :ref:`nrf54lv10dk ` | ``nrf54lv10dk/nrf54lv10a/cpuflpr`` | + .. nrf54lm20pdk_nrf54lm20a_cpuapp | nRF54LM20 PDK | | nrf54lm20pdk | ``nrf54lm20pdk/nrf54lm20a/cpuapp`` | diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst index 7d235df82e92..6f728eab6a28 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst @@ -202,7 +202,7 @@ Connectivity bridge High-Performance Framework (HPF) -------------------------------- -|no_changes_yet_note| +* Added support for the nRF54LV10A SoC in HPF MSPI. IPC radio firmware ------------------ diff --git a/drivers/mspi/Kconfig.hpf b/drivers/mspi/Kconfig.hpf index 798287f923e2..f3b502ca0bb2 100644 --- a/drivers/mspi/Kconfig.hpf +++ b/drivers/mspi/Kconfig.hpf @@ -30,7 +30,7 @@ config MSPI_HPF_INIT_PRIORITY config MSPI_HPF_IPC_NO_COPY bool "IPC no copy mode" default y - depends on SOC_NRF54L15 || SOC_NRF54LM20A || SOC_NRF54LM20B + depends on SOC_NRF54L15 || SOC_NRF54LM20A || SOC_NRF54LM20B || SOC_NRF54LV10A help If y Data is passed through IPC by reference, this requires both cores to be able to access each others memory spaces. diff --git a/drivers/mspi/mspi_hpf.c b/drivers/mspi/mspi_hpf.c index 6d90e0d62f9a..899b824fb6e8 100644 --- a/drivers/mspi/mspi_hpf.c +++ b/drivers/mspi/mspi_hpf.c @@ -27,25 +27,16 @@ LOG_MODULE_REGISTER(mspi_hpf, CONFIG_MSPI_LOG_LEVEL); #define IPC_TIMEOUT_MS 100 #define IPC_BOUND_TIMEOUT_MS 100 #define IPC_BOUND_RETRY_COUNT 10 -#define IPC_BOUND_RETRY_DELAY_MS 10 +#define IPC_BOUND_RETRY_DELAY_MS 10 #define EP_SEND_TIMEOUT_MS 10 #define EXTREME_DRIVE_FREQ_THRESHOLD 32000000 #define CNT0_TOP_CALCULATE(freq) (NRFX_CEIL_DIV(SystemCoreClock, freq * 2) - 1) #define DATA_LINE_INDEX(pinctr_fun) (pinctr_fun - NRF_FUN_HPF_MSPI_DQ0) #define DATA_PIN_UNUSED UINT8_MAX -#if defined(CONFIG_SOC_NRF54L15) || defined(CONFIG_SOC_NRF54LM20A) || \ - defined(CONFIG_SOC_NRF54LM20B) - -#define HPF_MSPI_PORT_NUMBER 2 /* Physical port number */ -#define HPF_MSPI_SCK_PIN_NUMBER 1 /* Physical pin number on port 2 */ - #define HPF_MSPI_DATA_LINE_CNT_MAX 8 #define HPF_MSPI_CS_LINE_CNT_MAX 5 #define MAX_MSPI_DUMMY_CLOCKS 59 -#else -#error "Unsupported SoC for HPF MSPI" -#endif #ifdef CONFIG_PINCTRL_STORE_REG #define HPF_MPSI_PINCTRL_DEV_CONFIG_INIT(node_id) \ @@ -431,7 +422,7 @@ static int check_pin_assignments(const struct pinctrl_state *state) { uint8_t data_pins[HPF_MSPI_DATA_LINE_CNT_MAX]; uint8_t data_pins_cnt = 0; - uint8_t cs_pins[HPF_MSPI_PINS_MAX]; + uint8_t cs_pins[HPF_MSPI_PIN_COUNT]; uint8_t cs_pins_cnt = 0; uint32_t psel = 0; uint32_t pin_fun = 0; @@ -571,8 +562,8 @@ static int api_config(const struct mspi_dt_spec *spec) } } - if (drv_cfg->pcfg->states[state_id].pin_cnt > HPF_MSPI_PINS_MAX) { - LOG_ERR("Too many pins defined. Max: %d", HPF_MSPI_PINS_MAX); + if (drv_cfg->pcfg->states[state_id].pin_cnt > HPF_MSPI_PIN_COUNT) { + LOG_ERR("Too many pins defined. Max: %d", HPF_MSPI_PIN_COUNT); return -ENOTSUP; } diff --git a/include/drivers/mspi/hpf_mspi.h b/include/drivers/mspi/hpf_mspi.h index 8eef7b65cb74..0b405f9880c9 100644 --- a/include/drivers/mspi/hpf_mspi.h +++ b/include/drivers/mspi/hpf_mspi.h @@ -15,13 +15,6 @@ extern "C" { #endif -#if defined(CONFIG_SOC_NRF54L15) || defined(CONFIG_SOC_NRF54LM20A) || \ - defined(CONFIG_SOC_NRF54LM20B) -#define HPF_MSPI_PINS_MAX 11 -#else -#error "Unsupported SoC for HPF MSPI" -#endif - /** @brief eMSPI opcodes. */ typedef enum { HPF_MSPI_EP_BOUNDED = 0, @@ -63,7 +56,7 @@ typedef struct { typedef struct { hpf_mspi_opcode_t opcode; /* HPF_MSPI_CONFIG_PINS */ uint8_t pins_count; - pinctrl_soc_pin_t pin[HPF_MSPI_PINS_MAX]; + pinctrl_soc_pin_t pin[HPF_MSPI_PIN_COUNT]; } hpf_mspi_pinctrl_soc_pin_msg_t; typedef struct { diff --git a/snippets/hpf/mspi/snippet.yml b/snippets/hpf/mspi/snippet.yml index d23dc9df9317..ca0c8cd58324 100644 --- a/snippets/hpf/mspi/snippet.yml +++ b/snippets/hpf/mspi/snippet.yml @@ -29,3 +29,6 @@ boards: /nrf54lm20dk/nrf54lm20b/cpuapp/: append: EXTRA_DTC_OVERLAY_FILE: board/nrf54lm20dk_nrf54lm20b_cpuapp.overlay + /.*/nrf54lv10a/cpuapp/: + append: + EXTRA_DTC_OVERLAY_FILE: soc/nrf54lv10a_cpuapp.overlay diff --git a/snippets/hpf/mspi/soc/nrf54lv10a_cpuapp.overlay b/snippets/hpf/mspi/soc/nrf54lv10a_cpuapp.overlay new file mode 100644 index 000000000000..bbbc3e8af2a6 --- /dev/null +++ b/snippets/hpf/mspi/soc/nrf54lv10a_cpuapp.overlay @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/ { + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + + sram_rx: memory@2002b000 { + reg = <0x2002b000 0x07f0>; + }; + + sram_tx: memory@2002b7f0 { + reg = <0x2002b7f0 0x07f0>; + }; + + cpuflpr_error_code: memory@2002bfe0 { + reg = <0x2002bfe0 0x0020>; /* 32 bytes */ + }; + }; + + soc { + cpuflpr_sram_code_data: memory@2002c000 { + compatible = "mmio-sram"; + reg = <0x2002c000 DT_SIZE_K(15)>; + ranges = <0x0 0x2002c000 DT_SIZE_K(15)>; + #address-cells = <1>; + #size-cells = <1>; + status = "reserved"; + }; + }; + + ipc { + ipc0: ipc0 { + compatible = "zephyr,ipc-icmsg"; + tx-region = <&sram_tx>; + rx-region = <&sram_rx>; + mboxes = <&cpuapp_vevif_rx 20>, <&cpuapp_vevif_tx 16>; + mbox-names = "rx", "tx"; + status = "okay"; + }; + }; +}; + +&rram_controller { + cpuflpr_rram: rram@f9400 { + compatible = "soc-nv-flash"; + reg = <0xf9400 DT_SIZE_K(15)>; + ranges = <0x0 0xf9400 DT_SIZE_K(15)>; + erase-block-size = <0x1000>; + write-block-size = <0x10>; + #address-cells = <1>; + #size-cells = <1>; + }; +}; + +&cpuapp_rram { + reg = <0x0 DT_SIZE_K(997)>; + ranges = <0x0 0x0 DT_SIZE_K(997)>; + #address-cells = <1>; + #size-cells = <1>; +}; + +&cpuapp_sram { + reg = <0x20000000 DT_SIZE_K(171)>; + ranges = <0x0 0x20000000 0x3b400>; +}; + +&cpuflpr_vpr { + execution-memory = <&cpuflpr_sram_code_data>; + source-memory = <&cpuflpr_rram>; +}; + +&gpio1 { + status = "okay"; +}; + +&cpuapp_vevif_rx { + status = "okay"; +}; + +&cpuapp_vevif_tx { + status = "okay"; +}; + +&pinctrl { + /omit-if-no-ref/ hpf_mspi_default: hpf_mspi_default { + group1 { + psels = , + , + , + , + , + ; + nordic,drive-mode = ; + bias-pull-up; + }; + }; + + /omit-if-no-ref/ hpf_mspi_sleep: hpf_mspi_sleep { + group1 { + psels = , + , + , + , + , + ; + low-power-enable; + }; + }; +}; + +&hpf_mspi { + clock-frequency = ; + pinctrl-0 = <&hpf_mspi_default>; + pinctrl-1 = <&hpf_mspi_sleep>; + pinctrl-names = "default", "sleep"; + status = "okay"; +}; diff --git a/tests/drivers/gpio/hpf_gpio_basic_api/boards/nrf54lv10dk_nrf54lv10a_cpuapp.overlay b/tests/drivers/gpio/hpf_gpio_basic_api/boards/nrf54lv10dk_nrf54lv10a_cpuapp.overlay index 8ad639d7e832..d8796c5c97ce 100644 --- a/tests/drivers/gpio/hpf_gpio_basic_api/boards/nrf54lv10dk_nrf54lv10a_cpuapp.overlay +++ b/tests/drivers/gpio/hpf_gpio_basic_api/boards/nrf54lv10dk_nrf54lv10a_cpuapp.overlay @@ -4,13 +4,13 @@ * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ -/* Test requires GPIO loopback between P0.04 and P1.16. */ +/* Test requires GPIO loopback between P1.22 and P1.16. */ / { resources { compatible = "test-hpf-gpio"; out-gpios = <&hpf_gpio 16 0>; - in-gpios = <&gpio0 4 0>; + in-gpios = <&gpio1 22 0>; }; }; @@ -18,6 +18,6 @@ status = "okay"; }; -&gpio0 { +&gpio1 { status = "okay"; }; diff --git a/tests/drivers/gpio/hpf_gpio_more_loops/boards/nrf54lv10dk_nrf54lv10a_cpuapp.overlay b/tests/drivers/gpio/hpf_gpio_more_loops/boards/nrf54lv10dk_nrf54lv10a_cpuapp.overlay index b7189c10125c..f86858d65da8 100644 --- a/tests/drivers/gpio/hpf_gpio_more_loops/boards/nrf54lv10dk_nrf54lv10a_cpuapp.overlay +++ b/tests/drivers/gpio/hpf_gpio_more_loops/boards/nrf54lv10dk_nrf54lv10a_cpuapp.overlay @@ -5,8 +5,8 @@ */ /* Test requires GPIO loopback: - * - between P1.16 and P0.04, - * - between P1.18 and P1.19, + * - between P1.16 and P1.22, + * - between P1.17 and P1.23, * - between P1.20 and P1.21. */ @@ -19,10 +19,10 @@ * All outputs must be on the same device. */ zephyr,user { - out-gpios = <&hpf_gpio 16 GPIO_ACTIVE_HIGH>, <&hpf_gpio 18 GPIO_ACTIVE_HIGH>, + out-gpios = <&hpf_gpio 16 GPIO_ACTIVE_HIGH>, <&hpf_gpio 17 GPIO_ACTIVE_HIGH>, <&hpf_gpio 20 GPIO_ACTIVE_HIGH>; - in-gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>, <&gpio1 19 GPIO_ACTIVE_HIGH>, + in-gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>, <&gpio1 23 GPIO_ACTIVE_HIGH>, <&gpio1 21 GPIO_ACTIVE_HIGH>; }; }; @@ -31,14 +31,6 @@ status = "okay"; }; -&gpiote30 { - status = "okay"; -}; - -&gpio0 { - status = "okay"; -}; - &gpio1 { status = "okay"; }; diff --git a/tests/drivers/grtc/grtc_clk_output/boards/nrf54lv10dk_nrf54lv10a_cpuapp.overlay b/tests/drivers/grtc/grtc_clk_output/boards/nrf54lv10dk_nrf54lv10a_cpuapp.overlay index c39fe3db9010..b4e850f28020 100644 --- a/tests/drivers/grtc/grtc_clk_output/boards/nrf54lv10dk_nrf54lv10a_cpuapp.overlay +++ b/tests/drivers/grtc/grtc_clk_output/boards/nrf54lv10dk_nrf54lv10a_cpuapp.overlay @@ -10,7 +10,7 @@ / { zephyr,user { - gpios = <&gpio1 16 GPIO_ACTIVE_HIGH>; /* Connect to dedicated GRTC output */ + gpios = <&gpio1 25 GPIO_ACTIVE_HIGH>; /* Connect to dedicated GRTC output */ }; }; diff --git a/tests/drivers/mspi/app_fault_timer/Kconfig b/tests/drivers/mspi/app_fault_timer/Kconfig new file mode 100644 index 000000000000..514cdd9aa7db --- /dev/null +++ b/tests/drivers/mspi/app_fault_timer/Kconfig @@ -0,0 +1,13 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +config FLASH + default y if DT_HAS_JEDEC_MSPI_NOR_ENABLED + +config FLASH_PAGE_LAYOUT + default y if DT_HAS_JEDEC_MSPI_NOR_ENABLED + +source "Kconfig.zephyr" diff --git a/tests/drivers/mspi/app_fault_timer/boards/emul_device.overlay b/tests/drivers/mspi/app_fault_timer/boards/emul_device.overlay new file mode 100644 index 000000000000..b319c4dfcc75 --- /dev/null +++ b/tests/drivers/mspi/app_fault_timer/boards/emul_device.overlay @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2026 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +&hpf_mspi { + mspi_device@0 { + compatible = "zephyr,mspi-emul-device"; + status = "okay"; + reg = <0>; + + mspi-max-frequency = ; + mspi-io-mode = "MSPI_IO_MODE_QUAD_1_4_4"; + mspi-data-rate = "MSPI_DATA_RATE_SINGLE"; + mspi-hardware-ce-num = <0>; + mspi-cpp-mode = "MSPI_CPP_MODE_0"; + mspi-endian = "MSPI_BIG_ENDIAN"; + mspi-ce-polarity = "MSPI_CE_ACTIVE_LOW"; + }; +}; diff --git a/tests/drivers/mspi/app_fault_timer/prj.conf b/tests/drivers/mspi/app_fault_timer/prj.conf index 3091d4af2cf5..138bccfda978 100644 --- a/tests/drivers/mspi/app_fault_timer/prj.conf +++ b/tests/drivers/mspi/app_fault_timer/prj.conf @@ -6,5 +6,3 @@ CONFIG_TEST=y CONFIG_ZTEST=y -CONFIG_FLASH=y -CONFIG_FLASH_PAGE_LAYOUT=y diff --git a/tests/drivers/mspi/app_fault_timer/src/main.c b/tests/drivers/mspi/app_fault_timer/src/main.c index e5872d9283aa..893c23c93945 100644 --- a/tests/drivers/mspi/app_fault_timer/src/main.c +++ b/tests/drivers/mspi/app_fault_timer/src/main.c @@ -7,15 +7,35 @@ #include #include #include -#include #include -#define TEST_AREA_DEV_NODE DT_INST(0, jedec_mspi_nor) -#define TEST_AREA_OFFSET 0x0 -#define EXPECTED_SIZE 64 -#define TIMEOUT 15000000 +#if IS_ENABLED(CONFIG_DT_HAS_JEDEC_MSPI_NOR_ENABLED) +#include +#elif IS_ENABLED(CONFIG_DT_HAS_ZEPHYR_MSPI_EMUL_DEVICE_ENABLED) +#include +#else +#error "The test requires an enabled MSPI NOR flash memory or an emulated MSPI device" +#endif + +#define BUFFER_SIZE 64 +#define TIMEOUT 15000000 + +#if IS_ENABLED(CONFIG_DT_HAS_JEDEC_MSPI_NOR_ENABLED) +#define FLASH_TEST_AREA_DEV_NODE DT_INST(0, jedec_mspi_nor) +#define FLASH_TEST_AREA_OFFSET 0x0 + +static const struct device *const flash_dev = DEVICE_DT_GET(FLASH_TEST_AREA_DEV_NODE); +#else +#define MSPI_BUS_NODE DT_NODELABEL(hpf_mspi) +#define EMUL_DEV_NODE DT_INST(0, zephyr_mspi_emul_device) + +static const struct device *mspi_bus = DEVICE_DT_GET(MSPI_BUS_NODE); +static const struct mspi_dev_id emul_dev_id = { + .dev_idx = 0xFF, +}; +static const struct mspi_dev_cfg emul_dev_cfg = MSPI_DEVICE_CONFIG_DT(EMUL_DEV_NODE); +#endif -static const struct device *const flash_dev = DEVICE_DT_GET(TEST_AREA_DEV_NODE); static const struct device *const flpr_fault_timer = DEVICE_DT_GET(DT_NODELABEL(fault_timer)); static volatile bool timer_irq; @@ -39,7 +59,13 @@ static void fault_timer_before(void *arg) .ticks = counter_us_to_ticks(flpr_fault_timer, CONFIG_MSPI_HPF_FAULT_TIMEOUT) }; +#if IS_ENABLED(CONFIG_DT_HAS_JEDEC_MSPI_NOR_ENABLED) zassert_true(device_is_ready(flash_dev)); +#else + zassert_true(device_is_ready(mspi_bus)); + rc = mspi_dev_config(mspi_bus, &emul_dev_id, MSPI_DEVICE_CONFIG_ALL, &emul_dev_cfg); + zassert_equal(rc, 0, "Cannot configure an emulated MSPI device"); +#endif zassert_true(device_is_ready(flpr_fault_timer)); rc = counter_set_top_value(flpr_fault_timer, &top_cfg); zassert_equal(rc, 0, "Cannot set top value"); @@ -55,16 +81,35 @@ static void fault_timer_before(void *arg) ZTEST(hpf_fault_timer, test_timer_timeout) { int rc; - uint8_t buf[EXPECTED_SIZE]; - volatile uint32_t count; + uint8_t buf[BUFFER_SIZE] = { 0 }; + volatile uint32_t count = 0; /* 1. The timer is started and the flash is read. */ rc = counter_start(flpr_fault_timer); zassert_equal(rc, 0, "Cannot start timer"); - - rc = flash_read(flash_dev, TEST_AREA_OFFSET, buf, EXPECTED_SIZE); +#if IS_ENABLED(CONFIG_DT_HAS_JEDEC_MSPI_NOR_ENABLED) + rc = flash_read(flash_dev, FLASH_TEST_AREA_OFFSET, buf, BUFFER_SIZE); zassert_equal(rc, 0, "Cannot read flash"); +#else + struct mspi_xfer_packet packet = { + .dir = MSPI_TX, + .cmd = 0x87654321, + .address = 0x12345678, + .data_buf = buf, + .num_bytes = sizeof(buf) + }; + struct mspi_xfer xfer = { + .xfer_mode = MSPI_PIO, + .packets = &packet, + .num_packet = 1, + .timeout = 10, + .cmd_length = 4, + .addr_length = 4 + }; + rc = mspi_transceive(mspi_bus, &emul_dev_id, &xfer); + zassert_equal(rc, 0, "Cannot write on MSPI bus"); +#endif while (timer_irq == false && count < TIMEOUT) { count++; } diff --git a/tests/drivers/mspi/app_fault_timer/testcase.yaml b/tests/drivers/mspi/app_fault_timer/testcase.yaml index 9d2849d52cb0..a76a0a554fff 100644 --- a/tests/drivers/mspi/app_fault_timer/testcase.yaml +++ b/tests/drivers/mspi/app_fault_timer/testcase.yaml @@ -4,14 +4,21 @@ common: - drivers - mspi harness: ztest - harness_config: - fixture: external_flash tests: drivers.mspi.hpf_app_fault_timer: + harness_config: + fixture: external_flash platform_allow: - nrf54l15dk/nrf54l15/cpuapp - nrf54lm20dk/nrf54lm20a/cpuapp - nrf54lm20dk/nrf54lm20b/cpuapp integration_platforms: - nrf54l15dk/nrf54l15/cpuapp + drivers.mspi.hpf_app_fault_timer.emul_mspi_dev: + platform_allow: + - nrf54lv10dk/nrf54lv10a/cpuapp + integration_platforms: + - nrf54lv10dk/nrf54lv10a/cpuapp + extra_args: + - EXTRA_DTC_OVERLAY_FILE="boards/emul_device.overlay" diff --git a/tests/drivers/mspi/error_cases/boards/nrf54lv10dk_nrf54lv10a_cpuapp.overlay b/tests/drivers/mspi/error_cases/boards/nrf54lv10dk_nrf54lv10a_cpuapp.overlay new file mode 100644 index 000000000000..eb247baff426 --- /dev/null +++ b/tests/drivers/mspi/error_cases/boards/nrf54lv10dk_nrf54lv10a_cpuapp.overlay @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2026 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/ { + aliases { + mspi0 = &hpf_mspi_api; + }; +}; + +&cpuflpr_vpr { + status = "okay"; + + hpf_mspi_api: hpf_mspi_api { + compatible = "nordic,hpf-mspi-controller"; + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = ; + pinctrl-0 = <&hpf_mspi_default>; + pinctrl-1 = <&hpf_mspi_sleep>; + pinctrl-names = "default", "sleep"; + status = "okay"; + + mspi_device: mspi_device@0 { + status = "okay"; + compatible = "zephyr,mspi-emul-device"; + reg = <0x0>; + mspi-max-frequency = ; + mspi-io-mode = "MSPI_IO_MODE_SINGLE"; + mspi-data-rate = "MSPI_DATA_RATE_SINGLE"; + mspi-hardware-ce-num = <0>; + mspi-cpp-mode = "MSPI_CPP_MODE_0"; + mspi-endian = "MSPI_BIG_ENDIAN"; + mspi-ce-polarity = "MSPI_CE_ACTIVE_LOW"; + }; + }; +}; diff --git a/tests/drivers/mspi/error_cases/testcase.yaml b/tests/drivers/mspi/error_cases/testcase.yaml index bf355cc10172..f571f64202a0 100644 --- a/tests/drivers/mspi/error_cases/testcase.yaml +++ b/tests/drivers/mspi/error_cases/testcase.yaml @@ -8,11 +8,10 @@ common: tests: drivers.mspi.error_cases.hpf: harness: ztest - harness_config: - fixture: external_flash platform_allow: - nrf54l15dk/nrf54l15/cpuapp - nrf54lm20dk/nrf54lm20a/cpuapp - nrf54lm20dk/nrf54lm20b/cpuapp + - nrf54lv10dk/nrf54lv10a/cpuapp integration_platforms: - nrf54l15dk/nrf54l15/cpuapp diff --git a/tests/drivers/mspi/mspi_with_spis/Kconfig b/tests/drivers/mspi/mspi_with_spis/Kconfig new file mode 100644 index 000000000000..5462fd3d5126 --- /dev/null +++ b/tests/drivers/mspi/mspi_with_spis/Kconfig @@ -0,0 +1,11 @@ +# +# Copyright (c) 2026 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +config TEST_MSPI_DATA_LINES_MAX + int "Maximum number of MSPI data lines used in the test" + default 4 + +source "Kconfig.zephyr" diff --git a/tests/drivers/mspi/mspi_with_spis/boards/hpf_mspi.overlay b/tests/drivers/mspi/mspi_with_spis/boards/hpf_mspi.overlay new file mode 100644 index 000000000000..6808c3102bcc --- /dev/null +++ b/tests/drivers/mspi/mspi_with_spis/boards/hpf_mspi.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2026 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +dut: &hpf_mspi {}; diff --git a/tests/drivers/mspi/mspi_with_spis/boards/nrf54h20dk_nrf54h20_cpuapp_sqspi.overlay b/tests/drivers/mspi/mspi_with_spis/boards/nrf54h20dk_nrf54h20_cpuapp_sqspi.overlay index 7c795f052218..87a5b5191478 100644 --- a/tests/drivers/mspi/mspi_with_spis/boards/nrf54h20dk_nrf54h20_cpuapp_sqspi.overlay +++ b/tests/drivers/mspi/mspi_with_spis/boards/nrf54h20dk_nrf54h20_cpuapp_sqspi.overlay @@ -8,6 +8,12 @@ * - P7.5 <-> P0.9 */ +/ { + zephyr,user { + mspi-ce-num = <1>; + }; +}; + &pinctrl { sqspi_default: sqspi_default { group1 { diff --git a/tests/drivers/mspi/mspi_with_spis/boards/nrf54lv10dk_nrf54lv10a_cpuapp.conf b/tests/drivers/mspi/mspi_with_spis/boards/nrf54lv10dk_nrf54lv10a_cpuapp.conf new file mode 100644 index 000000000000..8d6388de103f --- /dev/null +++ b/tests/drivers/mspi/mspi_with_spis/boards/nrf54lv10dk_nrf54lv10a_cpuapp.conf @@ -0,0 +1 @@ +CONFIG_TEST_MSPI_DATA_LINES_MAX=1 diff --git a/tests/drivers/mspi/mspi_with_spis/boards/nrf54lv10dk_nrf54lv10a_cpuapp.overlay b/tests/drivers/mspi/mspi_with_spis/boards/nrf54lv10dk_nrf54lv10a_cpuapp.overlay new file mode 100644 index 000000000000..686705fbd7c2 --- /dev/null +++ b/tests/drivers/mspi/mspi_with_spis/boards/nrf54lv10dk_nrf54lv10a_cpuapp.overlay @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2026 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +/* + * Wiring required for the test: + * - P1.16 <-> P1.24 + * - P1.17 <-> P1.25 + * - P1.20 <-> P1.21 + */ + +/ { + zephyr,user { + mspi-ce-num = <0>; + }; +}; + +&pinctrl { + spis20_default_alt: spi20_default_alt { + group1 { + psels = , + , + , + ; + }; + }; + + spis20_sleep_alt: spis20_sleep_alt { + group1 { + psels = , + , + , + ; + low-power-enable; + }; + }; +}; + +test_line0: &spi20 { + compatible = "nordic,nrf-spis"; + status = "okay"; + def-char = <0x00>; + pinctrl-0 = <&spis20_default_alt>; + pinctrl-1 = <&spis20_sleep_alt>; + pinctrl-names = "default", "sleep"; + /delete-property/ rx-delay-supported; + /delete-property/ rx-delay; +}; diff --git a/tests/drivers/mspi/mspi_with_spis/src/main.c b/tests/drivers/mspi/mspi_with_spis/src/main.c index 205f55fdc415..73f0e3471897 100644 --- a/tests/drivers/mspi/mspi_with_spis/src/main.c +++ b/tests/drivers/mspi/mspi_with_spis/src/main.c @@ -12,9 +12,8 @@ #define MSPI_NODE DT_NODELABEL(dut) -#define DATA_LINES_MAX 4 - #define SCK_FREQUENCY MHZ(4) +#define CE_NUM DT_PROP(DT_PATH(zephyr_user), mspi_ce_num) #define CMD_LEN_MAX 2 #define ADDR_LEN_MAX 4 @@ -34,26 +33,26 @@ static const struct spi_config spis_config = { SPI_TRANSFER_MSB }; #define SPIS_DEV_ENTRY(i, _) DEVICE_DT_GET(DT_NODELABEL(test_line##i)) -static const struct device *spis_dev[DATA_LINES_MAX] = { - LISTIFY(DATA_LINES_MAX, SPIS_DEV_ENTRY, (,)) +static const struct device *spis_dev[CONFIG_TEST_MSPI_DATA_LINES_MAX] = { + LISTIFY(CONFIG_TEST_MSPI_DATA_LINES_MAX, SPIS_DEV_ENTRY, (,)) }; -static struct k_poll_signal async_sig[DATA_LINES_MAX]; -static struct k_poll_event async_evt[DATA_LINES_MAX]; +static struct k_poll_signal async_sig[CONFIG_TEST_MSPI_DATA_LINES_MAX]; +static struct k_poll_event async_evt[CONFIG_TEST_MSPI_DATA_LINES_MAX]; /* Use buffers that are one byte longer than the maximum length of a transfer, * since for some mysterious reason it often happened that when the SPIS buffer * had exactly the same size as a transfer length, the last received byte had * wrong value, although sQSPI transferred it correctly. */ -static uint8_t rx_arr[DATA_LINES_MAX] +static uint8_t rx_arr[CONFIG_TEST_MSPI_DATA_LINES_MAX] [CMD_LEN_MAX + ADDR_LEN_MAX + DATA_LEN_MAX + 1]; #define RX_BUF_ENTRY(i, _) [i] = { .buf = rx_arr[i], .len = sizeof(rx_arr[i]), } static const struct spi_buf rx_buf[] = { - LISTIFY(DATA_LINES_MAX, RX_BUF_ENTRY, (,)) + LISTIFY(CONFIG_TEST_MSPI_DATA_LINES_MAX, RX_BUF_ENTRY, (,)) }; #define RX_SET_ENTRY(i, _) [i] = { .buffers = &rx_buf[i], .count = 1, } static const struct spi_buf_set rx_set[] = { - LISTIFY(DATA_LINES_MAX, RX_SET_ENTRY, (,)) + LISTIFY(CONFIG_TEST_MSPI_DATA_LINES_MAX, RX_SET_ENTRY, (,)) }; static uint32_t get_octet(uint8_t *octet, uint8_t num_lines, uint32_t stream_pos) @@ -162,7 +161,7 @@ static void test_tx_transfer(struct mspi_xfer *xfer, uint8_t cmd_lines, static void test_tx_transfers(enum mspi_io_mode io_mode) { struct mspi_dev_cfg dev_cfg = { - .ce_num = 1, + .ce_num = CE_NUM, .freq = SCK_FREQUENCY, .io_mode = io_mode, .data_rate = MSPI_DATA_RATE_SINGLE, @@ -270,6 +269,7 @@ ZTEST(mspi_with_spis, test_tx_single) test_tx_transfers(MSPI_IO_MODE_SINGLE); } +#if CONFIG_TEST_MSPI_DATA_LINES_MAX >= 2 ZTEST(mspi_with_spis, test_tx_dual_1_1_2) { test_tx_transfers(MSPI_IO_MODE_DUAL_1_1_2); @@ -279,7 +279,9 @@ ZTEST(mspi_with_spis, test_tx_dual_1_2_2) { test_tx_transfers(MSPI_IO_MODE_DUAL_1_2_2); } +#endif +#if CONFIG_TEST_MSPI_DATA_LINES_MAX >= 4 ZTEST(mspi_with_spis, test_tx_quad_1_1_4) { test_tx_transfers(MSPI_IO_MODE_QUAD_1_1_4); @@ -289,6 +291,7 @@ ZTEST(mspi_with_spis, test_tx_quad_1_4_4) { test_tx_transfers(MSPI_IO_MODE_QUAD_1_4_4); } +#endif static void *setup(void) { diff --git a/tests/drivers/mspi/mspi_with_spis/testcase.yaml b/tests/drivers/mspi/mspi_with_spis/testcase.yaml index d0648f4a9709..1c3b6ee8141a 100644 --- a/tests/drivers/mspi/mspi_with_spis/testcase.yaml +++ b/tests/drivers/mspi/mspi_with_spis/testcase.yaml @@ -4,14 +4,27 @@ common: - mspi - ci_tests_drivers_sqspi harness: ztest - harness_config: - fixture: mspi_spis_loopback tests: drivers.mspi.mspi_with_spis.nrf54h20.sqspi: + harness_config: + fixture: mspi_spis_loopback platform_allow: - nrf54h20dk/nrf54h20/cpuapp integration_platforms: - nrf54h20dk/nrf54h20/cpuapp extra_args: - DTC_OVERLAY_FILE="boards/nrf54h20dk_nrf54h20_cpuapp_sqspi.overlay" + drivers.mspi.mspi_with_spis.nrf54lv10.hpf: + harness_config: + fixture: gpio_loopback + platform_allow: + - nrf54lv10dk/nrf54lv10a/cpuapp + integration_platforms: + - nrf54lv10dk/nrf54lv10a/cpuapp + extra_args: + - EXTRA_DTC_OVERLAY_FILE="boards/hpf_mspi.overlay" + - SB_CONFIG_VPR_LAUNCHER=n + - SB_CONFIG_PARTITION_MANAGER=n + - SB_CONFIG_HPF=y + - SB_CONFIG_HPF_MSPI=y diff --git a/tests/drivers/mspi/trap_handler/Kconfig b/tests/drivers/mspi/trap_handler/Kconfig new file mode 100644 index 000000000000..514cdd9aa7db --- /dev/null +++ b/tests/drivers/mspi/trap_handler/Kconfig @@ -0,0 +1,13 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +config FLASH + default y if DT_HAS_JEDEC_MSPI_NOR_ENABLED + +config FLASH_PAGE_LAYOUT + default y if DT_HAS_JEDEC_MSPI_NOR_ENABLED + +source "Kconfig.zephyr" diff --git a/tests/drivers/mspi/trap_handler/boards/emul_device.overlay b/tests/drivers/mspi/trap_handler/boards/emul_device.overlay new file mode 100644 index 000000000000..b319c4dfcc75 --- /dev/null +++ b/tests/drivers/mspi/trap_handler/boards/emul_device.overlay @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2026 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +&hpf_mspi { + mspi_device@0 { + compatible = "zephyr,mspi-emul-device"; + status = "okay"; + reg = <0>; + + mspi-max-frequency = ; + mspi-io-mode = "MSPI_IO_MODE_QUAD_1_4_4"; + mspi-data-rate = "MSPI_DATA_RATE_SINGLE"; + mspi-hardware-ce-num = <0>; + mspi-cpp-mode = "MSPI_CPP_MODE_0"; + mspi-endian = "MSPI_BIG_ENDIAN"; + mspi-ce-polarity = "MSPI_CE_ACTIVE_LOW"; + }; +}; diff --git a/tests/drivers/mspi/trap_handler/boards/nrf54lv10dk_nrf54lv10a_cpuapp_memory.overlay b/tests/drivers/mspi/trap_handler/boards/nrf54lv10dk_nrf54lv10a_cpuapp_memory.overlay new file mode 100644 index 000000000000..14ccb57f0633 --- /dev/null +++ b/tests/drivers/mspi/trap_handler/boards/nrf54lv10dk_nrf54lv10a_cpuapp_memory.overlay @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2026 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +&sram_rx { + reg = <0x20028c00 0x07e0>; +}; + +&sram_tx { + reg = <0x200293f0 0x07e0>; +}; + +&cpuflpr_error_code { + reg = <0x20029be0 0x0020>; /* 32 bytes */ +}; + +&cpuflpr_sram_code_data { + reg = <0x20029c00 DT_SIZE_K(24)>; + ranges = <0x0 0x20029c00 DT_SIZE_K(24)>; + status = "reserved"; +}; + +&cpuflpr_rram { + reg = <0xf7000 DT_SIZE_K(24)>; + ranges = <0x0 0xf7000 DT_SIZE_K(24)>; +}; + +&cpuapp_rram { + reg = <0x0 DT_SIZE_K(988)>; + ranges = <0x0 0x0 DT_SIZE_K(988)>; + #address-cells = <1>; + #size-cells = <1>; +}; + +&cpuapp_sram { + reg = <0x20000000 DT_SIZE_K(162)>; + ranges = <0x0 0x20000000 DT_SIZE_K(162)>; +}; diff --git a/tests/drivers/mspi/trap_handler/boards/nrf54lv10dk_nrf54lv10a_cpuflpr_memory.overlay b/tests/drivers/mspi/trap_handler/boards/nrf54lv10dk_nrf54lv10a_cpuflpr_memory.overlay new file mode 100644 index 000000000000..aef363b1feb1 --- /dev/null +++ b/tests/drivers/mspi/trap_handler/boards/nrf54lv10dk_nrf54lv10a_cpuflpr_memory.overlay @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2026 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +&sram_tx { + reg = <0x20028c00 0x07e0>; +}; + +&sram_rx { + reg = <0x200293f0 0x07e0>; +}; + +&cpuflpr_error_code { + reg = <0x20029be0 0x0020>; /* 32 bytes */ +}; + +&cpuflpr_rram { + reg = <0xf7000 DT_SIZE_K(24)>; + ranges = <0x0 0xf7000 DT_SIZE_K(24)>; +}; + +&cpuflpr_code_partition { + reg = <0x0 DT_SIZE_K(24)>; +}; + +&cpuflpr_sram { + reg = <0x20029c00 DT_SIZE_K(24)>; + ranges = <0x0 0x20029c00 DT_SIZE_K(24)>; +}; diff --git a/tests/drivers/mspi/trap_handler/prj.conf b/tests/drivers/mspi/trap_handler/prj.conf index 5f3bcc52f0cc..7f7dc6a3ece6 100644 --- a/tests/drivers/mspi/trap_handler/prj.conf +++ b/tests/drivers/mspi/trap_handler/prj.conf @@ -6,7 +6,5 @@ CONFIG_TEST=y CONFIG_ZTEST=y -CONFIG_FLASH=y -CONFIG_FLASH_PAGE_LAYOUT=y CONFIG_MAIN_STACK_SIZE=2048 CONFIG_ZTEST_STACK_SIZE=4096 diff --git a/tests/drivers/mspi/trap_handler/src/main.c b/tests/drivers/mspi/trap_handler/src/main.c index e4d734304dbc..4a0ddb1545ad 100644 --- a/tests/drivers/mspi/trap_handler/src/main.c +++ b/tests/drivers/mspi/trap_handler/src/main.c @@ -11,9 +11,11 @@ #define MSPI_BUS_NODE DT_NODELABEL(hpf_mspi) +#if !IS_ENABLED(CONFIG_DT_HAS_ZEPHYR_MSPI_EMUL_DEVICE_ENABLED) static const struct device *mspi_devices[] = { DT_FOREACH_CHILD_STATUS_OKAY_SEP(MSPI_BUS_NODE, DEVICE_DT_GET, (,)) }; +#endif static struct mspi_dev_cfg device_cfg[] = { DT_FOREACH_CHILD_STATUS_OKAY_SEP(MSPI_BUS_NODE, MSPI_DEVICE_CONFIG_DT, (,)) @@ -28,8 +30,9 @@ ZTEST(hpf_trap_handler, test_trap_handler) }; zassert_true(device_is_ready(mspi_bus), "mspi_bus is not ready"); +#if !IS_ENABLED(CONFIG_DT_HAS_ZEPHYR_MSPI_EMUL_DEVICE_ENABLED) zassert_true(device_is_ready(mspi_devices[0]), "mspi_device is not ready"); - +#endif /* Push wrong device id to trigger assert on flpr app side */ ret = mspi_dev_config(mspi_bus, &dev_id, MSPI_DEVICE_CONFIG_ALL, &device_cfg[0]); zassert_equal(ret, -ETIMEDOUT, "Assert not triggered?"); diff --git a/tests/drivers/mspi/trap_handler/testcase.yaml b/tests/drivers/mspi/trap_handler/testcase.yaml index 58a89d631e95..342ddd095311 100644 --- a/tests/drivers/mspi/trap_handler/testcase.yaml +++ b/tests/drivers/mspi/trap_handler/testcase.yaml @@ -6,13 +6,14 @@ common: sysbuild: true harness: console harness_config: - fixture: external_flash type: one_line regex: - ">>> HPF APP FATAL ERROR" tests: drivers.mspi.hpf_trap_handler.l15: + harness_config: + fixture: external_flash platform_allow: - nrf54l15dk/nrf54l15/cpuapp integration_platforms: @@ -33,3 +34,13 @@ tests: - hpf_mspi_CONFIG_ASSERT=y - hpf_mspi_CONFIG_ASSERT_TEST=y - hpf_mspi_EXTRA_DTC_OVERLAY_FILE="${ZEPHYR_NRF_MODULE_DIR}/tests/drivers/mspi/trap_handler/boards/nrf54lm20dk_nrf54lm20_cpuflpr_memory.overlay" + drivers.mspi.hpf_trap_handler.lv10: + platform_allow: + - nrf54lv10dk/nrf54lv10a/cpuapp + integration_platforms: + - nrf54lv10dk/nrf54lv10a/cpuapp + extra_args: + - EXTRA_DTC_OVERLAY_FILE="./boards/nrf54lv10dk_nrf54lv10a_cpuapp_memory.overlay;./boards/emul_device.overlay" + - hpf_mspi_CONFIG_ASSERT=y + - hpf_mspi_CONFIG_ASSERT_TEST=y + - hpf_mspi_EXTRA_DTC_OVERLAY_FILE="${ZEPHYR_NRF_MODULE_DIR}/tests/drivers/mspi/trap_handler/boards/nrf54lv10dk_nrf54lv10a_cpuflpr_memory.overlay" diff --git a/west.yml b/west.yml index 969cff2f5c1c..076988d8274a 100644 --- a/west.yml +++ b/west.yml @@ -87,7 +87,6 @@ manifest: - cmsis_6 - edtt - fatfs - - hal_nordic - hal_st # required for ST sensors (unrelated to STM32 MCUs) - hal_tdk # required for Invensense sensors such as ICM42670 - hal_wurthelektronik @@ -117,6 +116,13 @@ manifest: # # Some of these are also Zephyr modules which have NCS-specific # changes. + - name: hal_nordic + revision: nrfx-removed + remote: zephyrproject + path: modules/hal/nor + - name: nrfx + revision: pull/1197/head + path: modules/hal/nor/nrfx - name: wfa-qt-control-app repo-path: sdk-wi-fiquicktrack-controlappc path: modules/lib/wfa-qt-control-app