From c6ad5be9a5e3dfe643c668a8dd5f9ccee5276264 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Mon, 22 Nov 2021 14:58:29 +0200 Subject: [PATCH 01/79] boards/riscv/mpfs/icicle/configs/standalone: Add a standalone target - boots from eNVM - uses lim memory for RAM - has console on uart 0 - has procfs enabled - has most of nsh commands enabled Signed-off-by: Jukka Laitinen --- .../mpfs/icicle/configs/standalone/defconfig | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 boards/risc-v/mpfs/icicle/configs/standalone/defconfig diff --git a/boards/risc-v/mpfs/icicle/configs/standalone/defconfig b/boards/risc-v/mpfs/icicle/configs/standalone/defconfig new file mode 100644 index 0000000000000..7958978dacb46 --- /dev/null +++ b/boards/risc-v/mpfs/icicle/configs/standalone/defconfig @@ -0,0 +1,63 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="icicle" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_ICICLE_MPFS=y +CONFIG_ARCH_CHIP="mpfs" +CONFIG_ARCH_CHIP_MPFS250T_FCVG484=y +CONFIG_ARCH_CHIP_MPFS=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARD_LOOPSPERMSEC=54000 +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_ERROR=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FS=y +CONFIG_DEBUG_FS_ERROR=y +CONFIG_FS_PROCFS=y +CONFIG_FS_ROMFS=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INIT_STACKSIZE=3072 +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_FLOATINGPOINT=y +CONFIG_LIBC_HOSTNAME="icicle" +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_MEMSET_64BIT=y +CONFIG_MEMSET_OPTSPEED=y +CONFIG_MPFS_BOOTLOADER=y +CONFIG_MPFS_BOOT_HART=1 +CONFIG_MPFS_DDR_INIT=y +CONFIG_MPFS_ENABLE_DPFPU=y +CONFIG_MPFS_UART0=y +CONFIG_MPFS_UART1=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_DISABLE_IFUPDOWN=y +CONFIG_NSH_DISABLE_MKDIR=y +CONFIG_NSH_DISABLE_RM=y +CONFIG_NSH_DISABLE_RMDIR=y +CONFIG_NSH_DISABLE_UMOUNT=y +CONFIG_NSH_LINELEN=160 +CONFIG_NSH_STRERROR=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=1048576 +CONFIG_RAM_START=0x08000000 +CONFIG_RAW_BINARY=y +CONFIG_READLINE_CMD_HISTORY=y +CONFIG_SCHED_HPWORK=y +CONFIG_START_MONTH=4 +CONFIG_START_YEAR=2021 +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_TIME64=y +CONFIG_TASK_NAME_SIZE=20 +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_UART1_BAUD=2000000 +CONFIG_USEC_PER_TICK=1000 From ffd0ae51de73055612a339f6d8489815467615a3 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Wed, 24 Nov 2021 10:13:55 +0200 Subject: [PATCH 02/79] Fix the check workflow for tiiuae repo - Change git repository urls to point to our tiiuae repos for nuttx & nuttx apps - Remove most of the the build steps, leave just arm-12 and riscv; arm-12 has a build for stm32f7, and riscv for mpfs Signed-off-by: Jukka Laitinen --- .github/workflows/build.yml | 10 +++++----- .github/workflows/check.yml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 698aa21607252..849e225688ea9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -67,13 +67,13 @@ jobs: # Determine the repo and leave that unset to use the normal checkout behavior # of using the merge commit instead of HEAD case $GITHUB_REPOSITORY in - "apache/nuttx") + "tiiuae/nuttx") # OS echo "Triggered by change in OS" APPS_REF=$REF_NAME ;; - "apache/nuttx-apps" ) + "tiiuae/incubator-nuttx-apps" ) # APPS OS_REF=$REF_NAME echo "Triggered by change in APPS" @@ -91,7 +91,7 @@ jobs: - name: Checkout nuttx repo uses: actions/checkout@v3 with: - repository: apache/nuttx + repository: tiiuae/nuttx ref: ${{ steps.gittargets.outputs.os_ref }} path: sources/nuttx fetch-depth: 1 @@ -101,7 +101,7 @@ jobs: - name: Checkout apps repo uses: actions/checkout@v3 with: - repository: apache/nuttx-apps + repository: tiiuae/incubator-nuttx-apps ref: ${{ steps.gittargets.outputs.apps_ref }} path: sources/apps fetch-depth: 1 @@ -123,7 +123,7 @@ jobs: strategy: matrix: - boards: [arm-01, arm-02, arm-03, arm-04, arm-05, arm-06, arm-07, arm-08, arm-09, arm-10, arm-11, arm-12, arm-13, other, risc-v, sim-01, sim-02, xtensa, codechecker] + boards: [arm-12, risc-v] steps: - name: Download Source Artifact diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index b2ce7b9ccd8a4..28adffb82a5e3 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -32,7 +32,7 @@ jobs: - name: Checkout nuttx repo uses: actions/checkout@v3 with: - repository: apache/nuttx + repository: tiiuae/nuttx path: nuttx fetch-depth: 0 From 477df1afe4a7e674b11e4197c2b07dcd6ce1cce4 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Thu, 21 Jul 2022 14:14:53 +0400 Subject: [PATCH 03/79] arch/risc-v/src/opensbi/Make.defs: Switch opensbi to the nuttx/size optimized version in tiiuae repo Signed-off-by: Jukka Laitinen --- arch/risc-v/src/opensbi/Make.defs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/risc-v/src/opensbi/Make.defs b/arch/risc-v/src/opensbi/Make.defs index b60878639b8e5..b5962a986cf05 100644 --- a/arch/risc-v/src/opensbi/Make.defs +++ b/arch/risc-v/src/opensbi/Make.defs @@ -37,10 +37,10 @@ INCLUDES += ${INCDIR_PREFIX}$(ARCH_SRCDIR)$(DELIM)opensbi$(DELIM)opensbi-3rdpar SBI_DIR := opensbi OPENSBI_UNPACK = opensbi-3rdparty -OPENSBI_COMMIT = 4998a712b2ab504eff306110879ee05af6050177 -OPENSBI_URL = https://github.com/riscv-software-src/opensbi/tarball +OPENSBI_COMMIT = 19b05a2fd4fd04329d26f73a73e179631d7ae44c +OPENSBI_URL = https://github.com/tiiuae/opensbi/tarball OPENSBI_TARBALL = opensbi.tar.gz -OPENSBI_DIR = riscv-software-src-opensbi-4998a71 +OPENSBI_DIR = tiiuae-opensbi-19b05a2 $(OPENSBI_TARBALL): $(call DOWNLOAD,$(OPENSBI_URL),$(OPENSBI_COMMIT),opensbi/$(OPENSBI_TARBALL)) From c9f3f900000c53c6f966eddb828ae4a729a19ca8 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Wed, 17 Aug 2022 15:43:38 +0400 Subject: [PATCH 04/79] [REVERTME] arch/risc-v/src/mpfs/mpfs_ethernet.c: Hack the ethernet driver to re-initialize on rx timeout If the interface is UP, and no packets are received in 30s, re-initialize the interface by calling the already implemented mpfs_txtimeout_expiry. This is a temporary workaround for a bug where IF might be UP and working but packets can only be transmitted. Receive side just doesn't work at all. The original bug can be re-produced easily by disconnecting and reconnecting the ethernet cable while the IF is up. Signed-off-by: Jukka Laitinen --- arch/risc-v/src/mpfs/mpfs_ethernet.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/arch/risc-v/src/mpfs/mpfs_ethernet.c b/arch/risc-v/src/mpfs/mpfs_ethernet.c index 7b058d9424445..d49360255262f 100644 --- a/arch/risc-v/src/mpfs/mpfs_ethernet.c +++ b/arch/risc-v/src/mpfs/mpfs_ethernet.c @@ -155,6 +155,10 @@ #define MPFS_TXTIMEOUT (60 * CLK_TCK) +/* RX timeout = 30s */ + +#define MPFS_RXTIMEOUT (30 * CLK_TCK) + /* PHY reset tim in loop counts */ #define PHY_RESET_WAIT_COUNT (10) @@ -250,6 +254,7 @@ struct mpfs_ethmac_s uint8_t intf; /* Ethernet interface number */ uint8_t phyaddr; /* PHY address */ struct wdog_s txtimeout; /* TX timeout timer */ + struct wdog_s rxtimeout; /* RX timeout timer */ struct work_s irqwork; /* For deferring interrupt work to the work queue */ struct work_s pollwork; /* For deferring poll work to the work queue */ @@ -366,6 +371,7 @@ static void mpfs_ipv6multicast(struct sam_gmac_s *priv); #endif static void mpfs_interrupt_work(void *arg); +static void mpfs_txtimeout_expiry(wdparm_t arg); /**************************************************************************** * Private Functions @@ -447,6 +453,14 @@ static int mpfs_interrupt_0(int irq, void *context, void *arg) wd_cancel(&priv->txtimeout); } + if ((isr & GEM_INT_RECEIVE_COMPLETE) != 0) + { + /* If a RX transfer just completed, restart the timeout */ + + wd_start(&priv->rxtimeout, MPFS_RXTIMEOUT, + mpfs_txtimeout_expiry, (wdparm_t)priv); + } + /* Schedule to perform the interrupt processing on the worker thread. */ work_queue(ETHWORK, &priv->irqwork, mpfs_interrupt_work, priv, 0); @@ -1528,6 +1542,13 @@ static int mpfs_ifup(struct net_driver_s *dev) up_enable_irq(priv->mac_q_int[2]); up_enable_irq(priv->mac_q_int[3]); + /* Set up the RX timeout. If we don't receive anything in time, try + * to re-initialize + */ + + wd_start(&priv->rxtimeout, MPFS_RXTIMEOUT, + mpfs_txtimeout_expiry, (wdparm_t)priv); + return OK; } @@ -1571,6 +1592,10 @@ static int mpfs_ifdown(struct net_driver_s *dev) wd_cancel(&priv->txtimeout); + /* Cancel the RX timeout timers */ + + wd_cancel(&priv->rxtimeout); + /* Put the MAC in its reset, non-operational state. This should be * a known configuration that will guarantee the mpfs_ifup() always * successfully brings the interface back up. From 902c21ac5dd006330d186f171675e6d6d4be078d Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Wed, 14 Sep 2022 12:50:22 +0400 Subject: [PATCH 05/79] [HACK] Set SD-card speed to 50MHz SD-card clock speed is just forced to 50MHz. Note that to be correct, one should first set the SD-card into high-speed mode, but currently NuttX doesn't support this. With our cards, just setting the interface to 50MHz seems to work fine, and it removes the issue with 25MHZ clock causing disturbance on GPS bands. Typically cards which support high-speed mode just work with 50MHz interface clock. This patch should be reverted when the NuttX supports high-speed mode, and we can properly set it. Signed-off-by: Jukka Laitinen --- arch/risc-v/src/mpfs/mpfs_emmcsd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_emmcsd.c b/arch/risc-v/src/mpfs/mpfs_emmcsd.c index 873fc4ddb09ac..50856e2dbb685 100644 --- a/arch/risc-v/src/mpfs/mpfs_emmcsd.c +++ b/arch/risc-v/src/mpfs/mpfs_emmcsd.c @@ -156,7 +156,7 @@ /* Provide default SD-card 4bit clk if unset at board.h */ #ifndef MPFS_SD_CLOCK_4BIT -# define MPFS_SD_CLOCK_4BIT MPFS_MMC_CLOCK_25MHZ +# define MPFS_SD_CLOCK_4BIT MPFS_MMC_CLOCK_50MHZ #endif /* Define the Hardware FIFO size */ @@ -1869,7 +1869,7 @@ static void mpfs_clock(struct sdio_dev_s *dev, enum sdio_clock_e rate) /* SD normal operation clocking (narrow 1-bit mode) */ case CLOCK_SD_TRANSFER_1BIT: - clckr = MPFS_MMC_CLOCK_25MHZ; + clckr = MPFS_MMC_CLOCK_50MHZ; break; } From c03e56b29a99e18e4153b054b0c0825db579c838 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Tue, 20 Sep 2022 14:56:42 +0300 Subject: [PATCH 06/79] opensbi: Take SBI version that removes console into use --- arch/risc-v/src/opensbi/Make.defs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/risc-v/src/opensbi/Make.defs b/arch/risc-v/src/opensbi/Make.defs index b5962a986cf05..8bee7d102c77e 100644 --- a/arch/risc-v/src/opensbi/Make.defs +++ b/arch/risc-v/src/opensbi/Make.defs @@ -37,10 +37,10 @@ INCLUDES += ${INCDIR_PREFIX}$(ARCH_SRCDIR)$(DELIM)opensbi$(DELIM)opensbi-3rdpar SBI_DIR := opensbi OPENSBI_UNPACK = opensbi-3rdparty -OPENSBI_COMMIT = 19b05a2fd4fd04329d26f73a73e179631d7ae44c +OPENSBI_COMMIT = b18bb7ce78d4e5504a9cbd8df7b57d795f489a0a OPENSBI_URL = https://github.com/tiiuae/opensbi/tarball OPENSBI_TARBALL = opensbi.tar.gz -OPENSBI_DIR = tiiuae-opensbi-19b05a2 +OPENSBI_DIR = tiiuae-opensbi-b18bb7c $(OPENSBI_TARBALL): $(call DOWNLOAD,$(OPENSBI_URL),$(OPENSBI_COMMIT),opensbi/$(OPENSBI_TARBALL)) From f10e65095eaf4b1cad400a90383ab2b50c783e58 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Wed, 28 Sep 2022 10:56:19 +0400 Subject: [PATCH 07/79] Fix standalone defconfig for CI Signed-off-by: Jukka Laitinen --- boards/risc-v/mpfs/icicle/configs/standalone/defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/boards/risc-v/mpfs/icicle/configs/standalone/defconfig b/boards/risc-v/mpfs/icicle/configs/standalone/defconfig index 7958978dacb46..78d417dfdee52 100644 --- a/boards/risc-v/mpfs/icicle/configs/standalone/defconfig +++ b/boards/risc-v/mpfs/icicle/configs/standalone/defconfig @@ -27,7 +27,6 @@ CONFIG_IDLETHREAD_STACKSIZE=2048 CONFIG_INIT_ENTRYPOINT="nsh_main" CONFIG_INIT_STACKSIZE=3072 CONFIG_INTELHEX_BINARY=y -CONFIG_LIBC_FLOATINGPOINT=y CONFIG_LIBC_HOSTNAME="icicle" CONFIG_LIBC_PERROR_STDOUT=y CONFIG_LIBC_STRERROR=y From adfe82a0ddf94d1b309a480e6be3da86642a393d Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Wed, 28 Sep 2022 11:42:00 +0400 Subject: [PATCH 08/79] arch/risc-v/src/mpfs/mpfs_clockconfig.c: Flag out code only used in bootloader This removes the need to have all the DDR/clock configuration related "LIBERODEFS" flags defined, when not building a standalone/coldboot configuration All of this code is unused when not building with CONFIG_MPFS_BOOTLOADER Signed-off-by: Jukka Laitinen --- arch/risc-v/src/mpfs/mpfs_clockconfig.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/risc-v/src/mpfs/mpfs_clockconfig.c b/arch/risc-v/src/mpfs/mpfs_clockconfig.c index 320021a27805f..7802560cfa838 100644 --- a/arch/risc-v/src/mpfs/mpfs_clockconfig.c +++ b/arch/risc-v/src/mpfs/mpfs_clockconfig.c @@ -143,6 +143,8 @@ enum part_type_e static uint64_t g_cpu_clock = MPFS_MSS_EXT_SGMII_REF_CLK; +#ifdef CONFIG_MPFS_BOOTLOADER + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -630,6 +632,8 @@ void mpfs_clockconfig(void) mpfs_pll_config(); } +#endif + /**************************************************************************** * Name: mpfs_get_cpuclk ****************************************************************************/ From dd3fe0beb004ccea4977e8fe3dd8b153be17f6bd Mon Sep 17 00:00:00 2001 From: haitomatic Date: Thu, 26 May 2022 16:07:53 +0300 Subject: [PATCH 09/79] arch/risc-v/src/mpfs: Add mpfs canfd socket can driver --- arch/risc-v/src/mpfs/Kconfig | 31 + arch/risc-v/src/mpfs/Make.defs | 4 + .../src/mpfs/hardware/mpfs_fpga_canfd.h | 465 +++ arch/risc-v/src/mpfs/mpfs_fpga_canfd.c | 2915 +++++++++++++++++ arch/risc-v/src/mpfs/mpfs_fpga_canfd.h | 94 + 5 files changed, 3509 insertions(+) create mode 100644 arch/risc-v/src/mpfs/hardware/mpfs_fpga_canfd.h create mode 100644 arch/risc-v/src/mpfs/mpfs_fpga_canfd.c create mode 100644 arch/risc-v/src/mpfs/mpfs_fpga_canfd.h diff --git a/arch/risc-v/src/mpfs/Kconfig b/arch/risc-v/src/mpfs/Kconfig index 9245994e36113..cba838b534cad 100644 --- a/arch/risc-v/src/mpfs/Kconfig +++ b/arch/risc-v/src/mpfs/Kconfig @@ -575,6 +575,37 @@ config MPFS_COREPWM1_NCHANNELS range 1 16 depends on MPFS_COREPWM1 +comment "CAN-FD Options" + +config MPFS_CANFD + bool "CAN FD" + select ARCH_HAVE_CAN_ERRORS + select NET_CAN_HAVE_CANFD + select NET_CAN_EXTID + select NET_CAN_HAVE_TX_DEADLINE + default n + +config MPFS_CANFD_BASE + hex "Base address for the instance" + default 0x46000000 + depends on MPFS_CANFD + +config MPFS_CANFD_CLK + int "Clock frequency of the CANFD block (Hz)" + default 62500000 + range 1000000 100000000 + depends on MPFS_CANFD + +config MPFS_CANFD_ARBI_BITRATE + int "CAN FD Arbitration phase bitrate" + default 1000000 + depends on MPFS_CANFD + +config MPFS_CANFD_DATA_BITRATE + int "CAN Arbitration phase bitrate" + default 4000000 + depends on MPFS_CANFD + endmenu config MPFS_DMA diff --git a/arch/risc-v/src/mpfs/Make.defs b/arch/risc-v/src/mpfs/Make.defs index d4765ba0be8fb..a45a133fac850 100644 --- a/arch/risc-v/src/mpfs/Make.defs +++ b/arch/risc-v/src/mpfs/Make.defs @@ -74,6 +74,10 @@ ifeq (${CONFIG_MPFS_HAVE_COREPWM},y) CHIP_CSRCS += mpfs_corepwm.c endif +ifeq (${CONFIG_MPFS_CANFD}, y) +CHIP_CSRCS += mpfs_fpga_canfd.c +endif + ifeq (${CONFIG_MPFS_DDR_INIT},y) CHIP_CSRCS += mpfs_ddr.c endif diff --git a/arch/risc-v/src/mpfs/hardware/mpfs_fpga_canfd.h b/arch/risc-v/src/mpfs/hardware/mpfs_fpga_canfd.h new file mode 100644 index 0000000000000..e883ccef22011 --- /dev/null +++ b/arch/risc-v/src/mpfs/hardware/mpfs_fpga_canfd.h @@ -0,0 +1,465 @@ +/**************************************************************************** + * arch/risc-v/src/mpfs/hardware/mpfs_fpga_canfd.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_MPFS_HARDWARE_MPFS_FPGA_CANFD_H +#define __ARCH_RISCV_SRC_MPFS_HARDWARE_MPFS_FPGA_CANFD_H + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register Offsets *********************************************************/ + +#define MPFS_CANFD_DEVICE_ID_OFFSET (0x00) +#define MPFS_CANFD_VERSION_OFFSET (0x02) + +#define MPFS_CANFD_MODE_OFFSET (0x04) +#define MPFS_CANFD_SETTINGS_OFFSET (0x06) + +#define MPFS_CANFD_STATUS_OFFSET (0x08) + +#define MPFS_CANFD_COMMAND_OFFSET (0x0c) + +#define MPFS_CANFD_INT_STAT_OFFSET (0x10) + +#define MPFS_CANFD_INT_ENA_SET_OFFSET (0x14) + +#define MPFS_CANFD_INT_ENA_CLR_OFFSET (0x18) + +#define MPFS_CANFD_INT_MASK_SET_OFFSET (0x1c) + +#define MPFS_CANFD_INT_MASK_CLR_OFFSET (0x20) + +#define MPFS_CANFD_BTR_OFFSET (0x24) + +#define MPFS_CANFD_BTR_FD_OFFSET (0x28) + +#define MPFS_CANFD_EWL_OFFSET (0x2c) +#define MPFS_CANFD_ERP_OFFSET (0x2d) +#define MPFS_CANFD_FAULT_STATE_OFFSET (0x2e) + +#define MPFS_CANFD_REC_OFFSET (0x30) +#define MPFS_CANFD_TEC_OFFSET (0x32) + +#define MPFS_CANFD_ERR_NORM_OFFSET (0x34) +#define MPFS_CANFD_ERR_FD_OFFSET (0x36) + +#define MPFS_CANFD_CTR_PRES_OFFSET (0x38) + +#define MPFS_CANFD_FILTER_A_MASK_OFFSET (0x3c) + +#define MPFS_CANFD_FILTER_A_VAL_OFFSET (0x40) + +#define MPFS_CANFD_FILTER_B_MASK_OFFSET (0x44) + +#define MPFS_CANFD_FILTER_B_VAL_OFFSET (0x48) + +#define MPFS_CANFD_FILTER_C_MASK_OFFSET (0x4c) + +#define MPFS_CANFD_FILTER_C_VAL_OFFSET (0x50) + +#define MPFS_CANFD_FILTER_RAN_LOW_OFFSET (0x54) + +#define MPFS_CANFD_FILTER_RAN_HIGH_OFFSET (0x58) + +#define MPFS_CANFD_FILTER_CONTROL_OFFSET (0x5c) +#define MPFS_CANFD_FILTER_STATUS_OFFSET (0x5e) + +/* RX registers */ +#define MPFS_CANFD_RX_MEM_INFO_OFFSET (0x60) + +#define MPFS_CANFD_RX_POINTERS_OFFSET (0x64) + +#define MPFS_CANFD_RX_STATUS_OFFSET (0x68) +#define MPFS_CANFD_RX_SETTINGS_OFFSET (0x6a) + +#define MPFS_CANFD_RX_DATA_OFFSET (0x6c) + +/* TX registers */ +#define MPFS_CANFD_TX_STATUS_OFFSET (0x70) + +#define MPFS_CANFD_TX_COMMAND_OFFSET (0x74) +#define MPFS_CANFD_TXTB_INFO_OFFSET (0x76) + +#define MPFS_CANFD_TX_PRIORITY_OFFSET (0x78) + +#define MPFS_CANFD_ERR_CAPT_OFFSET (0x7c) +#define MPFS_CANFD_RETR_CTR_OFFSET (0x7d) +#define MPFS_CANFD_ALC_OFFSET (0x7e) + +#define MPFS_CANFD_TRV_DELAY_OFFSET (0x80) +#define MPFS_CANFD_SSP_CFG_OFFSET (0x82) + +#define MPFS_CANFD_RX_FR_CTR_OFFSET (0x84) + +#define MPFS_CANFD_TX_FR_CTR_OFFSET (0x88) + +#define MPFS_CANFD_DEBUG_REGISTER_OFFSET (0x8c) + +#define MPFS_CANFD_YOLO_OFFSET (0x90) + +#define MPFS_CANFD_TIMESTAMP_LOW_OFFSET (0x94) + +#define MPFS_CANFD_TIMESTAMP_HIGH_OFFSET (0x98) + +# define MPFS_CANFD_CTUCANFD_TXTB1_DATA_1 (0x100) +# define MPFS_CANFD_CTUCANFD_TXTB1_DATA_2 (0x104) +# define MPFS_CANFD_CTUCANFD_TXTB1_DATA_20 (0x14c) + +# define MPFS_CANFD_CTUCANFD_TXTB2_DATA_1 (0x200) +# define MPFS_CANFD_CTUCANFD_TXTB2_DATA_2 (0x204) +# define MPFS_CANFD_CTUCANFD_TXTB2_DATA_20 (0x24c) + +# define MPFS_CANFD_CTUCANFD_TXTB3_DATA_1 (0x300) +# define MPFS_CANFD_CTUCANFD_TXTB3_DATA_2 (0x304) +# define MPFS_CANFD_CTUCANFD_TXTB3_DATA_20 (0x34c) + +# define MPFS_CANFD_CTUCANFD_TXTB4_DATA_1 (0x400) +# define MPFS_CANFD_CTUCANFD_TXTB4_DATA_2 (0x404) +# define MPFS_CANFD_CTUCANFD_TXTB4_DATA_20 (0x44c) + +# define MPFS_CANFD_CTUCANFD_TXTB5_DATA_1 (0x500) +# define MPFS_CANFD_CTUCANFD_TXTB5_DATA_2 (0x504) +# define MPFS_CANFD_CTUCANFD_TXTB5_DATA_20 (0x54c) + +# define MPFS_CANFD_CTUCANFD_TXTB6_DATA_1 (0x600) +# define MPFS_CANFD_CTUCANFD_TXTB6_DATA_2 (0x604) +# define MPFS_CANFD_CTUCANFD_TXTB6_DATA_20 (0x64c) + +# define MPFS_CANFD_CTUCANFD_TXTB7_DATA_1 (0x700) +# define MPFS_CANFD_CTUCANFD_TXTB7_DATA_2 (0x704) +# define MPFS_CANFD_CTUCANFD_TXTB7_DATA_20 (0x74c) + +# define MPFS_CANFD_CTUCANFD_TXTB8_DATA_1 (0x800) +# define MPFS_CANFD_CTUCANFD_TXTB8_DATA_2 (0x804) +# define MPFS_CANFD_CTUCANFD_TXTB8_DATA_20 (0x84c) + +# define MPFS_CANFD_CTUCANFD_TST_CONTROL (0x900) +# define MPFS_CANFD_CTUCANFD_TST_DEST (0x904) +# define MPFS_CANFD_CTUCANFD_TST_WDATA (0x908) +# define MPFS_CANFD_CTUCANFD_TST_RDATA (0x90c) + +/* Control_registers memory region ******************************************/ + +/* DEVICE ID / VERSION registers */ +#define MPFS_CANFD_DEVICE_ID_DEVICE_ID_SHIFT (0) +#define MPFS_CANFD_DEVICE_ID_DEVICE_ID (0xffff << MPFS_CANFD_DEVICE_ID_DEVICE_ID_SHIFT) +#define MPFS_CANFD_DEVICE_ID_VER_MINOR_SHIFT (16) +#define MPFS_CANFD_DEVICE_ID_VER_MINOR (0xff << MPFS_CANFD_DEVICE_ID_VER_MINOR_SHIFT) +#define MPFS_CANFD_DEVICE_ID_VER_MAJOR_SHIFT (24) +#define MPFS_CANFD_DEVICE_ID_VER_MAJOR (0xff << MPFS_CANFD_DEVICE_ID_VER_MAJOR_SHIFT) + +/* MODE / SETTINGS registers */ +#define MPFS_CANFD_MODE_RST (1 << 0) +#define MPFS_CANFD_MODE_BMM (1 << 1) +#define MPFS_CANFD_MODE_STM (1 << 2) +#define MPFS_CANFD_MODE_AFM (1 << 3) +#define MPFS_CANFD_MODE_FDE (1 << 4) +#define MPFS_CANFD_MODE_TTTM (1 << 5) +#define MPFS_CANFD_MODE_ROM (1 << 6) +#define MPFS_CANFD_MODE_ACF (1 << 7) +#define MPFS_CANFD_MODE_TSTM (1 << 8) +#define MPFS_CANFD_MODE_RXBAM (1 << 9) +#define MPFS_CANFD_MODE_RTRLE (1 << 16) +#define MPFS_CANFD_MODE_RTRTH_SHIFT (17) +#define MPFS_CANFD_MODE_RTRTH (0x0f << MPFS_CANFD_MODE_RTRTH_SHIFT) +#define MPFS_CANFD_MODE_ILBP (1 << 21) +#define MPFS_CANFD_MODE_ENA (1 << 22) +#define MPFS_CANFD_MODE_NISOFD (1 << 23) +#define MPFS_CANFD_MODE_PEX (1 << 24) +#define MPFS_CANFD_MODE_TBFBO (1 << 25) +#define MPFS_CANFD_MODE_FDRF (1 << 26) + +/* STATUS registers */ +#define MPFS_CANFD_STATUS_RXNE (1 << 0) +#define MPFS_CANFD_STATUS_DOR (1 << 1) +#define MPFS_CANFD_STATUS_TXNF (1 << 2) +#define MPFS_CANFD_STATUS_EFT (1 << 3) +#define MPFS_CANFD_STATUS_RXS (1 << 4) +#define MPFS_CANFD_STATUS_TXS (1 << 5) +#define MPFS_CANFD_STATUS_EWL (1 << 6) +#define MPFS_CANFD_STATUS_IDLE (1 << 7) +#define MPFS_CANFD_STATUS_PEXS (1 << 8) +#define MPFS_CANFD_STATUS_STCNT (1 << 16) +#define MPFS_CANFD_STATUS_STRGS (1 << 17) + +/* COMMAND registers */ +#define MPFS_CANFD_COMMAND_RXRPMV (1 << 1) +#define MPFS_CANFD_COMMAND_RRB (1 << 2) +#define MPFS_CANFD_COMMAND_CDO (1 << 3) +#define MPFS_CANFD_COMMAND_ERCRST (1 << 4) +#define MPFS_CANFD_COMMAND_RXFCRST (1 << 5) +#define MPFS_CANFD_COMMAND_TXFCRST (1 << 6) +#define MPFS_CANFD_COMMAND_CPEXS (1 << 7) + +/* INT_STAT registers */ +#define MPFS_CANFD_INT_STAT_RXI (1 << 0) +#define MPFS_CANFD_INT_STAT_TXI (1 << 1) +#define MPFS_CANFD_INT_STAT_EWLI (1 << 2) +#define MPFS_CANFD_INT_STAT_DOI (1 << 3) +#define MPFS_CANFD_INT_STAT_FCSI (1 << 4) +#define MPFS_CANFD_INT_STAT_ALI (1 << 5) +#define MPFS_CANFD_INT_STAT_BEI (1 << 6) +#define MPFS_CANFD_INT_STAT_OFI (1 << 7) +#define MPFS_CANFD_INT_STAT_RXFI (1 << 8) +#define MPFS_CANFD_INT_STAT_BSI (1 << 9) +#define MPFS_CANFD_INT_STAT_RBNEI (1 << 10) +#define MPFS_CANFD_INT_STAT_TXBHCI (1 << 11) + +/* INT_ENA_SET registers */ +#define MPFS_CANFD_INT_ENA_SET_INT_ENA_SET (0x0fff << 0) + +/* INT_ENA_CLR registers */ +#define MPFS_CANFD_INT_ENA_CLR_INT_ENA_CLR (0x0fff << 0) + +/* INT_MASK_SET registers */ +#define MPFS_CANFD_INT_MASK_SET_INT_MASK_SET (0x0fff << 0) + +/* INT_MASK_CLR registers */ +#define MPFS_CANFD_INT_MASK_CLR_INT_MASK_CLR (0x0fff << 0) + +/* BTR registers */ +#define MPFS_CANFD_BTR_PROP_SHIFT (0) +#define MPFS_CANFD_BTR_PROP (0x7f << MPFS_CANFD_BTR_PROP_SHIFT) +#define MPFS_CANFD_BTR_PH1_SHIFT (7) +#define MPFS_CANFD_BTR_PH1 (0x3f << MPFS_CANFD_BTR_PH1_SHIFT) +#define MPFS_CANFD_BTR_PH2_SHIFT (13) +#define MPFS_CANFD_BTR_PH2 (0x3f << MPFS_CANFD_BTR_PH2_SHIFT) +#define MPFS_CANFD_BTR_BRP_SHIFT (19) +#define MPFS_CANFD_BTR_BRP (0xff << MPFS_CANFD_BTR_BRP_SHIFT) +#define MPFS_CANFD_BTR_SJW_SHIFT (27) +#define MPFS_CANFD_BTR_SJW (0x1f << MPFS_CANFD_BTR_SJW_SHIFT) + +/* BTR_FD registers */ +#define MPFS_CANFD_BTR_FD_PROP_FD_SHIFT (0) +#define MPFS_CANFD_BTR_FD_PROP_FD (0x3f << MPFS_CANFD_BTR_FD_PROP_FD_SHIFT) +#define MPFS_CANFD_BTR_FD_PH1_FD_SHIFT (7) +#define MPFS_CANFD_BTR_FD_PH1_FD (0x1f << MPFS_CANFD_BTR_FD_PH1_FD_SHIFT) +#define MPFS_CANFD_BTR_FD_PH2_FD_SHIFT (13) +#define MPFS_CANFD_BTR_FD_PH2_FD (0x1f << MPFS_CANFD_BTR_FD_PH2_FD_SHIFT) +#define MPFS_CANFD_BTR_FD_BRP_FD_SHIFT (19) +#define MPFS_CANFD_BTR_FD_BRP_FD (0xff << MPFS_CANFD_BTR_FD_BRP_FD_SHIFT) +#define MPFS_CANFD_BTR_FD_SJW_FD_SHIFT (27) +#define MPFS_CANFD_BTR_FD_SJW_FD (0x1f << MPFS_CANFD_BTR_FD_SJW_FD_SHIFT) + +/* EWL / ERP / FAULT_STATE registers */ +#define MPFS_CANFD_EWL_EW_LIMIT_SHIFT (0) +#define MPFS_CANFD_EWL_EW_LIMIT (0xff << MPFS_CANFD_EWL_EW_LIMIT_SHIFT) +#define MPFS_CANFD_EWL_ERP_LIMIT_SHIFT (8) +#define MPFS_CANFD_EWL_ERP_LIMIT (0xff << MPFS_CANFD_EWL_ERP_LIMIT_SHIFT) +#define MPFS_CANFD_EWL_ERA (1 << 16) +#define MPFS_CANFD_EWL_ERP (1 << 17) +#define MPFS_CANFD_EWL_BOF (1 << 18) + +/* REC / TEC registers */ +#define MPFS_CANFD_REC_REC_VAL_SHIFT (0) +#define MPFS_CANFD_REC_REC_VAL (0x01ff << MPFS_CANFD_REC_REC_VAL_SHIFT) +#define MPFS_CANFD_REC_TEC_VAL_SHIFT (16) +#define MPFS_CANFD_REC_TEC_VAL (0x01ff << MPFS_CANFD_REC_TEC_VAL_SHIFT) + +/* ERR_NORM ERR_FD registers */ +#define MPFS_CANFD_ERR_NORM_ERR_NORM_VAL_SHIFT (0) +#define MPFS_CANFD_ERR_NORM_ERR_NORM_VAL (0xffff << MPFS_CANFD_ERR_NORM_ERR_NORM_VAL_SHIFT) +#define MPFS_CANFD_ERR_NORM_ERR_FD_VAL_SHIFT (16) +#define MPFS_CANFD_ERR_NORM_ERR_FD_VAL (0xffff << MPFS_CANFD_ERR_NORM_ERR_FD_VAL_SHIFT) + +/* CTR_PRES registers */ +#define MPFS_CANFD_CTR_PRES_CTPV_SHIFT (0) +#define MPFS_CANFD_CTR_PRES_CTPV (0x01ff << MPFS_CANFD_CTR_PRES_CTPV_SHIFT) +#define MPFS_CANFD_CTR_PRES_PTX (1 << 9) +#define MPFS_CANFD_CTR_PRES_PRX (1 << 10) +#define MPFS_CANFD_CTR_PRES_ENORM (1 << 11) +#define MPFS_CANFD_CTR_PRES_EFD (1 << 12) + +/* FILTER_A_MASK registers */ +#define MPFS_CANFD_FILTER_A_MASK_BIT_MASK_A_VAL (0x1fffffff << 0) + +/* FILTER_A_VAL registers */ +#define MPFS_CANFD_FILTER_A_VAL_BIT_VAL_A_VAL (0x1fffffff << 0) + +/* FILTER_B_MASK registers */ +#define MPFS_CANFD_FILTER_B_MASK_BIT_MASK_B_VAL (0x1fffffff << 0) + +/* FILTER_B_VAL registers */ +#define MPFS_CANFD_FILTER_B_VAL_BIT_VAL_B_VAL (0x1fffffff << 0) + +/* FILTER_C_MASK registers */ +#define MPFS_CANFD_FILTER_C_MASK_BIT_MASK_C_VAL (0x1fffffff << 0) + +/* FILTER_C_VAL registers */ +#define MPFS_CANFD_FILTER_C_VAL_BIT_VAL_C_VAL (0x1fffffff << 0) + +/* FILTER_RAN_LOW registers */ +#define MPFS_CANFD_FILTER_RAN_LOW_BIT_RAN_LOW_VAL (0x1fffffff << 0) + +/* FILTER_RAN_HIGH registers */ +#define MPFS_CANFD_FILTER_RAN_HIGH_BIT_RAN_HIGH_VAL (0x1fffffff << 0) + +/* FILTER_CONTROL / FILTER_STATUS registers */ +#define MPFS_CANFD_FILTER_CONTROL_FANB (1 << 0) +#define MPFS_CANFD_FILTER_CONTROL_FANE (1 << 1) +#define MPFS_CANFD_FILTER_CONTROL_FAFB (1 << 2) +#define MPFS_CANFD_FILTER_CONTROL_FAFE (1 << 3) +#define MPFS_CANFD_FILTER_CONTROL_FBNB (1 << 4) +#define MPFS_CANFD_FILTER_CONTROL_FBNE (1 << 5) +#define MPFS_CANFD_FILTER_CONTROL_FBFB (1 << 6) +#define MPFS_CANFD_FILTER_CONTROL_FBFE (1 << 7) +#define MPFS_CANFD_FILTER_CONTROL_FCNB (1 << 8) +#define MPFS_CANFD_FILTER_CONTROL_FCNE (1 << 9) +#define MPFS_CANFD_FILTER_CONTROL_FCFB (1 << 10) +#define MPFS_CANFD_FILTER_CONTROL_FCFE (1 << 11) +#define MPFS_CANFD_FILTER_CONTROL_FRNB (1 << 12) +#define MPFS_CANFD_FILTER_CONTROL_FRNE (1 << 13) +#define MPFS_CANFD_FILTER_CONTROL_FRFB (1 << 14) +#define MPFS_CANFD_FILTER_CONTROL_FRFE (1 << 15) +#define MPFS_CANFD_FILTER_CONTROL_SFA (1 << 16) +#define MPFS_CANFD_FILTER_CONTROL_SFB (1 << 17) +#define MPFS_CANFD_FILTER_CONTROL_SFC (1 << 18) +#define MPFS_CANFD_FILTER_CONTROL_SFR (1 << 19) + +/* RX_MEM_INFO registers */ +#define MPFS_CANFD_RX_MEM_INFO_RX_BUFF_SIZE_SHIFT (0) +#define MPFS_CANFD_RX_MEM_INFO_RX_BUFF_SIZE (0x1fff << MPFS_CANFD_RX_MEM_INFO_RX_BUFF_SIZE_SHIFT) +#define MPFS_CANFD_RX_MEM_INFO_RX_MEM_FREE_SHIFT (16) +#define MPFS_CANFD_RX_MEM_INFO_RX_MEM_FREE (0x1fff << MPFS_CANFD_RX_MEM_INFO_RX_MEM_FREE_SHIFT) + +/* RX_POINTERS registers */ +#define MPFS_CANFD_RX_POINTERS_RX_WPP_SHIFT (0) +#define MPFS_CANFD_RX_POINTERS_RX_WPP (0x0fff << MPFS_CANFD_RX_POINTERS_RX_WPP_SHIFT) +#define MPFS_CANFD_RX_POINTERS_RX_RPP_SHIFT (16) +#define MPFS_CANFD_RX_POINTERS_RX_RPP (0x0fff << MPFS_CANFD_RX_POINTERS_RX_RPP_SHIFT) + +/* RX_STATUS / RX_SETTINGS registers */ +#define MPFS_CANFD_RX_STATUS_RXE (1 << 0) +#define MPFS_CANFD_RX_STATUS_RXF (1 << 1) +#define MPFS_CANFD_RX_STATUS_RXMOF (1 << 2) +#define MPFS_CANFD_RX_STATUS_RXFRC_SHIFT (4) +#define MPFS_CANFD_RX_STATUS_RXFRC (0x07ff << MPFS_CANFD_RX_STATUS_RXFRC_SHIFT) +#define MPFS_CANFD_RX_STATUS_RTSOP (1 << 16) + +/* RX_DATA registers */ +#define MPFS_CANFD_RX_DATA_RX_DATA (0xffffffff << 0) + +/* TX_STATUS registers */ +#define MPFS_CANFD_TX_STATUS_TX1S_SHIFT (0) +#define MPFS_CANFD_TX_STATUS_TX1S (0x0f << MPFS_CANFD_TX_STATUS_TX1S_SHIFT) +#define MPFS_CANFD_TX_STATUS_TX2S_SHIFT (4) +#define MPFS_CANFD_TX_STATUS_TX2S (0x0f << MPFS_CANFD_TX_STATUS_TX2S_SHIFT) +#define MPFS_CANFD_TX_STATUS_TX3S_SHIFT (8) +#define MPFS_CANFD_TX_STATUS_TX3S (0x0f << MPFS_CANFD_TX_STATUS_TX3S_SHIFT) +#define MPFS_CANFD_TX_STATUS_TX4S_SHIFT (12) +#define MPFS_CANFD_TX_STATUS_TX4S (0x0f << MPFS_CANFD_TX_STATUS_TX4S_SHIFT) +#define MPFS_CANFD_TX_STATUS_TX5S_SHIFT (16) +#define MPFS_CANFD_TX_STATUS_TX5S (0x0f << MPFS_CANFD_TX_STATUS_TX5S_SHIFT) +#define MPFS_CANFD_TX_STATUS_TX6S_SHIFT (20) +#define MPFS_CANFD_TX_STATUS_TX6S (0x0f << MPFS_CANFD_TX_STATUS_TX6S_SHIFT) +#define MPFS_CANFD_TX_STATUS_TX7S_SHIFT (24) +#define MPFS_CANFD_TX_STATUS_TX7S (0x0f << MPFS_CANFD_TX_STATUS_TX7S_SHIFT) +#define MPFS_CANFD_TX_STATUS_TX8S_SHIFT (28) +#define MPFS_CANFD_TX_STATUS_TX8S (0x0f << MPFS_CANFD_TX_STATUS_TX8S_SHIFT) + +/* TX_COMMAND TXTB_INFO registers */ +#define MPFS_CANFD_TX_COMMAND_TXCE (1 << 0) +#define MPFS_CANFD_TX_COMMAND_TXCR (1 << 1) +#define MPFS_CANFD_TX_COMMAND_TXCA (1 << 2) +#define MPFS_CANFD_TX_COMMAND_TXB1 (1 << 8) +#define MPFS_CANFD_TX_COMMAND_TXB2 (1 << 9) +#define MPFS_CANFD_TX_COMMAND_TXB3 (1 << 10) +#define MPFS_CANFD_TX_COMMAND_TXB4 (1 << 11) +#define MPFS_CANFD_TX_COMMAND_TXB5 (1 << 12) +#define MPFS_CANFD_TX_COMMAND_TXB6 (1 << 13) +#define MPFS_CANFD_TX_COMMAND_TXB7 (1 << 14) +#define MPFS_CANFD_TX_COMMAND_TXB8 (1 << 15) +#define MPFS_CANFD_TX_COMMAND_TXT_BUFFER_COUNT_SHIFT (16) +#define MPFS_CANFD_TX_COMMAND_TXT_BUFFER_COUNT (0x0f << MPFS_CANFD_TX_COMMAND_TXT_BUFFER_COUNT_SHIFT) + +/* TX_PRIORITY registers */ +#define MPFS_CANFD_TX_PRIORITY_TXT1P_SHIFT (0) +#define MPFS_CANFD_TX_PRIORITY_TXT1P (0x07 << )MPFS_CANFD_TX_PRIORITY_TXT1P_SHIFT +#define MPFS_CANFD_TX_PRIORITY_TXT2P_SHIFT (4) +#define MPFS_CANFD_TX_PRIORITY_TXT2P (0x07 << MPFS_CANFD_TX_PRIORITY_TXT2P_SHIFT) +#define MPFS_CANFD_TX_PRIORITY_TXT3P_SHIFT (8) +#define MPFS_CANFD_TX_PRIORITY_TXT3P (0x07 << MPFS_CANFD_TX_PRIORITY_TXT3P_SHIFT) +#define MPFS_CANFD_TX_PRIORITY_TXT4P_SHIFT (12) +#define MPFS_CANFD_TX_PRIORITY_TXT4P (0x07 << MPFS_CANFD_TX_PRIORITY_TXT4P_SHIFT) +#define MPFS_CANFD_TX_PRIORITY_TXT5P_SHIFT (16) +#define MPFS_CANFD_TX_PRIORITY_TXT5P (0x07 << MPFS_CANFD_TX_PRIORITY_TXT5P_SHIFT) +#define MPFS_CANFD_TX_PRIORITY_TXT6P_SHIFT (20) +#define MPFS_CANFD_TX_PRIORITY_TXT6P (0x07 << MPFS_CANFD_TX_PRIORITY_TXT6P_SHIFT) +#define MPFS_CANFD_TX_PRIORITY_TXT7P_SHIFT (24) +#define MPFS_CANFD_TX_PRIORITY_TXT7P (0x07 << MPFS_CANFD_TX_PRIORITY_TXT7P_SHIFT) +#define MPFS_CANFD_TX_PRIORITY_TXT8P_SHIFT (28) +#define MPFS_CANFD_TX_PRIORITY_TXT8P (0x07 << MPFS_CANFD_TX_PRIORITY_TXT8P_SHIFT) + +/* ERR_CAPT RETR_CTR ALC registers */ +#define MPFS_CANFD_ERR_CAPT_ERR_POS_SHIFT (0) +#define MPFS_CANFD_ERR_CAPT_ERR_POS (0x1f << MPFS_CANFD_ERR_CAPT_ERR_POS_SHIFT) +#define MPFS_CANFD_ERR_CAPT_ERR_TYPE_SHIFT (5) +#define MPFS_CANFD_ERR_CAPT_ERR_TYPE (0x07 << MPFS_CANFD_ERR_CAPT_ERR_TYPE_SHIFT) +#define MPFS_CANFD_ERR_CAPT_RETR_CTR_VAL_SHIFT (8) +#define MPFS_CANFD_ERR_CAPT_RETR_CTR_VAL (0x0f << MPFS_CANFD_ERR_CAPT_RETR_CTR_VAL_SHIFT) +#define MPFS_CANFD_ERR_CAPT_ALC_BIT_SHIFT (16) +#define MPFS_CANFD_ERR_CAPT_ALC_BIT (0x1f << MPFS_CANFD_ERR_CAPT_ALC_BIT_SHIFT) +#define MPFS_CANFD_ERR_CAPT_ALC_ID_FIELD_SHIFT (21) +#define MPFS_CANFD_ERR_CAPT_ALC_ID_FIELD (0x07 << MPFS_CANFD_ERR_CAPT_ALC_ID_FIELD_SHIFT) + +/* TRV_DELAY SSP_CFG registers */ +#define MPFS_CANFD_TRV_DELAY_TRV_DELAY_VALUE_SHIFT (0) +#define MPFS_CANFD_TRV_DELAY_TRV_DELAY_VALUE (0x7f << MPFS_CANFD_TRV_DELAY_TRV_DELAY_VALUE_SHIFT) +#define MPFS_CANFD_TRV_DELAY_SSP_OFFSET_SHIFT (16) +#define MPFS_CANFD_TRV_DELAY_SSP_OFFSET (0xff << MPFS_CANFD_TRV_DELAY_SSP_OFFSET_SHIFT) +#define MPFS_CANFD_TRV_DELAY_SSP_SRC_SHIFT (24) +#define MPFS_CANFD_TRV_DELAY_SSP_SRC (0x03 << MPFS_CANFD_TRV_DELAY_SSP_SRC_SHIFT) + +/* RX_FR_CTR registers */ +#define MPFS_CANFD_RX_FR_CTR_RX_FR_CTR_VAL (0xffffffff << 0) + +/* TX_FR_CTR registers */ +#define MPFS_CANFD_TX_FR_CTR_TX_FR_CTR_VAL (0xffffffff << 0) + +/* DEBUG_REGISTER registers */ +#define MPFS_CANFD_DEBUG_REGISTER_STUFF_COUNT_SHIFT (0) +#define MPFS_CANFD_DEBUG_REGISTER_STUFF_COUNT (0x07 << MPFS_CANFD_DEBUG_REGISTER_STUFF_COUNT_SHIFT) +#define MPFS_CANFD_DEBUG_REGISTER_DESTUFF_COUNT_SHIFT (3) +#define MPFS_CANFD_DEBUG_REGISTER_DESTUFF_COUNT (0x07 << MPFS_CANFD_DEBUG_REGISTER_DESTUFF_COUNT_SHIFT) +#define MPFS_CANFD_DEBUG_REGISTER_PC_ARB (1 << 6) +#define MPFS_CANFD_DEBUG_REGISTER_PC_CON (1 << 7) +#define MPFS_CANFD_DEBUG_REGISTER_PC_DAT (1 << 8) +#define MPFS_CANFD_DEBUG_REGISTER_PC_STC (1 << 9) +#define MPFS_CANFD_DEBUG_REGISTER_PC_CRC (1 << 10) +#define MPFS_CANFD_DEBUG_REGISTER_PC_CRCD (1 << 11) +#define MPFS_CANFD_DEBUG_REGISTER_PC_ACK (1 << 12) +#define MPFS_CANFD_DEBUG_REGISTER_PC_ACKD (1 << 13) +#define MPFS_CANFD_DEBUG_REGISTER_PC_EOF (1 << 14) +#define MPFS_CANFD_DEBUG_REGISTER_PC_INT (1 << 15) +#define MPFS_CANFD_DEBUG_REGISTER_PC_SUSP (1 << 16) +#define MPFS_CANFD_DEBUG_REGISTER_PC_OVR (1 << 17) +#define MPFS_CANFD_DEBUG_REGISTER_PC_SOF (1 << 18) + +/* YOLO_REG registers */ +#define MPFS_CANFD_YOLO_REG_YOLO_VAL (0xffffffff << 0) + +/* TIMESTAMP_LOW registers */ +#define MPFS_CANFD_TIMESTAMP_LOW_TIMESTAMP_LOW (0xffffffff << 0) + +/* TIMESTAMP_HIGH registers */ +#define MPFS_CANFD_TIMESTAMP_HIGH_TIMESTAMP_HIGH (0xffffffff << 0) + +#endif /* __ARCH_RISCV_SRC_MPFS_HARDWARE_MPFS_FPGA_CANFD_H */ \ No newline at end of file diff --git a/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c b/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c new file mode 100644 index 0000000000000..fc9d0ec202be5 --- /dev/null +++ b/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c @@ -0,0 +1,2915 @@ +/**************************************************************************** + * arch/risc-v/src/mpfs/mpfs_fpga_canfd.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "hardware/mpfs_fpga_canfd.h" +#include "riscv_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef OK +# define OK 0 +#endif + +/* This module only compiles if the CAN-FD IP core instance + * is configured to the FPGA + */ + +#ifndef CONFIG_MPFS_CANFD +# error This should not be compiled as CAN-FD FPGA block is not defined +#endif + +/* This module only compiles if Nuttx socketCAN interface supports CANFD */ + +#ifndef CONFIG_NET_CAN_CANFD +# error This should not be compiled as CAN-FD driver relies on socket CAN +#endif + +/* Clock reset and enabling */ + +#define MPFS_SYSREG_SOFT_RESET_CR (MPFS_SYSREG_BASE + \ + MPFS_SYSREG_SOFT_RESET_CR_OFFSET) +#define MPFS_SYSREG_SUBBLK_CLOCK_CR (MPFS_SYSREG_BASE + \ + MPFS_SYSREG_SUBBLK_CLOCK_CR_OFFSET) + +#define CANWORK HPWORK + +#define MPFS_CANFD_ID 0xCAFD + +/* For allocating the tx and rx CAN-FD frame buffer */ + +#define POOL_SIZE 1 +#define TIMESTAMP_SIZE sizeof(struct timeval) /* To support + * timestamping frame */ + +/* For bit timing calculation */ + +#define BT_COMPUTE_MAX_ERROR 50 /* 1/10th of % */ +#define BT_COMPUTE_SYNC_SEG 1 + +#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL +/* CAN hw filter support */ + +#define HW_FILTER_A 0 +#define HW_FILTER_B 1 +#define HW_FILTER_C 2 +#define HW_FILTER_RANGE 3 + +#define CAN_STD_ID 0 +#define CAN_EXT_ID 1 +#endif /* CONFIG_NETDEV_CAN_FILTER_IOCTL */ + +/* Special address description flags for the CAN_ID */ + +#define CAN_EFF_FLAG 0x80000000 /* EFF/SFF is set in the MSB */ +#define CAN_RTR_FLAG 0x40000000 /* remote transmission request */ +#define CAN_ERR_FLAG 0x20000000 /* error message frame */ + +/* Valid bits in CAN ID for frame formats */ + +#define CAN_SFF_MASK 0x000007FF /* standard frame format (SFF) */ +#define CAN_EFF_MASK 0x1FFFFFFF /* extended frame format (EFF) */ +#define CAN_ERR_MASK 0x1FFFFFFF /* omit EFF, RTR, ERR flags */ + +/* CAN control mode */ + +#define CAN_CTRLMODE_LOOPBACK 0x01 /* Loopback mode */ +#define CAN_CTRLMODE_LISTENONLY 0x02 /* Listen-only mode */ +#define CAN_CTRLMODE_3_SAMPLES 0x04 /* Triple sampling mode */ +#define CAN_CTRLMODE_ONE_SHOT 0x08 /* One-Shot mode */ +#define CAN_CTRLMODE_BERR_REPORTING 0x10 /* Bus-error reporting */ +#define CAN_CTRLMODE_FD 0x20 /* CAN FD mode */ +#define CAN_CTRLMODE_PRESUME_ACK 0x40 /* Ignore missing CAN ACKs */ +#define CAN_CTRLMODE_FD_NON_ISO 0x80 /* CAN FD in non-ISO mode */ +#define CAN_CTRLMODE_CC_LEN8_DLC 0x100 /* Classic CAN DLC option */ +#define CAN_CTRLMODE_TDC_AUTO 0x200 /* CAN transiver automatically + * calculates TDCV */ +#define CAN_CTRLMODE_TDC_MANUAL 0x400 /* TDCV is manually set up by user */ + +/* TXT buffer */ + +enum mpfs_can_txb_status +{ + TXT_NOT_EXIST = 0x0, + TXT_RDY = 0x1, + TXT_TRAN = 0x2, + TXT_ABTP = 0x3, + TXT_TOK = 0x4, + TXT_ERR = 0x6, + TXT_ABT = 0x7, + TXT_ETY = 0x8, +}; + +enum mpfs_can_txb_command +{ + TXT_CMD_SET_EMPTY = 0x01, + TXT_CMD_SET_READY = 0x02, + TXT_CMD_SET_ABORT = 0x04 +}; + +/**************************************************************************** + * Utility definitions + ****************************************************************************/ + +#ifndef min +#define min(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef max +#define max(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#define clamp(val, lo, hi) min(max(val, lo), hi) + +#define MPFS_CAN_FD_TXNF(priv) \ + (getreg32(priv->base + MPFS_CANFD_STATUS_OFFSET) & MPFS_CANFD_STATUS_TXNF) +#define MPFS_CAN_FD_ENABLED(priv) \ + (getreg32(priv->base + MPFS_CANFD_MODE_OFFSET) & MPFS_CANFD_MODE_ENA) + +#if __GNUC__ >= 3 +# define expect(expr,value) __builtin_expect((expr),(value)) +#else +# define expect(expr,value) (expr) +#endif + +#define expect_false(expr) expect((expr) != 0, 0) +#define expect_true(expr) expect((expr) != 0, 1) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* CAN operational and error states */ + +/* CAN bit timing parameters */ + +struct mpfs_can_bittiming_s +{ + uint32_t bitrate; /* Bit-rate in bits/second */ + uint32_t sample_point; /* Sample point in one-tenth of a percent */ + uint32_t tq; /* Time quanta (TQ) in nanoseconds */ + uint32_t prop_seg; /* Propagation segment in TQs */ + uint32_t phase_seg1; /* Phase buffer segment 1 in TQs */ + uint32_t phase_seg2; /* Phase buffer segment 2 in TQs */ + uint32_t sjw; /* Synchronisation jump width in TQs */ + uint32_t brp; /* Bitrate prescaler */ +}; + +/* CAN harware dependent bit timing constants + * Used for calculating and checking bit timing parameters + */ + +struct mpfs_can_bittiming_const_s +{ + uint32_t tseg_min; + uint32_t tseg_max; + uint32_t brp_min; + uint32_t brp_max; +}; + +static const struct mpfs_can_bittiming_const_s mpfs_can_bit_timing_range = +{ + .tseg_min = 3, + .tseg_max = 253, + .brp_min = 1, + .brp_max = 8, +}; + +static const struct mpfs_can_bittiming_const_s + mpfs_can_bit_timing_data_range = +{ + .tseg_min = 3, + .tseg_max = 125, + .brp_min = 1, + .brp_max = 2, +}; + +struct mpfs_can_clock_s +{ + uint32_t freq; /* CAN system clock frequency in Hz */ +}; + +enum mpfs_can_state_e +{ + CAN_STATE_ERROR_ACTIVE = 0, /* RX/TX error count < 96 */ + CAN_STATE_ERROR_WARNING, /* RX/TX error count < 128 */ + CAN_STATE_ERROR_PASSIVE, /* RX/TX error count < 256 */ + CAN_STATE_BUS_OFF, /* RX/TX error count >= 256 */ + CAN_STATE_STOPPED, /* Device is stopped */ + CAN_STATE_SLEEPING, /* Device is sleeping */ + CAN_STATE_MAX +}; + +struct mpfs_can_ctrlmode_s +{ + uint32_t mask; + uint32_t flags; +}; + +struct mpfs_can_berr_counter_s +{ + uint16_t txerr; + uint16_t rxerr; +}; + +struct mpfs_can_device_stats_s +{ + uint32_t bus_error; /* Bus errors */ + uint32_t error_warning; /* Changes to error warning state */ + uint32_t error_passive; /* Changes to error passive state */ + uint32_t bus_off; /* Changes to bus off state */ + uint32_t arbitration_lost; /* Arbitration lost errors */ + uint32_t restarts; /* CAN controller re-starts */ +}; + +/* CAN common private data */ + +struct mpfs_can_priv_s +{ + struct mpfs_can_device_stats_s can_stats; + struct mpfs_can_bittiming_s bittiming; + struct mpfs_can_bittiming_s data_bittiming; + const struct mpfs_can_bittiming_const_s *bittiming_const; + const struct mpfs_can_bittiming_const_s *data_bittiming_const; + struct mpfs_can_clock_s clock; + + enum mpfs_can_state_e state; + uint32_t ctrlmode; +}; + +/**************************************************************************** + * CANFD Frame Format + ****************************************************************************/ + +/* CAN frame format memory map */ + +enum mpfs_canfd_can_frame_format +{ + MPFS_CANFD_FRAME_FORMAT_W_OFFSET = 0x0, + MPFS_CANFD_IDENTIFIER_W_OFFSET = 0x4, + MPFS_CANFD_TIMESTAMP_L_W_OFFSET = 0x8, + MPFS_CANFD_TIMESTAMP_U_W_OFFSET = 0xc, + MPFS_CANFD_DATA_1_4_W_OFFSET = 0x10, + MPFS_CANFD_DATA_5_8_W_OFFSET = 0x14, + MPFS_CANFD_DATA_61_64_W_OFFSET = 0x4c, +}; + +/* CANFD_Frame_format memory region */ + +/* FRAME_FORMAT_W registers */ + +#define MPFS_CANFD_FRAME_FORMAT_W_DLC_SHIFT (0) +#define MPFS_CANFD_FRAME_FORMAT_W_DLC (0x0F << \ + MPFS_CANFD_FRAME_FORMAT_W_DLC_SHIFT) +#define MPFS_CANFD_FRAME_FORMAT_W_RTR (1 << 5) +#define MPFS_CANFD_FRAME_FORMAT_W_IDE (1 << 6) +#define MPFS_CANFD_FRAME_FORMAT_W_FDF (1 << 7) +#define MPFS_CANFD_FRAME_FORMAT_W_BRS (1 << 9) +#define MPFS_CANFD_FRAME_FORMAT_W_ESI_RSV (1 << 10) +#define MPFS_CANFD_FRAME_FORMAT_W_RWCNT_SHIFT (11) +#define MPFS_CANFD_FRAME_FORMAT_W_RWCNT (0x1F << \ + MPFS_CANFD_FRAME_FORMAT_W_RWCNT_SHIFT) + +/* IDENTIFIER_W registers */ + +#define MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_EXT_SHIFT (0) +#define MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_EXT (0x03FFFF << \ + MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_EXT_SHIFT) +#define MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_BASE_SHIFT (18) +#define MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_BASE (0x07FF << \ + MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_BASE_SHIFT) + +/**************************************************************************** + * CAN controller hardware configuration + ****************************************************************************/ + +struct mpfs_config_s +{ + uint32_t canfd_fpga_irq; /* the only CAN-FD FPGA IRQ */ +}; + +static const struct mpfs_config_s mpfs_fpga_canfd_config = +{ + .canfd_fpga_irq = MPFS_IRQ_FABRIC_F2H_0, +}; + +/**************************************************************************** + * The mpfs_driver_s encapsulates all state information for a single + * hw interface + ****************************************************************************/ + +struct mpfs_driver_s +{ + struct mpfs_can_priv_s can; + + const struct mpfs_config_s *config; + + uintptr_t base; /* CANFD FPGA base address */ + bool bifup; /* true:ifup false:ifdown */ + + struct work_s rxwork; /* for deferring rx interrupt work to the wq */ + struct work_s txdwork; /* For deferring tx done interrupt work to the + * wq */ + struct work_s pollwork; /* For deferring poll work to the wq */ + + struct canfd_frame *txdesc; /* A pointer to the list of TX descriptor */ + struct canfd_frame *rxdesc; /* A pointer to the list of RX descriptors */ + + /* rx */ + + uint32_t drv_flags; /* driver flag */ + uint32_t rxfrm_first_word; /* rx frame first word (usually a FFW) */ + + /* tx */ + + unsigned int txb_sent; + unsigned int txb_processed; + uint32_t txb_prio; + unsigned int ntxbufs; + +#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL + /* hw filter */ + + uint8_t used_bit_filter_number; + bool used_range_filter; +#endif /* CONFIG_NETDEV_CAN_FILTER_IOCTL */ + + /* This holds the information visible to the NuttX network */ + + struct net_driver_s dev; /* Interface understood by the network */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct mpfs_driver_s g_canfd; + +static uint8_t g_tx_pool[(sizeof(struct canfd_frame) + TIMESTAMP_SIZE) * + POOL_SIZE]; +static uint8_t g_rx_pool[(sizeof(struct canfd_frame) + TIMESTAMP_SIZE) * + POOL_SIZE]; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* (from interrupt) RX related functions */ + +static void mpfs_can_retrieve_rx_frame(struct mpfs_driver_s *priv, + struct canfd_frame *cf, + uint32_t ffw); +static void mpfs_receive_work(void *arg); + +/* (from interrupt) TX related functions */ + +static void mpfs_can_update_txb_prio(struct mpfs_driver_s *priv); +static void mpfs_can_send_txb_cmd(struct mpfs_driver_s *priv, + enum mpfs_can_txb_command cmd, + uint8_t buf); +static void mpfs_txdone(struct mpfs_driver_s *priv); +static void mpfs_txdone_work(void *arg); + +/* (from interrupt) Error handling related functions */ + +static enum mpfs_can_state_e + mpfs_can_get_err_state(struct mpfs_driver_s *priv); +static void mpfs_can_get_err_count(struct mpfs_driver_s *priv, + struct mpfs_can_berr_counter_s *bec); +static void mpfs_err_interrupt(struct mpfs_driver_s *priv, uint32_t isr); + +/* Interrupt service routine */ + +static int mpfs_interrupt(int irq, void *context, void *arg); + +/* (Nuttx network driver interface callback when TX packet available) Tx + * related functions + */ + +static enum mpfs_can_txb_status + mpfs_can_get_txb_status(struct mpfs_driver_s *priv, + uint8_t buf); +static bool mpfs_can_is_txb_writable(struct mpfs_driver_s *priv, + uint8_t buf); +static bool mpfs_can_write_txb(struct mpfs_driver_s *priv, + const struct canfd_frame *cf, + uint8_t buf, + bool is_ccf); +static int mpfs_transmit(struct mpfs_driver_s *priv); +static int mpfs_txpoll(struct net_driver_s *dev); +static void mpfs_txavail_work(void *arg); +static int mpfs_txavail(struct net_driver_s *dev); + +/* Bit timing related functions */ + +static int + mpfs_can_btr_compute(struct mpfs_driver_s *priv, + struct mpfs_can_bittiming_s *bt, + const struct mpfs_can_bittiming_const_s *btc); + +static int mpfs_can_config_bit_timing(struct mpfs_driver_s *priv, + struct mpfs_can_bittiming_s *bt, + bool arbi); +static int mpfs_can_config_arbi_bit_timing(struct mpfs_driver_s *priv); +static int mpfs_can_config_data_bit_timing(struct mpfs_driver_s *priv); + +/* Miscellaneous CAN controller interface functions */ + +static int mpfs_can_config_ssp(struct mpfs_driver_s *priv); +static void + mpfs_can_config_controller_mode(struct mpfs_driver_s *priv, + const struct mpfs_can_ctrlmode_s *mode); + +/* HW filter related functions */ + +#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL +static void mpfs_can_add_hw_filter(struct mpfs_driver_s *priv, + uint8_t filter_type, + uint8_t can_id_type, + uint8_t can_type, + uint32_t fid1, + uint32_t fid2); +static void mpfs_can_reset_hw_filter(struct mpfs_driver_s *priv); +#endif /* CONFIG_NETDEV_CAN_FILTER_IOCTL */ + +/* CAN controller life cycle routines */ + +static int mpfs_can_controller_start(struct mpfs_driver_s *priv); +static void mpfs_can_controller_stop(struct mpfs_driver_s *priv); +static int mpfs_reset(struct mpfs_driver_s *priv); + +/* Driver interface to Nuttx network callbacks */ + +static int mpfs_ifup(struct net_driver_s *dev); +static int mpfs_ifdown(struct net_driver_s *dev); +#ifdef CONFIG_NETDEV_CAN_BITRATE_IOCTL +static int mpfs_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg); +#endif + +/**************************************************************************** + * Private Function + ****************************************************************************/ + +/**************************************************************************** + * Name: mpfs_can_retrieve_rx_frame + * + * Description: + * Retrieve CAN/CANFD frame from RX Buffer + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * cf - Pointer to CANFD frame structure + * ffw - Previously read frame format word + * + * Returned Value: + * None + * + * Assumptions: + * Frame format word is already parsed in advance and provided as 'ffw' arg + * + ****************************************************************************/ + +static void mpfs_can_retrieve_rx_frame(struct mpfs_driver_s *priv, + struct canfd_frame *cf, + uint32_t ffw) +{ + uint32_t idw; + unsigned int i; + unsigned int data_wc; /* data word count */ + unsigned int data_bc; /* data byte count */ + unsigned int dlc; + unsigned int len; + + /* CAN ID */ + + idw = getreg32(priv->base + MPFS_CANFD_RX_DATA_OFFSET); + if (MPFS_CANFD_FRAME_FORMAT_W_IDE & ffw) + { + cf->can_id = (idw & CAN_EFF_MASK) | CAN_EFF_FLAG; + } + else + { + cf->can_id = + (idw >> MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_BASE_SHIFT) & + CAN_SFF_MASK; + } + + /* BRS, ESI, RTR Flags */ + + cf->flags = 0; + if (MPFS_CANFD_FRAME_FORMAT_W_FDF & ffw) + { + /* Enable bitrate switch by default if frame is CANFD */ + + cf->flags |= CANFD_BRS; + + if (MPFS_CANFD_FRAME_FORMAT_W_ESI_RSV & ffw) + { + cf->flags |= CANFD_ESI; + } + } + else if (MPFS_CANFD_FRAME_FORMAT_W_RTR & ffw) + { + cf->can_id |= CAN_RTR_FLAG; + } + + /* RWCNT : RX Count of Words without FRAME_FORMAT WORD. Minus the 3 words + * for 1 IDW, 2 timestamp words + */ + + data_wc = ((MPFS_CANFD_FRAME_FORMAT_W_RWCNT & ffw) >> + MPFS_CANFD_FRAME_FORMAT_W_RWCNT_SHIFT) - 3; + data_bc = data_wc * 4; + + /* DLC */ + + dlc = (MPFS_CANFD_FRAME_FORMAT_W_DLC & ffw) >> + MPFS_CANFD_FRAME_FORMAT_W_DLC_SHIFT; + if (dlc <= 8) + { + len = dlc; + } + else + { + if (MPFS_CANFD_FRAME_FORMAT_W_FDF & ffw) + { + len = data_wc << 2; + } + else + { + len = 8; + } + } + cf->len = len; + if (expect_false(len > data_bc)) + { + len = data_bc; + } + + /* Timestamp - Read and throw away */ + + getreg32(priv->base + MPFS_CANFD_RX_DATA_OFFSET); + getreg32(priv->base + MPFS_CANFD_RX_DATA_OFFSET); + + /* Data */ + + for (i = 0; i < len; i += 4) + { + uint32_t data = getreg32(priv->base + MPFS_CANFD_RX_DATA_OFFSET); + + *(uint32_t *)(cf->data + i) = data; + } + + /* Read and discard exceeding data that does not fit any frame. read + * pointer is automatically increased if RX buffer is not empty. + */ + + while (expect_false(i < data_bc)) + { + getreg32(priv->base + MPFS_CANFD_RX_DATA_OFFSET); + i += 4; + } +} + +/**************************************************************************** + * Name: mpfs_receive_work + * + * Description: + * An interrupt was received indicating the availability of a new RX packet + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by interrupt handling logic. + * + ****************************************************************************/ + +static void mpfs_receive_work(void *arg) +{ + struct mpfs_driver_s *priv = (struct mpfs_driver_s *)arg; + + uint32_t status; + uint32_t frame_count; + bool is_classical_can_frame = false; + + frame_count = (getreg32(priv->base + MPFS_CANFD_RX_STATUS_OFFSET) & + MPFS_CANFD_RX_STATUS_RXFRC) >> MPFS_CANFD_RX_STATUS_RXFRC_SHIFT; + while (frame_count) + { + struct canfd_frame *cf = (struct canfd_frame *)priv->rxdesc; + uint32_t ffw; + + ffw = getreg32(priv->base + MPFS_CANFD_RX_DATA_OFFSET); + + if (!(MPFS_CANFD_FRAME_FORMAT_W_RWCNT & ffw)) + { + break; + } + + if (!(MPFS_CANFD_FRAME_FORMAT_W_FDF & ffw)) + { + if (MPFS_CANFD_FRAME_FORMAT_W_RTR & ffw) + { + caninfo("Remote Frame received\n"); + } + else + { + caninfo("Classical CAN Frame received\n"); + } + + is_classical_can_frame = true; + } + else + { + caninfo("CANFD Frame received\n"); + } + + /* Retrieve the classical or CANFD or remote frame */ + + mpfs_can_retrieve_rx_frame(priv, cf, ffw); + + /* Copy the buffer pointer to priv->dev.. Set amount of data + * in priv->dev.d_len + */ + + priv->dev.d_len = is_classical_can_frame ? + sizeof(struct can_frame) : sizeof(struct canfd_frame); + priv->dev.d_buf = (uint8_t *)cf; + + /* Send to socket interface */ + + NETDEV_RXPACKETS(&priv->dev); + can_input(&priv->dev); + + /* Point the packet buffer back to the next Tx buffer that will be + * used during the next write. If the write queue is full, then + * this will point at an active buffer, which must not be written + * to. This is OK because devif_poll won't be called unless the + * queue is not full. + */ + + priv->dev.d_buf = (uint8_t *)priv->txdesc; + + frame_count = (getreg32(priv->base + MPFS_CANFD_RX_STATUS_OFFSET) & + MPFS_CANFD_RX_STATUS_RXFRC) >> MPFS_CANFD_RX_STATUS_RXFRC_SHIFT; + } + + /* Check for RX FIFO Overflow */ + + status = getreg32(priv->base + MPFS_CANFD_STATUS_OFFSET); + if (MPFS_CANFD_STATUS_DOR & status) + { + /* Notify to socket interface */ + + NETDEV_RXERRORS(&priv->dev); + + /* Clear Data Overrun */ + + putreg32(MPFS_CANFD_COMMAND_CDO, + priv->base + MPFS_CANFD_COMMAND_OFFSET); + } + + /* Clear and re-enable RBNEI */ + + putreg32(MPFS_CANFD_INT_STAT_RBNEI, + priv->base + MPFS_CANFD_INT_STAT_OFFSET); + putreg32(MPFS_CANFD_INT_STAT_RBNEI, + priv->base + MPFS_CANFD_INT_MASK_CLR_OFFSET); +} + +/**************************************************************************** + * Name: mpfs_can_update_txb_prio + * + * Description: + * Rotates priorities of TXT buffers + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * None + * + ****************************************************************************/ + +static void mpfs_can_update_txb_prio(struct mpfs_driver_s *priv) +{ + uint32_t prio = priv->txb_prio; + + /* Rotate TX_PRIORITY register states one step left */ + + prio = (prio << 4) | ((prio >> ((priv->ntxbufs - 1) * 4)) & 0xf); + priv->txb_prio = prio; + putreg32(prio, priv->base + MPFS_CANFD_TX_PRIORITY_OFFSET); +} + +/**************************************************************************** + * Name: mpfs_can_send_txb_cmd + * + * Description: + * Execute a TXT buffer command + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * cmd - Cmd to give + * buf - The TXT buffer index (0-based) + * + * Returned Value: + * None + * + * Assumptions: + * None + * + ****************************************************************************/ + +static void mpfs_can_send_txb_cmd(struct mpfs_driver_s *priv, + enum mpfs_can_txb_command cmd, + uint8_t buf) +{ + uint32_t txb_cmd = cmd; + + txb_cmd |= 1 << (buf + 8); + putreg32(txb_cmd, priv->base + MPFS_CANFD_TX_COMMAND_OFFSET); +} + +/**************************************************************************** + * Name: mpfs_txdone + * + * Description: + * Tx done interrupt service rountine + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * None + * + ****************************************************************************/ + +static void mpfs_txdone(struct mpfs_driver_s *priv) +{ + bool first_buffer = true; + bool buffer_processed; + enum mpfs_can_txb_status txb_status; + uint8_t txb_id; + + do + { + buffer_processed = false; + while ((int)(priv->txb_sent - priv->txb_processed) > 0) + { + txb_id = priv->txb_processed % priv->ntxbufs; + txb_status = mpfs_can_get_txb_status(priv, txb_id); + bool other_status = false; + + switch (txb_status) + { + case TXT_TOK: + break; + case TXT_ERR: + canwarn("TXB in Error state\n"); + break; + case TXT_ABT: + canwarn("TXB in Aborted state\n"); + break; + default: + other_status = true; + + if (first_buffer) + { + canerr("TXB#%u not in a finished state (0x%x)!\n", + txb_id, txb_status); + + priv->txb_processed++; + + /* Rotate TXT buffer priority */ + + mpfs_can_update_txb_prio(priv); + + /* Mark current unfinished state TXT buffer as empty */ + + mpfs_can_send_txb_cmd(priv, TXT_CMD_SET_EMPTY, txb_id); + + /* Something is fishy. CLear txb status change interrupt */ + + putreg32(MPFS_CANFD_INT_STAT_TXBHCI, + priv->base + MPFS_CANFD_INT_STAT_OFFSET); + + return; + } + break; + } + + if (other_status) + { + break; + } + else + { + priv->txb_processed++; + first_buffer = false; + buffer_processed = true; + + /* Rotate TXT buffer priority */ + + mpfs_can_update_txb_prio(priv); + + /* Mark current finished state TXT buffer as empty */ + + mpfs_can_send_txb_cmd(priv, TXT_CMD_SET_EMPTY, txb_id); + } + } + + if (buffer_processed) + { + /* Since there are some buffers processed and the number of TXT + * used now matched the number of processed buffer, we can clear + * the interrupt in order to avoid any erroneous interrupt after + * the last true TXT buffer interrupt is processed. + */ + + putreg32(MPFS_CANFD_INT_STAT_TXBHCI, + priv->base + MPFS_CANFD_INT_STAT_OFFSET); + } + } + while (buffer_processed); +} + +/**************************************************************************** + * Name: mpfs_txdone_work + * + * Description: + * An interrupt was received indicating that the last TX packet(s) is done + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by the watchdog logic. + * We are not in an interrupt context so that we can lock the network. + * + ****************************************************************************/ + +static void mpfs_txdone_work(void *arg) +{ + struct mpfs_driver_s *priv = (struct mpfs_driver_s *)arg; + + /* There should be space for a new TX in any event. Poll the network for + * new XMIT data + */ + + net_lock(); + devif_poll(&priv->dev, mpfs_txpoll); + net_unlock(); +} + +/**************************************************************************** + * Name: mpfs_can_get_err_state + * + * Description: + * Reads CAN fault confinement state + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * + * Returned Value: + * Fault confinement state of controller + * + ****************************************************************************/ + +static enum mpfs_can_state_e + mpfs_can_get_err_state(struct mpfs_driver_s *priv) +{ + u_int32_t ewl_erp_fs_reg, rec_tec_reg, ew_limit, rec_val, tec_val; + + ewl_erp_fs_reg = getreg32(priv->base + MPFS_CANFD_EWL_OFFSET); + rec_tec_reg = getreg32(priv->base + MPFS_CANFD_REC_OFFSET); + + ew_limit = ((ewl_erp_fs_reg & MPFS_CANFD_EWL_EW_LIMIT) >> + MPFS_CANFD_EWL_EW_LIMIT_SHIFT); + rec_val = ((rec_tec_reg & MPFS_CANFD_REC_REC_VAL) >> + MPFS_CANFD_REC_REC_VAL_SHIFT); + tec_val = ((rec_tec_reg & MPFS_CANFD_REC_TEC_VAL) >> + MPFS_CANFD_REC_TEC_VAL_SHIFT); + + if (ewl_erp_fs_reg & MPFS_CANFD_EWL_ERA) + { + if (rec_val < ew_limit && tec_val < ew_limit) + { + return CAN_STATE_ERROR_ACTIVE; + } + else + { + return CAN_STATE_ERROR_WARNING; + } + } + else if (ewl_erp_fs_reg & MPFS_CANFD_EWL_ERP) + { + return CAN_STATE_ERROR_PASSIVE; + } + else if (ewl_erp_fs_reg & MPFS_CANFD_EWL_BOF) + { + return CAN_STATE_BUS_OFF; + } + + canwarn("Invalid FPGA CAN-FD error state\n"); + return CAN_STATE_ERROR_PASSIVE; +} + +/**************************************************************************** + * Name: mpfs_can_get_err_count + * + * Description: + * Reads CAN RX/TX error counter + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * bec - Pointer to Error counter structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void mpfs_can_get_err_count(struct mpfs_driver_s *priv, + struct mpfs_can_berr_counter_s *bec) +{ + uint32_t rec_tec_reg = getreg32(priv->base + MPFS_CANFD_REC_OFFSET); + + bec->rxerr = ((rec_tec_reg & MPFS_CANFD_REC_REC_VAL) >> + MPFS_CANFD_REC_REC_VAL_SHIFT); + bec->txerr = ((rec_tec_reg & MPFS_CANFD_REC_TEC_VAL) >> + MPFS_CANFD_REC_TEC_VAL_SHIFT); +} + +/**************************************************************************** + * Name: mpfs_err_interrupt + * + * Description: + * Error frame ISR + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * isr - Interrupt status register value + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void mpfs_err_interrupt(struct mpfs_driver_s *priv, uint32_t isr) +{ + enum mpfs_can_state_e state; + struct mpfs_can_berr_counter_s bec; + uint32_t err_capt_retr_ctr_alc_reg; + uint32_t err_type; + uint32_t err_pos; + uint32_t alc_id_field; + uint32_t alc_bit; + + mpfs_can_get_err_count(priv, &bec); + state = mpfs_can_get_err_state(priv); + err_capt_retr_ctr_alc_reg = + getreg32(priv->base + MPFS_CANFD_ERR_CAPT_OFFSET); + + err_type = ((err_capt_retr_ctr_alc_reg & MPFS_CANFD_ERR_CAPT_ERR_TYPE) >> + MPFS_CANFD_ERR_CAPT_ERR_TYPE_SHIFT); + err_pos = ((err_capt_retr_ctr_alc_reg & MPFS_CANFD_ERR_CAPT_ERR_POS) >> + MPFS_CANFD_ERR_CAPT_ERR_POS_SHIFT); + alc_id_field = + ((err_capt_retr_ctr_alc_reg & MPFS_CANFD_ERR_CAPT_ALC_ID_FIELD) >> + MPFS_CANFD_ERR_CAPT_ALC_ID_FIELD_SHIFT); + alc_bit = ((err_capt_retr_ctr_alc_reg & MPFS_CANFD_ERR_CAPT_ALC_BIT) >> + MPFS_CANFD_ERR_CAPT_ALC_BIT_SHIFT); + + caninfo("ISR = 0x%08x, rxerr %d, txerr %d, error type %u, pos %u, ALC " + "id_field %u, bit %u\n", isr, bec.rxerr, bec.txerr, err_type, + err_pos, alc_id_field, alc_bit); + + /* Check for error warning limit and fault confinement state change */ + + if (MPFS_CANFD_INT_STAT_FCSI & isr || MPFS_CANFD_INT_STAT_EWLI & isr) + { + if (priv->can.state == state) + { + canwarn("No state change! Missed interrupt?\n"); + } + + priv->can.state = state; + + switch (state) + { + case CAN_STATE_BUS_OFF: + canwarn("Change to BUS_OFF error state\n"); + break; + case CAN_STATE_ERROR_PASSIVE: + priv->can.can_stats.error_passive++; + canwarn("Change to ERROR_PASSIVE error state\n"); + break; + case CAN_STATE_ERROR_WARNING: + priv->can.can_stats.error_warning++; + canwarn("Change to ERROR_WARNING error state\n"); + break; + case CAN_STATE_ERROR_ACTIVE: + caninfo("Change to ERROR_ACTIVE error state\n"); + return; + default: + canwarn("Unhandled error state %d\n", state); + break; + } + } + + if (MPFS_CANFD_INT_STAT_ALI & isr) + { + canerr("Arbitration lost\n"); + priv->can.can_stats.arbitration_lost++; + } + + if (MPFS_CANFD_INT_STAT_BEI & isr) + { + canerr("Bus error\n"); + priv->can.can_stats.bus_error++; + } + + /* Notify to socket interface. */ + + NETDEV_ERRORS(&priv->dev); +} + +/**************************************************************************** + * Name: mpfs_interrupt + * + * Description: + * Three interrupt sources will vector to this function: + * 1. CAN frame transmit interrupt + * 2. CAN frame receive interrupt + * 3. Error interrupt + * + * Input Parameters: + * irq - Number of the IRQ that generated the interrupt + * context - Interrupt register state save info (architecture-specific) + * + * Returned Value: + * OK on success + * + ****************************************************************************/ + +static int mpfs_interrupt(int irq, void *context, void *arg) +{ + struct mpfs_driver_s *priv = (struct mpfs_driver_s *)arg; + + uint32_t isr; + uint32_t icr; + uint32_t imask; + int irq_loops; + + for (irq_loops = 0; irq_loops < 10000; irq_loops++) + { + /* Get the interrupt status */ + + isr = getreg32(priv->base + MPFS_CANFD_INT_STAT_OFFSET); + + /* Check and exit interrupt service routine if there is no int flag in + * INT_STAT reg. + */ + + if (!isr) + { + return irq_loops ? OK : -1; + } + + /* Receive Buffer Not Empty Interrupt */ + + if (isr & MPFS_CANFD_INT_STAT_RBNEI) + { + /* Mask RBNEI first, then clear interrupt. Even if + * another IRQ fires, RBNEI will always be 0 (masked). + */ + + icr = MPFS_CANFD_INT_STAT_RBNEI; + putreg32(icr, priv->base + MPFS_CANFD_INT_MASK_SET_OFFSET); + putreg32(icr, priv->base + MPFS_CANFD_INT_STAT_OFFSET); + + /* Schedule work to process RX frame from CAN controller */ + + work_queue(CANWORK, &priv->rxwork, mpfs_receive_work, priv, 0); + } + + /* TXT Buffer HW Command Interrupt */ + + if (isr & MPFS_CANFD_INT_STAT_TXBHCI) + { + /* Clear TX interrupt flags */ + + mpfs_txdone(priv); + + /* Schedule work to poll for next available tx frame from the + * network. + */ + + work_queue(CANWORK, &priv->txdwork, mpfs_txdone_work, priv, 0); + } + + /* Error Interrupts */ + + if (isr & MPFS_CANFD_INT_STAT_EWLI || + isr & MPFS_CANFD_INT_STAT_FCSI || + isr & MPFS_CANFD_INT_STAT_ALI || + isr & MPFS_CANFD_INT_STAT_BEI) + { + icr = isr & (MPFS_CANFD_INT_STAT_EWLI | + MPFS_CANFD_INT_STAT_FCSI | + MPFS_CANFD_INT_STAT_ALI | + MPFS_CANFD_INT_STAT_BEI); + canerr("Some error interrupts. Clearing 0x%08x\n", icr); + putreg32(icr, priv->base + MPFS_CANFD_INT_STAT_OFFSET); + mpfs_err_interrupt(priv, isr); + } + } + + /* Now, it seems that there are still some interrupt flags that remain + * stuck in INT_STAT reg. + */ + + canerr("Stuck interrupt (isr=%08x)\n", isr); + + /* Check if any of the stuck one belongs to txb status. */ + + if (isr & MPFS_CANFD_INT_STAT_TXBHCI) + { +#if CONFIG_DEBUG_CAN_INFO + caninfo("txb_sent=0x%08x txb_processed=0x%08x\n", priv->txb_sent, + priv->txb_processed); + for (int i = 0; i < priv->ntxbufs; i++) + { + uint32_t status = mpfs_can_get_txb_status(priv, i); + caninfo("txb[%d] txb status=0x%08x\n", i, status); + } +#endif + /* Notify to socket interface */ + + NETDEV_TXERRORS(&priv->dev); + + /* Clear txb status change interrupt */ + + putreg32(MPFS_CANFD_INT_STAT_TXBHCI, + priv->base + MPFS_CANFD_INT_STAT_OFFSET); + } + + /* Check if any of the stuck one belongs to RX buffer data overrun */ + + if (isr & MPFS_CANFD_INT_STAT_DOI) + { + /* Notify to socket interface */ + + NETDEV_RXERRORS(&priv->dev); + + /* Clear Data Overrun interrupt */ + + putreg32(MPFS_CANFD_INT_STAT_DOI, + priv->base + MPFS_CANFD_INT_STAT_OFFSET); + } + + /* Clear and reset all interrupt. */ + + canwarn("Reset all interrupts...\n"); + imask = 0xffffffff; + putreg32(imask, priv->base + MPFS_CANFD_INT_ENA_CLR_OFFSET); + putreg32(imask, priv->base + MPFS_CANFD_INT_ENA_SET_OFFSET); + return OK; +} + +/**************************************************************************** + * Name: mpfs_can_get_tx_state + * + * Description: + * Get status of txt buffer + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * buf - txt buffer index to get status of (0-based) + * + * Returned Value: + * Status of txt buffer + * + * Assumptions: + * None + * + ****************************************************************************/ + +static enum mpfs_can_txb_status + mpfs_can_get_txb_status(struct mpfs_driver_s *priv, uint8_t buf) +{ + uint32_t tx_status = getreg32(priv->base + MPFS_CANFD_TX_STATUS_OFFSET); + enum mpfs_can_txb_status status = (tx_status >> (buf * 4)) & 0xf; + + return status; +} + +/**************************************************************************** + * Name: mpfs_can_is_txb_writable + * + * Description: + * Precheck txb state if a new frame can be written + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * buf - txt buffer index to get status of (0-based) + * + * Returned Value: + * True - Frame can be inserted to txt buffer + * False - If attempted, frame will not be inserted to txt buffer + * + * Assumptions: + * None + * + ****************************************************************************/ + +static bool mpfs_can_is_txb_writable(struct mpfs_driver_s *priv, + uint8_t buf) +{ + enum mpfs_can_txb_status buf_status; + + buf_status = mpfs_can_get_txb_status(priv, buf); + if (buf_status == TXT_RDY || buf_status == TXT_TRAN || + buf_status == TXT_ABTP) + { + canwarn("TXT buffer status %d\n", buf_status); + return false; + } + + return true; +} + +/**************************************************************************** + * Name: mpfs_can_write_txb + * + * Description: + * Load CAN frame onto txt buffer on the CAN controller + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * cf - Pointer to the CANFD frame to be inserted + * buf - txt buffer index to which the cf frame is inserted (0-based) + * is_ccf- is classical can frame (bool) + * + * Returned Value: + * True - TXT buffer written successfully + * False - Frame was not written to TXT buffer due to: + * 1. TXT buffer is not writable + * 2. Invalid TXT buffer index + * 3. Invalid frame length + * + * Assumptions: + * None + * + ****************************************************************************/ + +static bool mpfs_can_write_txb(struct mpfs_driver_s *priv, + const struct canfd_frame *cf, + uint8_t buf, + bool is_ccf) +{ + uint32_t buf_base; + uint32_t ffw = 0; + uint32_t idw = 0; + unsigned int i; + + /* Check for invalid txt buffer index */ + + if (buf >= priv->ntxbufs) + { + canerr("Invalid txt buffer index...\n"); + return false; + } + + /* Check if it is possible to insert frame to txt buffer */ + + if (!mpfs_can_is_txb_writable(priv, buf)) + { + canwarn("Not possible to insert frame to txt buffer...\n"); + return false; + } + + /* Check for invalid classical CAN / CANFD frame length */ + + if (cf->len > CANFD_MAX_DLEN || (cf->len > CAN_MAX_DLEN && is_ccf)) + { + canerr("Invalid classical / CANFD CAN frame length...\n"); + return false; + } + + /* Populate frame format word */ + + if (cf->can_id & CAN_RTR_FLAG) /* remote transmission request */ + { + ffw |= MPFS_CANFD_FRAME_FORMAT_W_RTR; + } + + if (cf->can_id & CAN_EFF_FLAG) /* extended frame format (29 bit long id) */ + { + ffw |= MPFS_CANFD_FRAME_FORMAT_W_IDE; + } + + if (!is_ccf) + { + ffw |= MPFS_CANFD_FRAME_FORMAT_W_FDF; /* FD Frame */ + if (cf->flags & CANFD_BRS) + { + ffw |= MPFS_CANFD_FRAME_FORMAT_W_BRS; /* Bit rate switch */ + } + } + + ffw |= MPFS_CANFD_FRAME_FORMAT_W_DLC & (len_to_can_dlc[cf->len] << + MPFS_CANFD_FRAME_FORMAT_W_DLC_SHIFT); + + /* Populate CAN frame id word */ + + if (cf->can_id & CAN_EFF_FLAG) + { + idw = cf->can_id & CAN_EFF_MASK; + } + else + { + idw = MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_BASE & + ((cf->can_id & CAN_SFF_MASK) << + MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_BASE_SHIFT); + } + + /* Write frame id and frame format word */ + + buf_base = (buf + 1) * 0x100; + putreg32(ffw, priv->base + buf_base + MPFS_CANFD_FRAME_FORMAT_W_OFFSET); + putreg32(idw, priv->base + buf_base + MPFS_CANFD_IDENTIFIER_W_OFFSET); + + /* Write CAN data payload */ + + if (!(cf->can_id & CAN_RTR_FLAG)) + { + for (i = 0; i < cf->len; i += 4) + { + uint32_t data = *(uint32_t *)(cf->data + i); + putreg32(data, + priv->base + buf_base + MPFS_CANFD_DATA_1_4_W_OFFSET + i); + } + } + + return true; +} + +/**************************************************************************** + * Name: mpfs_transmit + * + * Description: + * Start hardware transmission. Called either from the txdone interrupt + * handling or from watchdog based polling. + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + * Assumptions: + * May or may not be called from an interrupt handler. In either case, + * global interrupts are disabled, either explicitly or indirectly through + * interrupt handling logic. + * + ****************************************************************************/ + +static int mpfs_transmit(struct mpfs_driver_s *priv) +{ + uint32_t txb_id; + bool ok; + bool is_classical_can_frame; + + /* Retrieve the classical CAN / CANFD frame from network device buffer */ + + is_classical_can_frame = + priv->dev.d_len <= sizeof(struct can_frame) ? true : false; + struct canfd_frame *cf = (struct canfd_frame *)priv->dev.d_buf; + + /* Get the current txt buffer ID */ + + txb_id = priv->txb_sent % priv->ntxbufs; + + /* Insert classical CAN/CANFD frame into controller txt bf at txb_id */ + + ok = mpfs_can_write_txb(priv, cf, txb_id, is_classical_can_frame); + if (!ok) + { + canwarn("TXNF set but cannot insert frame into TXT buffer!\n"); + NETDEV_TXERRORS(&priv->dev); + return OK; + } + + /* Now, write to txt buffer seems ok, use txt command to set buffer state + * to READY for xmit. + */ + + mpfs_can_send_txb_cmd(priv, TXT_CMD_SET_READY, txb_id); + priv->txb_sent++; + + /* Increment statistics */ + + NETDEV_TXPACKETS(&priv->dev); + + return OK; +} + +/**************************************************************************** + * Name: mpfs_txpoll + * + * Description: + * The transmitter is available, check if the network has any outgoing + * packets ready to send. This is a callback from devif_poll(). + * devif_poll() may be called: + * + * 1. When the preceding TX packet send is complete, + * 2. During normal TX polling + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + * Assumptions: + * May or may not be called from an interrupt handler. In either case, + * global interrupts are disabled, either explicitly or indirectly through + * interrupt handling logic. + * + ****************************************************************************/ + +static int mpfs_txpoll(struct net_driver_s *dev) +{ + struct mpfs_driver_s *priv = + (struct mpfs_driver_s *)dev->d_private; + + /* If the polling resulted in data that should be sent out on the network, + * the field d_len is set to a value > 0. + */ + + if (priv->dev.d_len > 0) + { + if (!devif_loopback(&priv->dev)) + { + /* Send the packet */ + + mpfs_transmit(priv); + + /* Check if there is room in the device to hold another packet. If + * not, return a non-zero value to terminate the poll. + */ + + if (!MPFS_CAN_FD_TXNF(priv)) + { + return -EBUSY; + } + } + } + + /* If zero is returned, the polling will continue until all connections + * have been examined. + */ + + return OK; +} + +/**************************************************************************** + * Name: mpfs_txavail_work + * + * Description: + * Perform an out-of-cycle poll on the worker thread. + * + * Input Parameters: + * arg - Reference to the NuttX driver state structure (cast to void*) + * + * Returned Value: + * None + * + * Assumptions: + * Called on the higher priority worker thread. + * + ****************************************************************************/ + +static void mpfs_txavail_work(void *arg) +{ + struct mpfs_driver_s *priv = (struct mpfs_driver_s *)arg; + + /* Ignore the notification if the interface is not yet up */ + + if (priv->bifup) + { + /* Check if there is room in the controller to hold another outgoing + * packet. + */ + + if (MPFS_CAN_FD_TXNF(priv)) + { + /* Yes, there is, poll the network for new TXT transmit */ + + net_lock(); + devif_poll(&priv->dev, mpfs_txpoll); + net_unlock(); + } + } +} + +/**************************************************************************** + * Name: mpfs_txavail + * + * Description: + * Driver callback invoked when new TX data is available. This is a + * stimulus perform an out-of-cycle poll and, thereby, reduce the TX + * latency. + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * 0 - OK + * + * Assumptions: + * Called in normal user mode + * + ****************************************************************************/ + +static int mpfs_txavail(struct net_driver_s *dev) +{ + struct mpfs_driver_s *priv = + (struct mpfs_driver_s *)dev->d_private; + + if (work_available(&priv->pollwork)) + { + /* Schedule to serialize the poll on the worker thread. */ + + mpfs_txavail_work(priv); + } + + return OK; +} + +/**************************************************************************** + * Name: mpfs_can_btr_compute + * + * Description: + * Calculate bit timing values to be written to bit timing register + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * bt - Pointer to the bit timing structure to be set + * btc - Pointer to the constant bit timing structure to be used to set + * the bit timing params + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + * Assumptions: + * Bit timing constants needed to be set in advance on which calculation + * in this function is based + * + ****************************************************************************/ + +static int + mpfs_can_btr_compute(struct mpfs_driver_s *priv, + struct mpfs_can_bittiming_s *bt, + const struct mpfs_can_bittiming_const_s *btc) +{ + /* All measured in number of time quanta (Tq = brp / fsys) + * brp : baud rate prescaler as number of system clock periods + * prop_seg : propagation segment (1..8 Tq) + * phase_seg1 : phase segment 1 (1..8 Tq) + * phase_seg2 : phase segment 2 (1..8 Tq) + * + * tseg1 = prop_seg + phase_seg1 + * tseg2 = phase_seg2 + * tseg = tseg1 + tseg2 + * tsegall = BT_COMPUTE_SYNC_SEG + tseg / 2 + * + * sample point = (BT_COMPUTE_SYNC_SEG + tseg1) / + * (BT_COMPUTE_SYNC_SEG + tseg1 + tseg2) * 1000 + * + * CAN bitrate = 1 / (number_of_Tq * Tq) + */ + + unsigned int calc_br; /* current calculated bitrate */ + unsigned int br_err = 0; /* diff between user set bitrate + * and calculated bitrate */ + unsigned int best_br_err = UINT_MAX; /* best bitrate error */ + + unsigned int nominal_sp; /* nominal sample point either set + * by user or inferred from bitrate + * (CiA recommendation) */ + unsigned int calc_sp; /* calculated sample point */ + unsigned int sp_err; /* diff between and nominal sample + * point and currently calculated + * sample point */ + unsigned int best_sp_err = UINT_MAX; /* best sample point error */ + + unsigned int calc_brp; /* currently calculated bitrate + * prescaler */ + unsigned int best_brp = 0; /* currently calculated bitrate + * prescaler */ + unsigned int tseg_double; + unsigned int tseg_sync; + unsigned int tseg1 = 0; + unsigned int tseg2 = 0; + + /* Get sample point nominal */ + + if (bt->sample_point) + { + nominal_sp = bt->sample_point; + } + else + { + if (bt->bitrate <= 500000) + { + nominal_sp = 875; + } + else if (bt->bitrate <= 800000) + { + nominal_sp = 800; + } + else + { + nominal_sp = 750; + } + } + calc_sp = nominal_sp; + + /* Iterate tseg in possible range to find best bit timing values */ + + for (tseg_double = btc->tseg_max * 2 + 1; + tseg_double >= btc->tseg_min * 2; tseg_double--) + { + tseg_sync = tseg_double / 2 + BT_COMPUTE_SYNC_SEG; + + /* Recalculate bitrate prescaler */ + + calc_brp = priv->can.clock.freq / (tseg_sync * bt->bitrate) + + tseg_double % 2; + + if (calc_brp < btc->brp_min || calc_brp > btc->brp_max) + { + continue; + } + + /* Recalculate bitrate and bitrate error */ + + calc_br = priv->can.clock.freq / (calc_brp * tseg_sync); + + br_err = bt->bitrate - calc_br; + if (br_err > best_br_err) + { + continue; + } + else + { + best_sp_err = UINT_MAX; + } + + /* Now, it seems that we have a better bitrate, recalculate sample + * point, tseg1, tseg2 and sample point error + */ + + tseg2 = clamp(tseg_sync - nominal_sp * tseg_sync / 1000, 1, + btc->tseg_max * 249 / 1000); + tseg1 = tseg_double / 2 - tseg2; + calc_sp = 1000 * (tseg_sync - tseg2) / tseg_sync; + + sp_err = nominal_sp - calc_sp; + if (calc_sp > nominal_sp || sp_err > best_sp_err) + { + continue; + } + + /* Update best values and end condition check */ + + best_brp = calc_brp; + best_br_err = br_err; + best_sp_err = sp_err; + + if (best_br_err == 0 && best_sp_err == 0) + { + break; + } + } + + /* Check bitrate error against limit */ + + if ((uint32_t)best_br_err * 1000 > BT_COMPUTE_MAX_ERROR * bt->bitrate) + { + canerr("Bitrate error %d.%d%% is too high\n", br_err / 10, + br_err % 10); + return -EDOM; + } + + /* Retrieve the best calculated sample point */ + + bt->sample_point = calc_sp; + + /* Retrieve bit timing register components */ + + bt->brp = best_brp; + bt->prop_seg = tseg1 / 2; + bt->phase_seg1 = tseg1 - bt->prop_seg; + bt->phase_seg2 = tseg2; + + return OK; +} + +/**************************************************************************** + * Name: mpfs_can_config_bit_timing + * + * Description: + * Set CAN controller arbitration or data bitrate bit timing + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * bt - Pointer to Bit timing structure + * arbi - True - Arbitration bit timing, False - Data bit timing + * + * Returned Value: + * Zero (OK) on success, -EPERM if CAN controller is not disabled + * + * Assumptions: + * None + * + ****************************************************************************/ + +static int mpfs_can_config_bit_timing(struct mpfs_driver_s *priv, + struct mpfs_can_bittiming_s *bt, + bool arbi) +{ + int max_ph1_len = 31; + uint32_t btr = 0; + + if (MPFS_CAN_FD_ENABLED(priv)) + { + canerr("CAN controller should be disabled to set bit timing\n"); + return -EPERM; + } + + if (arbi) + { + max_ph1_len = 63; + } + + if (bt->phase_seg1 > max_ph1_len) + { + bt->prop_seg += bt->phase_seg1 - max_ph1_len; + bt->phase_seg1 = max_ph1_len; + } + + if (arbi) + { + btr = bt->prop_seg << MPFS_CANFD_BTR_PROP_SHIFT; + btr |= bt->phase_seg1 << MPFS_CANFD_BTR_PH1_SHIFT; + btr |= bt->phase_seg2 << MPFS_CANFD_BTR_PH2_SHIFT; + btr |= bt->brp << MPFS_CANFD_BTR_BRP_SHIFT; + btr |= bt->sjw << MPFS_CANFD_BTR_SJW_SHIFT; + caninfo("Arbitration bitrate: %u, Prop_seg: %u, phase_seg1: %u, " + "phase_seg2: %u, brp: %u, sjw: %u \n", bt->bitrate, + bt->prop_seg, bt->phase_seg1, bt->phase_seg2, bt->brp, + bt->sjw); + putreg32(btr, priv->base + MPFS_CANFD_BTR_OFFSET); + } + else + { + btr = bt->prop_seg << MPFS_CANFD_BTR_FD_PROP_FD_SHIFT; + btr |= bt->phase_seg1 << MPFS_CANFD_BTR_FD_PH1_FD_SHIFT; + btr |= bt->phase_seg2 << MPFS_CANFD_BTR_FD_PH2_FD_SHIFT; + btr |= bt->brp << MPFS_CANFD_BTR_FD_BRP_FD_SHIFT; + btr |= bt->sjw << MPFS_CANFD_BTR_FD_SJW_FD_SHIFT; + caninfo("Data bitrate: %u, Prop_seg: %u, phase_seg1: %u, " + "phase_seg2: %u, brp: %u, sjw: %u \n", bt->bitrate, + bt->prop_seg, bt->phase_seg1, bt->phase_seg2, bt->brp, + bt->sjw); + putreg32(btr, priv->base + MPFS_CANFD_BTR_FD_OFFSET); + } + + return OK; +} + +/**************************************************************************** + * Name: mpfs_can_config_arbi_bit_timing + * + * Description: + * Set CAN controller arbitration bit timing + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * + * Returned Value: + * Zero (OK) on success, -%EPERM if controller is enabled + * + * Assumptions: + * None + * + ****************************************************************************/ + +static int mpfs_can_config_arbi_bit_timing(struct mpfs_driver_s *priv) +{ + struct mpfs_can_bittiming_s *arbi_bt = &priv->can.bittiming; + + /* Set bit timing for arbitration bit rate */ + + return mpfs_can_config_bit_timing(priv, arbi_bt, true); +} + +/**************************************************************************** + * Name: mpfs_can_config_data_bit_timing + * + * Description: + * Set CAN controller data bit timing + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * + * Returned Value: + * Zero (OK) on success, -%EPERM if controller is enabled + * + * Assumptions: + * None + * + ****************************************************************************/ + +static int mpfs_can_config_data_bit_timing(struct mpfs_driver_s *priv) +{ + struct mpfs_can_bittiming_s *data_bt = &priv->can.data_bittiming; + + /* Set bit timing for data bit rate */ + + return mpfs_can_config_bit_timing(priv, data_bt, false); +} + +/**************************************************************************** + * Name: mpfs_can_config_ssp + * + * Description: + * Set CAN controller secondary sample point. + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * + * Returned Value: + * Zero (OK) on success, -EPERM if CAN controller is not disabled + * + * Assumptions: + * None + * + ****************************************************************************/ + +static int mpfs_can_config_ssp(struct mpfs_driver_s *priv) +{ + struct mpfs_can_bittiming_s *dbt = &(priv->can.data_bittiming); + int ssp_offset = 0; + uint32_t ssp_cfg = 0; + + if (MPFS_CAN_FD_ENABLED(priv)) + { + canerr("CAN controller should be disabled to set secondary sample " + "point\n"); + return -EPERM; + } + + /* secondary sample point is only used for bitrates > 1 Mbits/s */ + + if (dbt->bitrate > 1000000) + { + ssp_offset = (priv->can.clock.freq / 1000) * + dbt->sample_point / dbt->bitrate; + + if (ssp_offset > 127) + { + canwarn("Secondary sample point offset exceeds 127\n"); + ssp_offset = 127; + } + + ssp_cfg = ssp_offset << MPFS_CANFD_TRV_DELAY_SSP_OFFSET_SHIFT; + ssp_cfg |= 0x1 << MPFS_CANFD_TRV_DELAY_SSP_SRC_SHIFT; + } + + putreg32(ssp_cfg, priv->base + MPFS_CANFD_TRV_DELAY_OFFSET); + + return OK; +} + +/**************************************************************************** + * Name: mpfs_can_config_controller_mode + * + * Description: + * Configure CAN controller mode + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * mode - Pointer to controller modes to be set + * + * Returned Value: + * None + * + * Assumptions: + * None + * + ****************************************************************************/ + +static void + mpfs_can_config_controller_mode(struct mpfs_driver_s *priv, + const struct mpfs_can_ctrlmode_s *mode) +{ + uint32_t mode_reg = getreg32(priv->base + MPFS_CANFD_MODE_OFFSET); + + mode_reg = (mode->flags & CAN_CTRLMODE_LOOPBACK) ? + (mode_reg | MPFS_CANFD_MODE_ILBP) : + (mode_reg & ~MPFS_CANFD_MODE_ILBP); + + mode_reg = (mode->flags & CAN_CTRLMODE_LISTENONLY) ? + (mode_reg | MPFS_CANFD_MODE_BMM) : + (mode_reg & ~MPFS_CANFD_MODE_BMM); + + mode_reg = (mode->flags & CAN_CTRLMODE_FD) ? + (mode_reg | MPFS_CANFD_MODE_FDE) : + (mode_reg & ~MPFS_CANFD_MODE_FDE); + + mode_reg = (mode->flags & CAN_CTRLMODE_PRESUME_ACK) ? + (mode_reg | MPFS_CANFD_MODE_ACF) : + (mode_reg & ~MPFS_CANFD_MODE_ACF); + + mode_reg = (mode->flags & CAN_CTRLMODE_FD_NON_ISO) ? + (mode_reg | MPFS_CANFD_MODE_NISOFD) : + (mode_reg & ~MPFS_CANFD_MODE_NISOFD); + + mode_reg &= ~MPFS_CANFD_MODE_RTRTH; + mode_reg = (mode->flags & CAN_CTRLMODE_ONE_SHOT) ? + (mode_reg | MPFS_CANFD_MODE_RTRLE) : + (mode_reg & ~MPFS_CANFD_MODE_RTRLE); + +#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL + mode_reg |= MPFS_CANFD_MODE_AFM; +#endif + + /* Disable test mode */ + + mode_reg &= ~MPFS_CANFD_MODE_TSTM; + + putreg32(mode_reg, priv->base + MPFS_CANFD_MODE_OFFSET); +} + +/**************************************************************************** + * Name: mpfs_can_add_hw_filter + * + * Description: + * Add new hw filter to CAN Controller + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * filter_type - Filter A, B, C or Range + * can_id_type - std CAN ID / ext CAN ID + * can_type - classical CAN / CANFD + * filter_id1 - filter id 1 (can be filter value for bit filter or range + * low for range filter) + * filter_id2 - filter id 2 (can be filter mask for bit filter or range + * high for range filter) + * + * Returned Value: + * None + * + * Assumptions: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL +static void mpfs_can_add_hw_filter(struct mpfs_driver_s *priv, + uint8_t filter_type, + uint8_t can_id_type, + uint8_t can_type, + uint32_t fid1, + uint32_t fid2) +{ + uint32_t fc_reg; + + fc_reg = getreg32(priv->base + MPFS_CANFD_FILTER_CONTROL_OFFSET); + + switch (filter_type) + { + case HW_FILTER_A: + + /* Set filter control reg for filter A */ + + if (can_type == CAN_MSGPRIO_LOW) + { + /* Classical CAN frame filter */ + + fc_reg = (can_id_type == CAN_EXT_ID) ? + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FANE) : + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FANB); + + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FAFE; + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FAFB; + } + else if (can_type == CAN_MSGPRIO_HIGH) + { + /* CANFD frame filter */ + + fc_reg = (can_id_type == CAN_EXT_ID) ? + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FAFE) : + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FAFB); + + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FANE; + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FANB; + } + putreg32(fc_reg, priv->base + MPFS_CANFD_FILTER_CONTROL_OFFSET); + + /* Set bit filter value / mask */ + + putreg32(fid1, priv->base + MPFS_CANFD_FILTER_A_VAL_OFFSET); + putreg32(fid2, priv->base + MPFS_CANFD_FILTER_A_MASK_OFFSET); + break; + + case HW_FILTER_B: + + /* Set filter control reg for filter B */ + + if (can_type == CAN_MSGPRIO_LOW) + { + /* Classical CAN frame filter */ + + fc_reg = (can_id_type == CAN_EXT_ID) ? + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FBNE) : + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FBNB); + + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FBFE; + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FBFB; + } + else if (can_type == CAN_MSGPRIO_HIGH) + { + /* CANFD frame filter */ + + fc_reg = (can_id_type == CAN_EXT_ID) ? + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FBFE) : + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FBFB); + + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FBNE; + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FBNB; + } + putreg32(fc_reg, priv->base + MPFS_CANFD_FILTER_CONTROL_OFFSET); + + /* Set bit filter value / mask */ + + putreg32(fid1, priv->base + MPFS_CANFD_FILTER_B_VAL_OFFSET); + putreg32(fid2, priv->base + MPFS_CANFD_FILTER_B_MASK_OFFSET); + break; + + case HW_FILTER_C: + + /* Set filter control reg for filter C */ + + if (can_type == CAN_MSGPRIO_LOW) + { + /* Classical CAN frame filter */ + + fc_reg = (can_id_type == CAN_EXT_ID) ? + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FCNE) : + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FCNB); + + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FCFE; + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FCFB; + } + else if (can_type == CAN_MSGPRIO_HIGH) + { + /* CANFD frame filter */ + + fc_reg = (can_id_type == CAN_EXT_ID) ? + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FCFE) : + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FCFB); + + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FCNE; + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FCNB; + } + putreg32(fc_reg, priv->base + MPFS_CANFD_FILTER_CONTROL_OFFSET); + + /* Set bit filter value / mask */ + + putreg32(fid1, priv->base + MPFS_CANFD_FILTER_C_VAL_OFFSET); + putreg32(fid2, priv->base + MPFS_CANFD_FILTER_C_MASK_OFFSET); + break; + + case HW_FILTER_RANGE: + + /* Set filter control reg for filter range */ + + if (can_type == CAN_MSGPRIO_LOW) + { + /* Classical CAN frame filter */ + + fc_reg = (can_id_type == CAN_EXT_ID) ? + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FRNE) : + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FRNB); + + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FRFE; + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FRFB; + } + else if (can_type == CAN_MSGPRIO_HIGH) + { + /* CANFD frame filter */ + + fc_reg = (can_id_type == CAN_EXT_ID) ? + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FRFE) : + (fc_reg | MPFS_CANFD_FILTER_CONTROL_FRFB); + + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FRNE; + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FRNB; + } + putreg32(fc_reg, priv->base + MPFS_CANFD_FILTER_CONTROL_OFFSET); + + /* Set range filter low / high */ + + putreg32(fid1, priv->base + MPFS_CANFD_FILTER_RAN_LOW_OFFSET); + putreg32(fid2, priv->base + MPFS_CANFD_FILTER_RAN_HIGH_OFFSET); + break; + + default: + + /* Unsupported filter type */ + + break; + } +} +#endif /* CONFIG_NETDEV_CAN_FILTER_IOCTL */ + +/**************************************************************************** + * Name: mpfs_can_reset_hw_filter + * + * Description: + * Reset all hw filters (both bit and range filter) to default settings + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * None + * + ****************************************************************************/ +#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL +static void mpfs_can_reset_hw_filter(struct mpfs_driver_s *priv) +{ + uint32_t reg; + + /* Reset filter control */ + + reg = 0; + reg |= MPFS_CANFD_FILTER_CONTROL_FANB; + reg |= MPFS_CANFD_FILTER_CONTROL_FANE; + reg |= MPFS_CANFD_FILTER_CONTROL_FAFB; + reg |= MPFS_CANFD_FILTER_CONTROL_FAFE; + putreg32(reg, priv->base + MPFS_CANFD_FILTER_CONTROL_OFFSET); + + /* Reset bit filter A */ + + putreg32(0, priv->base + MPFS_CANFD_FILTER_A_VAL_OFFSET); + putreg32(0, priv->base + MPFS_CANFD_FILTER_A_MASK_OFFSET); + + /* Reset bit filter B */ + + putreg32(0, priv->base + MPFS_CANFD_FILTER_B_VAL_OFFSET); + putreg32(0, priv->base + MPFS_CANFD_FILTER_B_MASK_OFFSET); + + /* Reset bit filter C */ + + putreg32(0, priv->base + MPFS_CANFD_FILTER_C_VAL_OFFSET); + putreg32(0, priv->base + MPFS_CANFD_FILTER_C_MASK_OFFSET); + + /* Reset range filter */ + + putreg32(0, priv->base + MPFS_CANFD_FILTER_RAN_LOW_OFFSET); + putreg32(0, priv->base + MPFS_CANFD_FILTER_RAN_HIGH_OFFSET); + + priv->used_bit_filter_number = 0; + priv->used_range_filter = false; +} +#endif /* CONFIG_NETDEV_CAN_FILTER_IOCTL */ + +/**************************************************************************** + * Name: mpfs_can_controller_start + * + * Description: + * This routine starts the driver. Routine expects that controller is in + * reset state. It setups initial Tx buffers for FIFO priorities, sets + * bittiming, enables interrupts, switches core to operational mode and + * changes controller state to %CAN_STATE_STOPPED. + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * + * Returned Value: + * Zero (OK) on success and failure value on error + * + * Assumptions: + * None + * + ****************************************************************************/ + +static int mpfs_can_controller_start(struct mpfs_driver_s *priv) +{ + uint32_t int_ena; + uint32_t int_msk; + uint32_t mode_reg; + int err; + struct mpfs_can_ctrlmode_s mode; + + /* Initialize TXT buffer sent / processed counter values */ + + priv->txb_sent = 0; + priv->txb_processed = 0; + + /* Configure TXT buffers priority */ + + priv->txb_prio = 0x01234567; + putreg32(priv->base, priv->base + MPFS_CANFD_TX_PRIORITY_OFFSET); + + /* Configure bit-rates and ssp */ + + err = mpfs_can_config_arbi_bit_timing(priv); + if (err < 0) + { + return err; + } + + err = mpfs_can_config_data_bit_timing(priv); + if (err < 0) + { + return err; + } + + err = mpfs_can_config_ssp(priv); + if (err < 0) + { + return err; + } + + /* Configure modes */ + + mode.flags = priv->can.ctrlmode; + mode.mask = 0xffffffff; + mpfs_can_config_controller_mode(priv, &mode); + + /* Configure interrupts */ + + int_ena = MPFS_CANFD_INT_STAT_RBNEI | + MPFS_CANFD_INT_STAT_TXBHCI | + MPFS_CANFD_INT_STAT_EWLI | + MPFS_CANFD_INT_STAT_FCSI | + MPFS_CANFD_INT_STAT_DOI; + + /* Bus error reporting -> Allow Error/Arb.lost interrupts */ + + if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) + { + int_ena |= MPFS_CANFD_INT_STAT_ALI | MPFS_CANFD_INT_STAT_BEI; + } + + int_msk = ~int_ena; /* Mask all disabled interrupts */ + + /* It's after reset, so there is no need to clear anything */ + + uint32_t mask = 0xffffffff; + putreg32(mask, priv->base + MPFS_CANFD_INT_MASK_CLR_OFFSET); + putreg32(int_msk, priv->base + MPFS_CANFD_INT_MASK_SET_OFFSET); + putreg32(int_ena, priv->base + MPFS_CANFD_INT_ENA_SET_OFFSET); + + /* Put CAN driver to STOPPED state first, CAN controller will enters + * ERROR_ACTIVE on initial FCSI + */ + + priv->can.state = CAN_STATE_STOPPED; + + /* Enable the CAN controller */ + + mode_reg = getreg32(priv->base + MPFS_CANFD_MODE_OFFSET); + mode_reg |= MPFS_CANFD_MODE_ENA; + putreg32(mode_reg, priv->base + MPFS_CANFD_MODE_OFFSET); + + return OK; +} + +/**************************************************************************** + * Name: mpfs_can_controller_stop + * + * Description: + * This routine stops the driver. This is the drivers stop routine. It will + * disable the interrupts and disable the CAN controller + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * None + * + ****************************************************************************/ + +static void mpfs_can_controller_stop(struct mpfs_driver_s *priv) +{ + uint32_t mask = 0xffffffff; + uint32_t mode; + + /* Disable interrupts */ + + putreg32(mask, priv->base + MPFS_CANFD_INT_ENA_CLR_OFFSET); + putreg32(mask, priv->base + MPFS_CANFD_INT_MASK_SET_OFFSET); + + /* Disable the CAN controller */ + + mode = getreg32(priv->base + MPFS_CANFD_MODE_OFFSET); + mode &= ~MPFS_CANFD_MODE_ENA; + putreg32(mode, priv->base + MPFS_CANFD_MODE_OFFSET); + + /* Set CAN driver state to STOPPED */ + + priv->can.state = CAN_STATE_STOPPED; +} + +/**************************************************************************** + * Name: mpfs_reset + * + * Description: + * Put the EMAC in the non-operational, reset state + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * + * Returned Value: + * OK for success and -ETIMEDOUT for failure + * + * Assumptions: + * + ****************************************************************************/ + +static int mpfs_reset(struct mpfs_driver_s *priv) +{ + uint32_t i = 100; + uint32_t device_id; + + /* Reset FPGA and FIC3, enable clock for FIC3 before RD WR */ + + modifyreg32(MPFS_SYSREG_SOFT_RESET_CR, + SYSREG_SOFT_RESET_CR_FPGA | SYSREG_SOFT_RESET_CR_FIC3, + 0); + modifyreg32(MPFS_SYSREG_SUBBLK_CLOCK_CR, 0, SYSREG_SUBBLK_CLOCK_CR_FIC3); + + /* Reset CAN controller */ + + putreg32(MPFS_CANFD_MODE_RST, priv->base + MPFS_CANFD_MODE_OFFSET); + + /* Check if the device is up again */ + + do + { + device_id = (getreg32(priv->base + MPFS_CANFD_DEVICE_ID_OFFSET) & + MPFS_CANFD_DEVICE_ID_DEVICE_ID) >> + MPFS_CANFD_DEVICE_ID_DEVICE_ID_SHIFT; + + if (device_id == MPFS_CANFD_ID) + { + return OK; + } + + if (!i--) + { + canwarn("Device did not leave reset\n"); + return -ETIMEDOUT; + } + + nxsig_usleep(200); + } + while (1); +} + +/**************************************************************************** + * Name: mpfs_ifup + * + * Description: + * NuttX Callback: Start the CAN interface + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure + * + * Assumptions: + * + ****************************************************************************/ + +static int mpfs_ifup(struct net_driver_s *dev) +{ + struct mpfs_driver_s *priv = + (struct mpfs_driver_s *)dev->d_private; + + if (mpfs_can_controller_start(priv) < 0) + { + canerr("CAN controller start failed\n"); + return -1; + } + + priv->bifup = true; + + priv->txdesc = (struct canfd_frame *)&g_tx_pool; + priv->rxdesc = (struct canfd_frame *)&g_rx_pool; + + priv->dev.d_buf = (uint8_t *)priv->txdesc; + + /* Set interrupts */ + + up_enable_irq(priv->config->canfd_fpga_irq); + + return OK; +} + +/**************************************************************************** + * Name: mpfs_ifdown + * + * Description: + * NuttX Callback: Stop the CAN interface. + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure + * + * Assumptions: + * None + * + ****************************************************************************/ + +static int mpfs_ifdown(struct net_driver_s *dev) +{ + struct mpfs_driver_s *priv = + (struct mpfs_driver_s *)dev->d_private; + + mpfs_can_controller_stop(priv); + + priv->bifup = false; + return OK; +} + +/**************************************************************************** + * Name: mpfs_ioctl + * + * Description: + * PHY ioctl command handler + * + * Input Parameters: + * dev - Reference to the NuttX driver state structure + * cmd - ioctl command + * arg - Argument accompanying the command + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + * Assumptions: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_NETDEV_IOCTL +static int mpfs_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) +{ +#if defined(CONFIG_NETDEV_CAN_BITRATE_IOCTL) || \ +defined(CONFIG_NETDEV_CAN_FILTER_IOCTL) + struct mpfs_driver_s *priv = + (struct mpfs_driver_s *)dev->d_private; +#endif + int ret; + + switch (cmd) + { +#ifdef CONFIG_NETDEV_CAN_BITRATE_IOCTL + case SIOCGCANBITRATE: + + /* Get bitrate from the CAN controller */ + + { + struct can_ioctl_data_s *req = + (struct can_ioctl_data_s *)((uintptr_t)arg); + req->arbi_bitrate = priv->can.bittiming.bitrate / 1000; /* kbit/s */ + req->arbi_samplep = priv->can.bittiming.sample_point / 10; + req->data_bitrate = priv->can.data_bittiming.bitrate / 1000; /* kbit/s */ + req->data_samplep = priv->can.data_bittiming.sample_point / 10; + ret = OK; + } + break; + + case SIOCSCANBITRATE: + + /* Set bitrate of the CAN controller */ + + { + struct can_ioctl_data_s *req = + (struct can_ioctl_data_s *)((uintptr_t)arg); + + if (req->arbi_bitrate > 1000) + { + canerr("Arbitration bitrate > 1Mbps is not supported."); + ret = -EINVAL; + break; + } + priv->can.bittiming.bitrate = req->arbi_bitrate * 1000; /* bit/s */ + + if (req->arbi_samplep > 100 || req->arbi_samplep <= 0) + { + canerr("Invalid arbitration sample point. " + "Range should be (0,100]%%."); + ret = -EINVAL; + break; + } + priv->can.bittiming.sample_point = + req->arbi_samplep * 10; /* In one-tenth of a percent */ + + if (req->data_bitrate > 4000 || + req->data_bitrate < req->arbi_bitrate) + { + canerr("Data bitrate higher than 4Mbps is yet to be supported. " + "Data br cannot be smaller than arbitration br."); + ret = -EINVAL; + break; + } + priv->can.data_bittiming.bitrate = req->data_bitrate * 1000; /* bit/s */ + + if (req->data_samplep > 100 || req->data_samplep <= 0) + { + canerr("Invalid data sample point. Range should be (0,100]%%."); + ret = -EINVAL; + break; + } + priv->can.data_bittiming.sample_point = + req->data_samplep * 10; /* In one-tenth of a percent */ + + /* Calculate arbitration and data bit timing */ + + mpfs_can_btr_compute(priv, + &priv->can.bittiming, + priv->can.bittiming_const); + mpfs_can_btr_compute(priv, + &priv->can.data_bittiming, + priv->can.data_bittiming_const); + + /* CAN controller reset to write bit timing register */ + + mpfs_can_controller_stop(priv); + if (mpfs_can_controller_start(priv) < 0) + { + canerr("CAN controller start failed."); + ret = -1; + break; + } + + ret = OK; + } + break; +#endif /* CONFIG_NETDEV_CAN_BITRATE_IOCTL */ + +#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL + case SIOCACANSTDFILTER: + + { + uint8_t filter; + struct can_ioctl_filter_s *req = + (struct can_ioctl_filter_s *)((uintptr_t)arg); + + if (req->ftype == CAN_FILTER_MASK) + { + if (priv->used_bit_filter_number == 0) + { + /* Use bit filter A */ + + filter = HW_FILTER_A; + } + else if (priv->used_bit_filter_number == 1) + { + /* Use bit filter B */ + + filter = HW_FILTER_B; + } + else if (priv->used_bit_filter_number == 2) + { + /* Use bit filter C */ + + filter = HW_FILTER_C; + } + else + { + /* All bit filters used. Return with error */ + + canerr("All bit filters used. Cannot add more. Delete all and " + "add again."); + ret = -1; + break; + } + priv->used_bit_filter_number++; + } + else if (req->ftype == CAN_FILTER_RANGE) + { + /* Use range filter */ + + filter = HW_FILTER_RANGE; + priv->used_range_filter = true; + } + else + { + /* Dual address and other filter types not yet support */ + + canerr("Dual address and other filter types not yet support"); + ret = -1; + break; + } + + /* Add hw filter */ + + mpfs_can_add_hw_filter(priv, + filter, + CAN_STD_ID, + req->fprio, /* LOW for CAN, HIGH for FDCAN */ + req->fid1, + req->fid2); + + ret = OK; + } + break; + + case SIOCACANEXTFILTER: + + /* Add CAN EXTENDED ID HW FILTER */ + + { + uint8_t filter; + struct can_ioctl_filter_s *req = + (struct can_ioctl_filter_s *)((uintptr_t)arg); + + if (req->ftype == CAN_FILTER_MASK) + { + if (priv->used_bit_filter_number == 0) + { + /* Use bit filter A */ + + filter = HW_FILTER_A; + } + else if (priv->used_bit_filter_number == 1) + { + /* Use bit filter B */ + + filter = HW_FILTER_B; + } + else if (priv->used_bit_filter_number == 2) + { + /* Use bit filter C */ + + filter = HW_FILTER_C; + } + else + { + /* All bit filters used. Return with error */ + + canerr("All bit filters used. Cannot add more. Delete all and " + "add again."); + ret = -1; + break; + } + priv->used_bit_filter_number++; + } + else if (req->ftype == CAN_FILTER_RANGE) + { + /* Use range filter */ + + if (priv->used_range_filter) + { + /* The range filter is already used. Return with error */ + + canerr("Range filter used. Cannot add more. Delete all and " + "add again."); + ret = -1; + break; + } + filter = HW_FILTER_RANGE; + priv->used_range_filter = true; + } + else + { + /* Dual address and other filter types not yet support */ + + canerr("Dual address and other filter types not yet support"); + ret = -1; + break; + } + + /* Add hw filter */ + + mpfs_can_add_hw_filter(priv, + filter, + CAN_EXT_ID, + req->fprio, /* CAN Type: LOW for CAN, HIGH for FDCAN */ + req->fid1, + req->fid2); + + ret = OK; + } + break; + + case SIOCDCANSTDFILTER: + case SIOCDCANEXTFILTER: + + /* Reset all HW FILTERs */ + + { + mpfs_can_reset_hw_filter(priv); + ret = OK; + } + break; +#endif /* CONFIG_NETDEV_CAN_FILTER_IOCTL */ + + default: + ret = -ENOTTY; + break; + } + + return ret; +} +#endif /* CONFIG_NETDEV_IOCTL */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mpfs_fpga_canfd_init + * + * Description: + * Initialize the CAN controller and driver + * + * Returned Value: + * On success, a pointer to the MPFS CAN-FD driver is + * returned. NULL is returned on any failure. + * + * Assumptions: + * None + * + ****************************************************************************/ + +int mpfs_fpga_canfd_init(void) +{ + caninfo("Initialize CAN-FD driver...\n"); + struct mpfs_driver_s *priv; + priv = &g_canfd; + memset(priv, 0, sizeof(struct mpfs_driver_s)); + + priv->base = CONFIG_MPFS_CANFD_BASE; + priv->config = &mpfs_fpga_canfd_config; + + /* Initialize the CAN common private data structure */ + + priv->can.state = CAN_STATE_ERROR_ACTIVE; + priv->ntxbufs = 2; + priv->can.bittiming_const = &mpfs_can_bit_timing_range; + priv->can.data_bittiming_const = &mpfs_can_bit_timing_data_range; + + /* Get the can_clk info */ + + priv->can.clock.freq = CONFIG_MPFS_CANFD_CLK; + + /* Needed for timing adjustment to be performed as soon as possible */ + + priv->can.bittiming.bitrate = CONFIG_MPFS_CANFD_ARBI_BITRATE; + priv->can.data_bittiming.bitrate = CONFIG_MPFS_CANFD_DATA_BITRATE; + priv->can.bittiming.sjw = 5; + priv->can.data_bittiming.sjw = 5; + + /* Calculate nominal and data bit timing */ + + mpfs_can_btr_compute(priv, + &priv->can.bittiming, + priv->can.bittiming_const); + mpfs_can_btr_compute(priv, + &priv->can.data_bittiming, + priv->can.data_bittiming_const); + +#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL + /* Init hw filter runtime var */ + + priv->used_bit_filter_number = 0; + priv->used_range_filter = false; +#endif /* CONFIG_NETDEV_CAN_FILTER_IOCTL */ + + /* Set CAN control modes */ + + priv->can.ctrlmode = CAN_CTRLMODE_FD + | CAN_CTRLMODE_BERR_REPORTING; + + /* Attach the interrupt handler */ + + if (irq_attach(priv->config->canfd_fpga_irq, mpfs_interrupt, priv)) + { + /* We could not attach the ISR to the interrupt */ + + canerr("ERROR: Failed to attach to CAN IRQ\n"); + return -EAGAIN; + } + + /* Initialize the driver structure */ + + priv->dev.d_ifup = mpfs_ifup; /* I/F up (new IP address) callback */ + priv->dev.d_ifdown = mpfs_ifdown; /* I/F down callback */ + priv->dev.d_txavail = mpfs_txavail; /* New TX data callback */ +#ifdef CONFIG_NETDEV_IOCTL + priv->dev.d_ioctl = mpfs_ioctl; /* Support CAN ioctl() calls */ +#endif + priv->dev.d_private = priv; /* Used to recover private state from dev */ + + /* Reset controller */ + + if (mpfs_reset(priv) < 0) + { + return -1; + } + + caninfo("CAN-FD driver init done\n"); + + /* Put the interface in the down state. This usually amounts to resetting + * the device and/or calling mpfs_ifdown(). + */ + + mpfs_ifdown(&priv->dev); + + /* Register the device with the OS so that socket IOCTLs can be performed */ + + netdev_register(&priv->dev, NET_LL_CAN); + + return OK; +} diff --git a/arch/risc-v/src/mpfs/mpfs_fpga_canfd.h b/arch/risc-v/src/mpfs/mpfs_fpga_canfd.h new file mode 100644 index 0000000000000..4d925560b7d9f --- /dev/null +++ b/arch/risc-v/src/mpfs/mpfs_fpga_canfd.h @@ -0,0 +1,94 @@ +/**************************************************************************** + * arch/risc-v/src/mpfs/mpfs_fpga_canfd.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_MPFS_MPFS_FPGA_CANFD_H +#define __ARCH_RISCV_SRC_MPFS_MPFS_FPGA_CANFD_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* Check if CAN-FD support is enabled. */ + +#ifdef CONFIG_MPFS_CANFD + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "hardware/mpfs_fpga_canfd.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: mpfs_fpga_canfd_init + * + * Description: + * Initialize a CANFD block. + * + * Returned Value: + * OK on success, Negated errno on failure + * + ****************************************************************************/ + +int mpfs_fpga_canfd_init(void); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* CONFIG_MPFS_CANFD */ +#endif /* __ARCH_RISCV_SRC_MPFS_MPFS_FPGA_CANFD_H */ From b4414cb7ca7977dadffb64bacef65328cd89df5a Mon Sep 17 00:00:00 2001 From: haitomatic Date: Wed, 15 Jun 2022 09:30:29 +0000 Subject: [PATCH 10/79] boards/risc-v/mpfs/icicle: add new target for testing mpfs canfd driver --- .../mpfs/icicle/configs/canfd/defconfig | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 boards/risc-v/mpfs/icicle/configs/canfd/defconfig diff --git a/boards/risc-v/mpfs/icicle/configs/canfd/defconfig b/boards/risc-v/mpfs/icicle/configs/canfd/defconfig new file mode 100644 index 0000000000000..94ce3f360e6d1 --- /dev/null +++ b/boards/risc-v/mpfs/icicle/configs/canfd/defconfig @@ -0,0 +1,125 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_DISABLE_OS_API is not set +# CONFIG_NSH_DISABLE_LOSMART is not set +# CONFIG_SPI_CALLBACK is not set +CONFIG_ALLOW_BSD_COMPONENTS=y +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="icicle" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_ICICLE_MPFS=y +CONFIG_ARCH_CHIP="mpfs" +CONFIG_ARCH_CHIP_MPFS250T_FCVG484=y +CONFIG_ARCH_CHIP_MPFS=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARD_LOOPSPERMSEC=54000 +CONFIG_BUILTIN=y +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_ERROR=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEBUG_WARN=y +CONFIG_DEBUG_CUSTOM_INFO=y +CONFIG_DEBUG_NET=y +CONFIG_DEBUG_NET_INFO=y +CONFIG_DEBUG_NET_WARN=y +CONFIG_DEBUG_NET_ERROR=y +CONFIG_DEV_ZERO=y +CONFIG_EXPERIMENTAL=y +CONFIG_FS_PROCFS=y +CONFIG_FS_ROMFS=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INIT_STACKSIZE=3072 +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_FLOATINGPOINT=y +CONFIG_LIBC_HOSTNAME="icicle" +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_MEMSET_64BIT=y +CONFIG_MEMSET_OPTSPEED=y +CONFIG_MPFS_ENABLE_DPFPU=y +CONFIG_MPFS_UART1=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y + +# nsh commands enable +CONFIG_NSH_DISABLE_IFUPDOWN=n +CONFIG_NSH_DISABLE_ENV=n +CONFIG_NSH_DISABLE_MKDIR=n +CONFIG_NSH_DISABLE_RM=n +CONFIG_NSH_DISABLE_RMDIR=n +CONFIG_NSH_DISABLE_UMOUNT=y +CONFIG_NSH_DISABLE_UNSET=n +CONFIG_NSH_DISABLE_SET=n +CONFIG_NSH_DISABLE_SOURCE=n +CONFIG_NSH_DISABLE_UNAME=n +CONFIG_NSH_DISABLE_PWD=n +CONFIG_NSH_DISABLE_PS=n +CONFIG_NSH_DISABLE_MV=n +CONFIG_NSH_DISABLE_IFCONFIG=n +CONFIG_NSH_DISABLE_DMESG=n +CONFIG_NSH_DISABLE_DF=n + +CONFIG_NSH_LINELEN=160 +CONFIG_NSH_STRERROR=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=1048576 +CONFIG_RAM_START=0x80200000 +CONFIG_RAW_BINARY=y +CONFIG_READLINE_CMD_HISTORY=y +CONFIG_READLINE_TABCOMPLETION=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_WAITPID=y +CONFIG_SERIAL_NPOLLWAITERS=2 +CONFIG_STACK_COLORATION=y +CONFIG_START_MONTH=4 +CONFIG_START_YEAR=2021 +CONFIG_SYSLOG_COLOR_OUTPUT=y +CONFIG_SYSTEM_CLE_CMD_HISTORY=y +CONFIG_SYSTEM_COLOR_CLE=y +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_TIME64=y +CONFIG_TASK_NAME_SIZE=20 +CONFIG_TESTING_GETPRIME=y +CONFIG_TESTING_OSTEST=y +CONFIG_UART1_SERIAL_CONSOLE=y + +# Net +CONFIG_NET=y +CONFIG_NET_ETHERNET=n +CONFIG_NET_IPv4=n +# CONFIG_NET_ETHERNET=y +# CONFIG_NET_IPv4=y +CONFIG_NET_READAHEAD=y +CONFIG_NETDEV_LATEINIT=y + +# Net socket +CONFIG_NSOCKET_DESCRIPTORS=8 +CONFIG_NET_NACTIVESOCKETS=16 +CONFIG_NET_SOCKOPTS=y +CONFIG_NET_TIMESTAMP=n +CONFIG_NETDEV_IFINDEX=y +CONFIG_NSH_NETINIT=y # or where network is init? + +# socketCAN +CONFIG_NET_CANPROTO_OPTIONS=y +CONFIG_NET_CAN=y +CONFIG_NET_CAN_CANFD=y +CONFIG_CAN_CONNS=4 +CONFIG_NET_CAN_SOCK_OPTS=y +CONFIG_NET_CAN_RAW_FILTER_MAX=32 + +# MPFS FGPA CANFD +CONFIG_MPFS_CANFD=y From 75cbc77d3d557f2aeb3fae00e7ecec668a862067 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Wed, 30 Nov 2022 11:57:34 +0200 Subject: [PATCH 11/79] mpfs/emmcsd: Set same base clock for SDR/DDR modes --- arch/risc-v/src/mpfs/mpfs_emmcsd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/risc-v/src/mpfs/mpfs_emmcsd.c b/arch/risc-v/src/mpfs/mpfs_emmcsd.c index 50856e2dbb685..30cecca999550 100644 --- a/arch/risc-v/src/mpfs/mpfs_emmcsd.c +++ b/arch/risc-v/src/mpfs/mpfs_emmcsd.c @@ -1848,7 +1848,8 @@ static void mpfs_clock(struct sdio_dev_s *dev, enum sdio_clock_e rate) { clckr = MPFS_MMC_CLOCK_200MHZ; } - else if (priv->bus_mode == MPFS_EMMCSD_MODE_SDR) + else if (priv->bus_mode == MPFS_EMMCSD_MODE_SDR || + priv->bus_mode == MPFS_EMMCSD_MODE_DDR) { clckr = MPFS_MMC_CLOCK_50MHZ; } From a4e0296b0ea0d19d1188bf499b5fe3f444790680 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Wed, 30 Nov 2022 11:58:17 +0200 Subject: [PATCH 12/79] mpfs/emmcsd: [HACK] Set 8-bit data width and DDR HS mode for eMMC This is not the correct way to do this, but it gives a nice perf. boost --- arch/risc-v/src/mpfs/mpfs_emmcsd.c | 60 ++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/arch/risc-v/src/mpfs/mpfs_emmcsd.c b/arch/risc-v/src/mpfs/mpfs_emmcsd.c index 30cecca999550..8e3b53454a3cf 100644 --- a/arch/risc-v/src/mpfs/mpfs_emmcsd.c +++ b/arch/risc-v/src/mpfs/mpfs_emmcsd.c @@ -1805,6 +1805,57 @@ static void mpfs_widebus(struct sdio_dev_s *dev, bool wide) } } +/**************************************************************************** + * Name: mpfs_clock + * + ****************************************************************************/ + +static void mpfs_set_hs_8bit(struct sdio_dev_s *dev) +{ + int ret; + uint32_t r1; + + if ((ret = mpfs_sendcmd(dev, MMCSD_CMD6, 0x03b70000u | (6 << 8))) == OK) + { + if ((ret == mpfs_waitresponse(dev, MMCSD_CMD6)) == OK) + { + ret = mpfs_recvshortcrc(dev, MMCSD_CMD6, &r1); + } + } + + if (ret < 0) + { + mcerr("Failed to set high speed mode\n"); + goto err; + } + + modifyreg32(MPFS_EMMCSD_HRS06, 0, priv->bus_mode); + + if ((ret = mpfs_sendcmd(dev, MMCSD_CMD6, 0x03b70000u | (2 << 8))) == OK) + { + if ((ret == mpfs_waitresponse(dev, MMCSD_CMD6)) == OK) + { + ret = mpfs_recvshortcrc(dev, MMCSD_CMD6, &r1); + } + } + + if (ret < 0) + { + mcerr("Failed to set 8-bit mode\n"); + goto err; + } + + modifyreg32(MPFS_EMMCSD_SRS10, 0, MPFS_EMMCSD_SRS10_EDTW); + return; + +err: + + /* Reset to 1-bit legacy mode */ + + modifyreg32(MPFS_EMMCSD_HRS06, 0, MPFS_EMMCSD_MODE_LEGACY); + modifyreg32(MPFS_EMMCSD_SRS10, MPFS_EMMCSD_SRS10_EDTW, 0); +} + /**************************************************************************** * Name: mpfs_clock * @@ -1877,6 +1928,15 @@ static void mpfs_clock(struct sdio_dev_s *dev, enum sdio_clock_e rate) /* Set the new clock frequency */ mpfs_setclkrate(priv, clckr); + + /* REVISIT: This should really be a separate configuration procedure */ + + if (rate == CLOCK_MMC_TRANSFER) + { + /* eMMC: Set 8-bit data bus and correct bus mode */ + + mpfs_set_hs_8bit(dev); + } } /**************************************************************************** From 5158a1ae014b1de46d4c9c7e0b1cab8cf82c25e0 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Wed, 30 Nov 2022 13:40:08 +0200 Subject: [PATCH 13/79] mpfs/emmcsd: Fix build issue with 8-bit HS mode --- arch/risc-v/src/mpfs/mpfs_emmcsd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/risc-v/src/mpfs/mpfs_emmcsd.c b/arch/risc-v/src/mpfs/mpfs_emmcsd.c index 8e3b53454a3cf..0b4acd1049477 100644 --- a/arch/risc-v/src/mpfs/mpfs_emmcsd.c +++ b/arch/risc-v/src/mpfs/mpfs_emmcsd.c @@ -1812,6 +1812,7 @@ static void mpfs_widebus(struct sdio_dev_s *dev, bool wide) static void mpfs_set_hs_8bit(struct sdio_dev_s *dev) { + struct mpfs_dev_s *priv = (struct mpfs_dev_s *)dev; int ret; uint32_t r1; From 51991d6d7cc4b0b7808ac8402650a0c8dfb617d1 Mon Sep 17 00:00:00 2001 From: Jani Paalijarvi Date: Mon, 12 Dec 2022 17:25:45 +0200 Subject: [PATCH 14/79] Fix build.yml Disable macOS builds for now. --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 849e225688ea9..79d9afc3f1bf7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -173,6 +173,7 @@ jobs: continue-on-error: true macOS: + if: ${{ false }} # disable for now permissions: contents: none runs-on: macos-13 From 95b4d63756d9b9153961f8d658177d07e95d359b Mon Sep 17 00:00:00 2001 From: Jani Paalijarvi Date: Fri, 9 Sep 2022 11:15:15 +0300 Subject: [PATCH 15/79] risc-v/mpfs: ihc: Make IHC HSS workaround configurable --- arch/risc-v/src/mpfs/Kconfig | 7 +++++++ arch/risc-v/src/mpfs/mpfs_ihc.c | 2 ++ 2 files changed, 9 insertions(+) diff --git a/arch/risc-v/src/mpfs/Kconfig b/arch/risc-v/src/mpfs/Kconfig index cba838b534cad..54f84900619eb 100644 --- a/arch/risc-v/src/mpfs/Kconfig +++ b/arch/risc-v/src/mpfs/Kconfig @@ -451,6 +451,13 @@ config MPFS_IHC_RPMSG_CH2 Use this only if using 2 x RPMSG channels. This makes the NuttX work as the RPMSG channel 2 client. +config MPFS_IHC_WITH_HSS + bool "IHC with HSS" + depends on MPFS_IHC_CLIENT + default n + ---help--- + Set this to true if using IHC with HSS bootloader + config MPFS_ETHMAC bool default n diff --git a/arch/risc-v/src/mpfs/mpfs_ihc.c b/arch/risc-v/src/mpfs/mpfs_ihc.c index 02bd8a2182692..a1833721a8ace 100644 --- a/arch/risc-v/src/mpfs/mpfs_ihc.c +++ b/arch/risc-v/src/mpfs/mpfs_ihc.c @@ -169,7 +169,9 @@ static int mpfs_rptun_register_callback(struct rptun_dev_s *dev, * HSS. */ +#ifdef CONFIG_MPFS_IHC_WITH_HSS uint8_t unused_filler[0x80000] __attribute__((section(".filler_area"))); +#endif static struct rpmsg_endpoint g_mpgs_echo_ping_ept; static struct mpfs_queue_table_s g_mpfs_virtqueue_table[VRINGS]; From 526ae426ad83d3e2dc8a157513ca00495903770c Mon Sep 17 00:00:00 2001 From: Jani Paalijarvi Date: Tue, 27 Sep 2022 09:49:07 +0300 Subject: [PATCH 16/79] drivers/net/rpmsgdrv.c: Take netdev_register() return value into account --- drivers/net/rpmsgdrv.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/rpmsgdrv.c b/drivers/net/rpmsgdrv.c index 33309d1c7ba9f..974f9e1abb301 100644 --- a/drivers/net/rpmsgdrv.c +++ b/drivers/net/rpmsgdrv.c @@ -1113,6 +1113,7 @@ int net_rpmsg_drv_init(FAR const char *cpuname, { FAR struct net_rpmsg_drv_s *priv; FAR struct net_driver_s *dev; + int ret; /* Allocate the interface structure */ @@ -1151,7 +1152,6 @@ int net_rpmsg_drv_init(FAR const char *cpuname, NULL); /* Register the device with the OS so that socket IOCTLs can be performed */ - - netdev_register(dev, lltype); - return OK; + ret = netdev_register(dev, lltype); + return ret; } From 3ce90e5d6e707d78433e9c6c7bcb8c31183db5ce Mon Sep 17 00:00:00 2001 From: Jani Paalijarvi Date: Tue, 13 Dec 2022 09:22:25 +0200 Subject: [PATCH 17/79] drivers/net/rpmsgdrv.c: Support only TRANSFER commands All other commands are disabled in send_recv(). Signed-off-by: Jani Paalijarvi --- drivers/net/rpmsgdrv.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/net/rpmsgdrv.c b/drivers/net/rpmsgdrv.c index 974f9e1abb301..a6ed0719313c8 100644 --- a/drivers/net/rpmsgdrv.c +++ b/drivers/net/rpmsgdrv.c @@ -612,6 +612,13 @@ static int net_rpmsg_drv_send_recv(FAR struct net_driver_s *dev, FAR struct net_rpmsg_drv_cookie_s cookie; int ret; + /* TODO: Only TRANSFER command is implemeted on Linux side */ + + if (command != NET_RPMSG_TRANSFER) + { + return 0; + } + nxsem_init(&cookie.sem, 0, 0); cookie.header = header; @@ -1152,6 +1159,7 @@ int net_rpmsg_drv_init(FAR const char *cpuname, NULL); /* Register the device with the OS so that socket IOCTLs can be performed */ + ret = netdev_register(dev, lltype); return ret; } From 5da097cd66435eb11c8d2b5151aaecef7d62a4ec Mon Sep 17 00:00:00 2001 From: Jani Paalijarvi Date: Wed, 30 Nov 2022 10:13:50 +0200 Subject: [PATCH 18/79] arch/risc-v/src/mpfs/mpfs_ihc.c: Increase RPMSG buffer size Signed-off-by: Jani Paalijarvi --- arch/risc-v/src/mpfs/mpfs_ihc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/risc-v/src/mpfs/mpfs_ihc.c b/arch/risc-v/src/mpfs/mpfs_ihc.c index a1833721a8ace..49f4ddaeba979 100644 --- a/arch/risc-v/src/mpfs/mpfs_ihc.c +++ b/arch/risc-v/src/mpfs/mpfs_ihc.c @@ -86,7 +86,7 @@ #define VRINGS 0x02 /* Number of vrings */ #define VRING_ALIGN 0x1000 /* Vring alignment */ #define VRING_NR 256 /* Number of descriptors */ -#define VRING_SIZE 512 /* Size of one descriptor */ +#define VRING_SIZE 612 /* Size of one descriptor */ #ifndef CONFIG_MPFS_IHC_RPMSG_CH2 /* This is the RPMSG default channel used with only one RPMSG channel */ From 8c5745bd0560deb3046345b7b741c8ce08ccbade Mon Sep 17 00:00:00 2001 From: Jani Paalijarvi Date: Fri, 2 Dec 2022 13:01:00 +0200 Subject: [PATCH 19/79] mpfs_ihc: Make Vring addresses configurable --- arch/risc-v/src/mpfs/Kconfig | 30 ++++++++++++++++++++++++++++++ arch/risc-v/src/mpfs/mpfs_ihc.c | 21 ++++++++++----------- 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/arch/risc-v/src/mpfs/Kconfig b/arch/risc-v/src/mpfs/Kconfig index 54f84900619eb..c0adb615e98f0 100644 --- a/arch/risc-v/src/mpfs/Kconfig +++ b/arch/risc-v/src/mpfs/Kconfig @@ -458,6 +458,36 @@ config MPFS_IHC_WITH_HSS ---help--- Set this to true if using IHC with HSS bootloader +config MPFS_CH1_VRING_SHMEM_ADDR + hex "Channel 1 Vring shared memory start" + default 0xA2410000 + depends on MPFS_IHC_CLIENT + +config MPFS_CH1_VRING0_DESC_ADDR + hex "Channel 1 Vring0 descriptor area" + default 0xA2400000 + depends on MPFS_IHC_CLIENT + +config MPFS_CH1_VRING1_DESC_ADDR + hex "Channel 1 Vring1 descriptor area" + default 0xA2408000 + depends on MPFS_IHC_CLIENT + +config MPFS_CH2_VRING_SHMEM_ADDR + hex "Channel 2 Vring shared memory start" + default 0xA2460000 + depends on MPFS_IHC_CLIENT && MPFS_IHC_RPMSG_CH2 + +config MPFS_CH2_VRING0_DESC_ADDR + hex "Channel 2 Vring0 descriptor area" + default 0xA2450000 + depends on MPFS_IHC_CLIENT && MPFS_IHC_RPMSG_CH2 + +config MPFS_CH2_VRING1_DESC_ADDR + hex "Channel 2 Vring1 descriptor area" + default 0xA2458000 + depends on MPFS_IHC_CLIENT && MPFS_IHC_RPMSG_CH2 + config MPFS_ETHMAC bool default n diff --git a/arch/risc-v/src/mpfs/mpfs_ihc.c b/arch/risc-v/src/mpfs/mpfs_ihc.c index 49f4ddaeba979..40662408275a8 100644 --- a/arch/risc-v/src/mpfs/mpfs_ihc.c +++ b/arch/risc-v/src/mpfs/mpfs_ihc.c @@ -91,19 +91,18 @@ #ifndef CONFIG_MPFS_IHC_RPMSG_CH2 /* This is the RPMSG default channel used with only one RPMSG channel */ -#define VRING_SHMEM 0xa2410000 /* Vring shared memory start */ -#define VRING0_DESCRIPTORS 0xa2400000 /* Vring0 descriptor area */ -#define VRING1_DESCRIPTORS 0xa2408000 /* Vring1 descriptor area */ -#define VRING0_NOTIFYID 0 /* Vring0 id */ -#define VRING1_NOTIFYID 1 /* Vring1 id */ +#define VRING_SHMEM CONFIG_MPFS_CH1_VRING_SHMEM_ADDR /* Vring shared memory start */ +#define VRING0_DESCRIPTORS CONFIG_MPFS_CH1_VRING0_DESC_ADDR /* Vring0 descriptor area */ +#define VRING1_DESCRIPTORS CONFIG_MPFS_CH1_VRING1_DESC_ADDR /* Vring1 descriptor area */ +#define VRING0_NOTIFYID 0 /* Vring0 id */ +#define VRING1_NOTIFYID 1 /* Vring1 id */ #else /* This is the RPMSG channel 2, enabled separately */ - -#define VRING_SHMEM 0xa2460000 /* Vring shared memory start */ -#define VRING0_DESCRIPTORS 0xa2450000 /* Vring0 descriptor area */ -#define VRING1_DESCRIPTORS 0xa2458000 /* Vring1 descriptor area */ -#define VRING0_NOTIFYID 2 /* Vring0 id */ -#define VRING1_NOTIFYID 3 /* Vring1 id */ +#define VRING_SHMEM CONFIG_MPFS_CH2_VRING_SHMEM_ADDR /* Vring shared memory start */ +#define VRING0_DESCRIPTORS CONFIG_MPFS_CH2_VRING0_DESC_ADDR /* Vring0 descriptor area */ +#define VRING1_DESCRIPTORS CONFIG_MPFS_CH2_VRING1_DESC_ADDR /* Vring1 descriptor area */ +#define VRING0_NOTIFYID 2 /* Vring0 id */ +#define VRING1_NOTIFYID 3 /* Vring1 id */ #endif /**************************************************************************** From fcb4f6f80e979bddf91b1896c574316bff8cb7ef Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Thu, 19 Jan 2023 12:06:33 +0400 Subject: [PATCH 20/79] arch/risc-v/src/mpfs/mpfs_fpga_canfd.c: Fix CONFIG_DEBUG_CAN_INFO ifdef and forward declare devif_loopback Signed-off-by: Jukka Laitinen --- arch/risc-v/src/mpfs/mpfs_fpga_canfd.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c b/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c index fc9d0ec202be5..0fb3ea06eebec 100644 --- a/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c +++ b/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c @@ -50,6 +50,12 @@ #include "hardware/mpfs_fpga_canfd.h" #include "riscv_internal.h" +/**************************************************************************** + * Forward Declarations + ****************************************************************************/ + +extern int devif_loopback(FAR struct net_driver_s *dev); + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -1196,7 +1202,7 @@ static int mpfs_interrupt(int irq, void *context, void *arg) if (isr & MPFS_CANFD_INT_STAT_TXBHCI) { -#if CONFIG_DEBUG_CAN_INFO +#ifdef CONFIG_DEBUG_CAN_INFO caninfo("txb_sent=0x%08x txb_processed=0x%08x\n", priv->txb_sent, priv->txb_processed); for (int i = 0; i < priv->ntxbufs; i++) From e66ee2903739ff2a3aa1b14360a7c6b196f342b6 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Thu, 19 Jan 2023 15:05:36 +0400 Subject: [PATCH 21/79] boards/risc-v/mpfs/icicle/configs/canfd/defconfig: Normalize Signed-off-by: Jukka Laitinen --- .../mpfs/icicle/configs/canfd/defconfig | 63 ++++--------------- 1 file changed, 11 insertions(+), 52 deletions(-) diff --git a/boards/risc-v/mpfs/icicle/configs/canfd/defconfig b/boards/risc-v/mpfs/icicle/configs/canfd/defconfig index 94ce3f360e6d1..32507993c60e8 100644 --- a/boards/risc-v/mpfs/icicle/configs/canfd/defconfig +++ b/boards/risc-v/mpfs/icicle/configs/canfd/defconfig @@ -6,8 +6,9 @@ # modifications. # # CONFIG_DISABLE_OS_API is not set +# CONFIG_NET_ETHERNET is not set +# CONFIG_NET_IPv4 is not set # CONFIG_NSH_DISABLE_LOSMART is not set -# CONFIG_SPI_CALLBACK is not set CONFIG_ALLOW_BSD_COMPONENTS=y CONFIG_ARCH="risc-v" CONFIG_ARCH_BOARD="icicle" @@ -26,13 +27,12 @@ CONFIG_DEBUG_ERROR=y CONFIG_DEBUG_FEATURES=y CONFIG_DEBUG_FULLOPT=y CONFIG_DEBUG_INFO=y -CONFIG_DEBUG_SYMBOLS=y -CONFIG_DEBUG_WARN=y -CONFIG_DEBUG_CUSTOM_INFO=y CONFIG_DEBUG_NET=y +CONFIG_DEBUG_NET_ERROR=y CONFIG_DEBUG_NET_INFO=y CONFIG_DEBUG_NET_WARN=y -CONFIG_DEBUG_NET_ERROR=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEBUG_WARN=y CONFIG_DEV_ZERO=y CONFIG_EXPERIMENTAL=y CONFIG_FS_PROCFS=y @@ -41,35 +41,22 @@ CONFIG_IDLETHREAD_STACKSIZE=2048 CONFIG_INIT_ENTRYPOINT="nsh_main" CONFIG_INIT_STACKSIZE=3072 CONFIG_INTELHEX_BINARY=y -CONFIG_LIBC_FLOATINGPOINT=y CONFIG_LIBC_HOSTNAME="icicle" CONFIG_LIBC_PERROR_STDOUT=y CONFIG_LIBC_STRERROR=y CONFIG_MEMSET_64BIT=y CONFIG_MEMSET_OPTSPEED=y +CONFIG_MPFS_CANFD=y CONFIG_MPFS_ENABLE_DPFPU=y CONFIG_MPFS_UART1=y +CONFIG_NET=y +CONFIG_NETDEV_IFINDEX=y +CONFIG_NETDEV_LATEINIT=y +CONFIG_NET_CAN=y +CONFIG_NET_CAN_SOCK_OPTS=y CONFIG_NSH_ARCHINIT=y CONFIG_NSH_BUILTIN_APPS=y - -# nsh commands enable -CONFIG_NSH_DISABLE_IFUPDOWN=n -CONFIG_NSH_DISABLE_ENV=n -CONFIG_NSH_DISABLE_MKDIR=n -CONFIG_NSH_DISABLE_RM=n -CONFIG_NSH_DISABLE_RMDIR=n CONFIG_NSH_DISABLE_UMOUNT=y -CONFIG_NSH_DISABLE_UNSET=n -CONFIG_NSH_DISABLE_SET=n -CONFIG_NSH_DISABLE_SOURCE=n -CONFIG_NSH_DISABLE_UNAME=n -CONFIG_NSH_DISABLE_PWD=n -CONFIG_NSH_DISABLE_PS=n -CONFIG_NSH_DISABLE_MV=n -CONFIG_NSH_DISABLE_IFCONFIG=n -CONFIG_NSH_DISABLE_DMESG=n -CONFIG_NSH_DISABLE_DF=n - CONFIG_NSH_LINELEN=160 CONFIG_NSH_STRERROR=y CONFIG_PREALLOC_TIMERS=4 @@ -95,31 +82,3 @@ CONFIG_TASK_NAME_SIZE=20 CONFIG_TESTING_GETPRIME=y CONFIG_TESTING_OSTEST=y CONFIG_UART1_SERIAL_CONSOLE=y - -# Net -CONFIG_NET=y -CONFIG_NET_ETHERNET=n -CONFIG_NET_IPv4=n -# CONFIG_NET_ETHERNET=y -# CONFIG_NET_IPv4=y -CONFIG_NET_READAHEAD=y -CONFIG_NETDEV_LATEINIT=y - -# Net socket -CONFIG_NSOCKET_DESCRIPTORS=8 -CONFIG_NET_NACTIVESOCKETS=16 -CONFIG_NET_SOCKOPTS=y -CONFIG_NET_TIMESTAMP=n -CONFIG_NETDEV_IFINDEX=y -CONFIG_NSH_NETINIT=y # or where network is init? - -# socketCAN -CONFIG_NET_CANPROTO_OPTIONS=y -CONFIG_NET_CAN=y -CONFIG_NET_CAN_CANFD=y -CONFIG_CAN_CONNS=4 -CONFIG_NET_CAN_SOCK_OPTS=y -CONFIG_NET_CAN_RAW_FILTER_MAX=32 - -# MPFS FGPA CANFD -CONFIG_MPFS_CANFD=y From d5b44841a443282eb2c306f5789f753626bfd745 Mon Sep 17 00:00:00 2001 From: haitomatic Date: Thu, 19 Jan 2023 19:59:44 +0000 Subject: [PATCH 22/79] remove devif_loopback in canfd driver since it is now devif_poll func that takes care of the need for loopback --- arch/risc-v/src/mpfs/mpfs_fpga_canfd.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c b/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c index 0fb3ea06eebec..7fa4996cfe697 100644 --- a/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c +++ b/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c @@ -50,12 +50,6 @@ #include "hardware/mpfs_fpga_canfd.h" #include "riscv_internal.h" -/**************************************************************************** - * Forward Declarations - ****************************************************************************/ - -extern int devif_loopback(FAR struct net_driver_s *dev); - /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -1517,20 +1511,17 @@ static int mpfs_txpoll(struct net_driver_s *dev) if (priv->dev.d_len > 0) { - if (!devif_loopback(&priv->dev)) - { - /* Send the packet */ + /* Send the packet */ - mpfs_transmit(priv); + mpfs_transmit(priv); - /* Check if there is room in the device to hold another packet. If - * not, return a non-zero value to terminate the poll. - */ + /* Check if there is room in the device to hold another packet. If + * not, return a non-zero value to terminate the poll. + */ - if (!MPFS_CAN_FD_TXNF(priv)) - { - return -EBUSY; - } + if (!MPFS_CAN_FD_TXNF(priv)) + { + return -EBUSY; } } From a9855a5e72707629b6d8c7d02450d1f8dee28257 Mon Sep 17 00:00:00 2001 From: Jani Paalijarvi Date: Fri, 27 Jan 2023 09:35:17 +0200 Subject: [PATCH 23/79] arch/risc-v/src/mpfs/mpfs_ihc.c: Minor fixes Remove unnecessary VQID shifting (16 -> 0). Give an error if RPTUN init fails. --- arch/risc-v/src/mpfs/mpfs_ihc.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_ihc.c b/arch/risc-v/src/mpfs/mpfs_ihc.c index 40662408275a8..18272f418f20e 100644 --- a/arch/risc-v/src/mpfs/mpfs_ihc.c +++ b/arch/risc-v/src/mpfs/mpfs_ihc.c @@ -438,7 +438,7 @@ static void mpfs_ihc_rx_handler(uint32_t *message, bool is_ack) } else { - g_vq_idx = (message[0] >> 16); + g_vq_idx = message[0]; DEBUGASSERT((g_vq_idx == VRING0_NOTIFYID) || (g_vq_idx == VRING1_NOTIFYID)); @@ -983,7 +983,7 @@ static int mpfs_rptun_notify(struct rptun_dev_s *dev, uint32_t notifyid) if (notifyid == VRING0_NOTIFYID) { - tx_msg[0] = (notifyid << 16); + tx_msg[0] = notifyid; tx_msg[1] = 0; return mpfs_ihc_tx_message(CONTEXTA_HARTID, tx_msg); @@ -1142,7 +1142,6 @@ static void mpfs_rpmsg_device_created(struct rpmsg_device *rdev, void *priv_) struct rpmsg_virtio_device *vdev = container_of(rdev, struct rpmsg_virtio_device, rdev); - g_mpfs_virtio_device = vdev; g_mpfs_rpmsg_device = rdev; @@ -1256,6 +1255,12 @@ int mpfs_ihc_init(void) ihcinfo("Waiting for the master online...\n"); ret = mpfs_rptun_init(MPFS_RPTUN_SHMEM_NAME, MPFS_RPTUN_CPU_NAME); + if (ret < 0) + { + ihcerr("ERROR: Not able to init RPTUN\n"); + goto init_error; + } + ihcinfo("..master is online\n"); /* Register callback to notify when rpmsg device is ready */ From 92007092b1ad29bb847c9c7b0c98a8a793a7e0df Mon Sep 17 00:00:00 2001 From: Jani Paalijarvi Date: Fri, 27 Jan 2023 10:57:21 +0200 Subject: [PATCH 24/79] Remove MPFS_IHC_LINUX_ON_HART4 from default configurations Enable LINUX_ON_HART4 in rpmsg-ch2 defconfig of ICICLE board. Remove LINUX_ON_HART4 config from rpmsg-ch1 defconfig of ICICLE board. --- arch/risc-v/src/mpfs/Kconfig | 2 +- boards/risc-v/mpfs/icicle/configs/rpmsg-ch1/defconfig | 1 - boards/risc-v/mpfs/icicle/configs/rpmsg-ch2/defconfig | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/risc-v/src/mpfs/Kconfig b/arch/risc-v/src/mpfs/Kconfig index c0adb615e98f0..af8b0595be853 100644 --- a/arch/risc-v/src/mpfs/Kconfig +++ b/arch/risc-v/src/mpfs/Kconfig @@ -398,7 +398,7 @@ config MPFS_IHC_LINUX_ON_HART3 config MPFS_IHC_LINUX_ON_HART4 int "Linux on hart4" depends on MPFS_IHC_CLIENT || MPFS_IHC_SBI - default 1 + default 0 range 0 1 ---help--- Set this to 1 if U-boot / Linux is running on hart4 diff --git a/boards/risc-v/mpfs/icicle/configs/rpmsg-ch1/defconfig b/boards/risc-v/mpfs/icicle/configs/rpmsg-ch1/defconfig index cd526cb972ac6..415a2892d4136 100644 --- a/boards/risc-v/mpfs/icicle/configs/rpmsg-ch1/defconfig +++ b/boards/risc-v/mpfs/icicle/configs/rpmsg-ch1/defconfig @@ -50,7 +50,6 @@ CONFIG_MEMSET_64BIT=y CONFIG_MEMSET_OPTSPEED=y CONFIG_MM_IOB=y CONFIG_MPFS_IHC_CLIENT=y -CONFIG_MPFS_IHC_LINUX_ON_HART4=0 CONFIG_MPFS_IHC_NUTTX_ON_HART1=1 CONFIG_MPFS_IHC_NUTTX_ON_HART2=0 CONFIG_MPFS_UART1=y diff --git a/boards/risc-v/mpfs/icicle/configs/rpmsg-ch2/defconfig b/boards/risc-v/mpfs/icicle/configs/rpmsg-ch2/defconfig index 5dc95abc1fc44..3341c583e9c86 100644 --- a/boards/risc-v/mpfs/icicle/configs/rpmsg-ch2/defconfig +++ b/boards/risc-v/mpfs/icicle/configs/rpmsg-ch2/defconfig @@ -51,6 +51,7 @@ CONFIG_MEMSET_OPTSPEED=y CONFIG_MM_IOB=y CONFIG_MPFS_IHC_CLIENT=y CONFIG_MPFS_IHC_LINUX_ON_HART3=0 +CONFIG_MPFS_IHC_LINUX_ON_HART4=1 CONFIG_MPFS_IHC_RPMSG_CH2=y CONFIG_MPFS_UART2=y CONFIG_NSH_ARCHINIT=y From da7fcae456f60e83771e07e3e07fe56e4398a923 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Fri, 3 Feb 2023 17:17:15 +0400 Subject: [PATCH 25/79] arch/arm/src/stm32f7/stm32_ethernet.c: Fix "unused variable" warning Fix build warning when CONFIG_STM32F7_AUTONEG is not set Signed-off-by: Jukka Laitinen --- arch/arm/src/stm32f7/stm32_ethernet.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/src/stm32f7/stm32_ethernet.c b/arch/arm/src/stm32f7/stm32_ethernet.c index 92daf09f5d32f..0e14c905b4713 100644 --- a/arch/arm/src/stm32f7/stm32_ethernet.c +++ b/arch/arm/src/stm32f7/stm32_ethernet.c @@ -3136,7 +3136,9 @@ static inline int stm32_dm9161(struct stm32_ethmac_s *priv) static int stm32_phyinit(struct stm32_ethmac_s *priv) { +#ifdef CONFIG_STM32F7_AUTONEG volatile uint32_t timeout; +#endif uint32_t regval; uint16_t phyval; int ret; From 62d55b736f3d60e86c41c3f4c5798bd35a16326b Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Thu, 9 Feb 2023 20:53:42 +0400 Subject: [PATCH 26/79] arch/risc-v/src/mpfs/mpfs_userspace.c: Map MTIME into userspace reserved IO area in protected build Signed-off-by: Jukka Laitinen --- arch/risc-v/src/mpfs/hardware/mpfs_clint.h | 6 ++++++ arch/risc-v/src/mpfs/mpfs_userspace.c | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/arch/risc-v/src/mpfs/hardware/mpfs_clint.h b/arch/risc-v/src/mpfs/hardware/mpfs_clint.h index a15d849267902..d398cca8dbd71 100644 --- a/arch/risc-v/src/mpfs/hardware/mpfs_clint.h +++ b/arch/risc-v/src/mpfs/hardware/mpfs_clint.h @@ -21,6 +21,12 @@ #ifndef __ARCH_RISCV_SRC_MPFS_HARDWARE_MPFS_CLINT_H #define __ARCH_RISCV_SRC_MPFS_HARDWARE_MPFS_CLINT_H +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "mpfs_memorymap.h" + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ diff --git a/arch/risc-v/src/mpfs/mpfs_userspace.c b/arch/risc-v/src/mpfs/mpfs_userspace.c index a4409e2dcb088..3b8f9ef5d5093 100644 --- a/arch/risc-v/src/mpfs/mpfs_userspace.c +++ b/arch/risc-v/src/mpfs/mpfs_userspace.c @@ -31,6 +31,7 @@ #include #include +#include "hardware/mpfs_clint.h" #include "mpfs_userspace.h" #include "riscv_internal.h" @@ -248,6 +249,10 @@ static void configure_mmu(void) map_region(UFLASH_START, UFLASH_START, UFLASH_SIZE, MMU_UTEXT_FLAGS); map_region(USRAM_START, USRAM_START, USRAM_SIZE, MMU_UDATA_FLAGS); + /* Map the MTIME counter to the start of USR IO region */ + + map_region(MPFS_CLINT_MTIME & (~RV_MMU_PAGE_MASK), USRIO_START, RV_MMU_PAGE_SIZE, PTE_R | PTE_U | PTE_G); + /* Connect the L1 and L2 page tables */ mmu_ln_setentry(1, PGT_L1_VBASE, PGT_L2_PBASE, UFLASH_START, PTE_G); From 26f28ec9deb72286aabbbd7e6e303414f9f4874f Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Fri, 10 Feb 2023 15:48:33 +0400 Subject: [PATCH 27/79] boards/risc-v/mpfs/icicle: Add USRIO area for userspace IO mappings Signed-off-by: Jukka Laitinen --- boards/risc-v/mpfs/icicle/include/board_memorymap.h | 10 ++++++++++ boards/risc-v/mpfs/icicle/scripts/kernel-space.ld | 2 ++ boards/risc-v/mpfs/icicle/scripts/memory.ld | 2 ++ 3 files changed, 14 insertions(+) diff --git a/boards/risc-v/mpfs/icicle/include/board_memorymap.h b/boards/risc-v/mpfs/icicle/include/board_memorymap.h index 47cac1185796c..353112aa86d6d 100644 --- a/boards/risc-v/mpfs/icicle/include/board_memorymap.h +++ b/boards/risc-v/mpfs/icicle/include/board_memorymap.h @@ -65,6 +65,11 @@ #define USRAM_START (uintptr_t)__usram_start #define USRAM_SIZE (uintptr_t)__usram_size +/* User IO */ + +#define USRIO_START (uintptr_t)__usrio_start +#define USRIO_SIZE (uintptr_t)__usrio_size + /**************************************************************************** * Public Data ****************************************************************************/ @@ -95,4 +100,9 @@ extern uint8_t __uflash_size[]; extern uint8_t __usram_start[]; extern uint8_t __usram_size[]; +/* User IO (R) */ + +extern uint8_t __usrio_start[]; +extern uint8_t __usrio_size[]; + #endif /* __BOARDS_RISC_V_MPFS_ICICLE_INCLUDE_BOARD_MEMORYMAP_H */ diff --git a/boards/risc-v/mpfs/icicle/scripts/kernel-space.ld b/boards/risc-v/mpfs/icicle/scripts/kernel-space.ld index 20ecbffab506b..bd0b3675ce8b5 100644 --- a/boards/risc-v/mpfs/icicle/scripts/kernel-space.ld +++ b/boards/risc-v/mpfs/icicle/scripts/kernel-space.ld @@ -30,6 +30,8 @@ __uflash_start = ORIGIN(uflash); __uflash_size = LENGTH(uflash); __usram_start = ORIGIN(usram); __usram_size = LENGTH(usram); +__usrio_start = ORIGIN(usrio); +__usrio_size = LENGTH(usrio); /* Provide the kernel boundaries as well */ diff --git a/boards/risc-v/mpfs/icicle/scripts/memory.ld b/boards/risc-v/mpfs/icicle/scripts/memory.ld index 890ba735baf8c..f31a88d4eaacc 100644 --- a/boards/risc-v/mpfs/icicle/scripts/memory.ld +++ b/boards/risc-v/mpfs/icicle/scripts/memory.ld @@ -25,4 +25,6 @@ MEMORY ksram (rwx) : ORIGIN = 0x80080000, LENGTH = 256K /* w/ cache */ usram (rwx) : ORIGIN = 0x800C0000, LENGTH = 256K /* w/ cache */ + + usrio (r) : ORIGIN = 0x80100000, LENGTH = 32K } From 765313f8b8d809b0b7b9a9ea2d50f55be35b6533 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Mon, 13 Feb 2023 17:36:12 +0400 Subject: [PATCH 28/79] Add mpfs crypto driver into nuttx build Signed-off-by: Jukka Laitinen --- arch/risc-v/src/mpfs/.gitignore | 1 + arch/risc-v/src/mpfs/Kconfig | 8 ++++++++ arch/risc-v/src/mpfs/Make.defs | 3 +++ arch/risc-v/src/mpfs/crypto.defs | 14 ++++++++++++++ 4 files changed, 26 insertions(+) create mode 100644 arch/risc-v/src/mpfs/.gitignore create mode 100644 arch/risc-v/src/mpfs/crypto.defs diff --git a/arch/risc-v/src/mpfs/.gitignore b/arch/risc-v/src/mpfs/.gitignore new file mode 100644 index 0000000000000..b099a95f78380 --- /dev/null +++ b/arch/risc-v/src/mpfs/.gitignore @@ -0,0 +1 @@ +/crypto diff --git a/arch/risc-v/src/mpfs/Kconfig b/arch/risc-v/src/mpfs/Kconfig index af8b0595be853..efb6706b96195 100644 --- a/arch/risc-v/src/mpfs/Kconfig +++ b/arch/risc-v/src/mpfs/Kconfig @@ -808,3 +808,11 @@ config ARCH_MPU_HAS_NO4 config ARCH_MPU_HAS_NAPOT default y + +config MPFS_CRYPTO + bool "Enable MPFS HW crypto + default n + +#if MPFS_CRYPTO +source crypto/Kconfig +#endif diff --git a/arch/risc-v/src/mpfs/Make.defs b/arch/risc-v/src/mpfs/Make.defs index a45a133fac850..8efd0168c9bd3 100644 --- a/arch/risc-v/src/mpfs/Make.defs +++ b/arch/risc-v/src/mpfs/Make.defs @@ -107,3 +107,6 @@ ifeq ($(CONFIG_MPFS_CORESPI),y) CHIP_CSRCS += mpfs_corespi.c endif +ifeq ($(CONFIG_MPFS_CRYPTO),y) +include mpfs/crypto.defs +endif diff --git a/arch/risc-v/src/mpfs/crypto.defs b/arch/risc-v/src/mpfs/crypto.defs new file mode 100644 index 0000000000000..44e6a4633968c --- /dev/null +++ b/arch/risc-v/src/mpfs/crypto.defs @@ -0,0 +1,14 @@ +MPFS_CRYPTO = mpfs/crypto/.git +$(MPFS_CRYPTO): + $(Q) echo "Cloning PolarFire crypto driver" + $(Q) git clone git@github.com:tiiuae/pf_crypto mpfs/crypto + +context::$(MPFS_CRYPTO) + +distclean:: + $(Q) rm -rf mpfs/crypto + +CHIP_CSRCS += mpfs_crypto.c + +DEPPATH += --dep-path crypto --dep-path mpfs/crypto +VPATH += :crypto:mpfs/crypto From 7661ca113e6412c9b15ac50930839d104819681f Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Tue, 14 Feb 2023 12:51:04 +0200 Subject: [PATCH 29/79] mpfs/Kconfig: fix typo on config file --- arch/risc-v/src/mpfs/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/risc-v/src/mpfs/Kconfig b/arch/risc-v/src/mpfs/Kconfig index efb6706b96195..bd97aff18fee4 100644 --- a/arch/risc-v/src/mpfs/Kconfig +++ b/arch/risc-v/src/mpfs/Kconfig @@ -810,7 +810,7 @@ config ARCH_MPU_HAS_NAPOT default y config MPFS_CRYPTO - bool "Enable MPFS HW crypto + bool "Enable MPFS HW crypto" default n #if MPFS_CRYPTO From a8c0f1ea651176b05aee1209bf46c0307b0b71f7 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Tue, 14 Feb 2023 13:56:55 +0200 Subject: [PATCH 30/79] mpfs/mpfs_mm_init: Add the MTIME user mapping for kernel mode as well Just a temporary patch, need to implement some kind of scalable solution for this. It might be a good idea to map something else for the user to avoid using ecall to enter the kernel for simple reads ? Also, increase the L3 table size --- arch/risc-v/src/mpfs/mpfs_mm_init.c | 11 ++++++++--- arch/risc-v/src/mpfs/mpfs_userspace.c | 3 ++- boards/risc-v/mpfs/icicle/scripts/ld-kernel.script | 6 ++++++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_mm_init.c b/arch/risc-v/src/mpfs/mpfs_mm_init.c index 90f69b33fe440..6c5bdd394dacc 100644 --- a/arch/risc-v/src/mpfs/mpfs_mm_init.c +++ b/arch/risc-v/src/mpfs/mpfs_mm_init.c @@ -54,9 +54,9 @@ #define PGT_L2_VBASE PGT_L2_PBASE #define PGT_L3_VBASE PGT_L3_PBASE -#define PGT_L1_SIZE (512) /* Enough to map 512 GiB */ -#define PGT_L2_SIZE (512) /* Enough to map 1 GiB */ -#define PGT_L3_SIZE (1024) /* Enough to map 4 MiB */ +#define PGT_L1_SIZE (512) /* Enough to map 512 GiB */ +#define PGT_L2_SIZE (512) /* Enough to map 1 GiB */ +#define PGT_L3_SIZE (40 * 1024) /* Enough to map 40 MiB */ /* Calculate the minimum size for the L3 table */ @@ -251,4 +251,9 @@ void mpfs_kernel_mappings(void) mmu_ln_map_region(2, PGT_L2_VBASE, PGPOOL_START, PGPOOL_START, PGPOOL_SIZE, MMU_KDATA_FLAGS); + + /* Map the MTIME counter to the start of USR IO region */ + + map_region(MPFS_CLINT_MTIME & (~RV_MMU_PAGE_MASK), USRIO_START, + RV_MMU_PAGE_SIZE, PTE_R | PTE_U | PTE_G); } diff --git a/arch/risc-v/src/mpfs/mpfs_userspace.c b/arch/risc-v/src/mpfs/mpfs_userspace.c index 3b8f9ef5d5093..f457a26f6b949 100644 --- a/arch/risc-v/src/mpfs/mpfs_userspace.c +++ b/arch/risc-v/src/mpfs/mpfs_userspace.c @@ -251,7 +251,8 @@ static void configure_mmu(void) /* Map the MTIME counter to the start of USR IO region */ - map_region(MPFS_CLINT_MTIME & (~RV_MMU_PAGE_MASK), USRIO_START, RV_MMU_PAGE_SIZE, PTE_R | PTE_U | PTE_G); + map_region(MPFS_CLINT_MTIME & (~RV_MMU_PAGE_MASK), USRIO_START, + RV_MMU_PAGE_SIZE, PTE_R | PTE_U | PTE_G); /* Connect the L1 and L2 page tables */ diff --git a/boards/risc-v/mpfs/icicle/scripts/ld-kernel.script b/boards/risc-v/mpfs/icicle/scripts/ld-kernel.script index cea4ae185760d..0e8a29c657fb5 100644 --- a/boards/risc-v/mpfs/icicle/scripts/ld-kernel.script +++ b/boards/risc-v/mpfs/icicle/scripts/ld-kernel.script @@ -28,6 +28,7 @@ MEMORY kflash (rx) : ORIGIN = 0x80000000, LENGTH = 2048K /* w/ cache */ ksram (rwx) : ORIGIN = 0x80200000, LENGTH = 2048K /* w/ cache */ pgram (rwx) : ORIGIN = 0x80400000, LENGTH = 4096K /* w/ cache */ + usrio (r) : ORIGIN = 0x80800000, LENGTH = 32K /* w/ cache */ } OUTPUT_ARCH("riscv") @@ -45,6 +46,11 @@ __ksram_end = ORIGIN(ksram) + LENGTH(ksram); __pgheap_start = ORIGIN(pgram); __pgheap_size = LENGTH(pgram); +/* User I/O */ + +__usrio_start = ORIGIN(usrio); +__usrio_size = LENGTH(usrio); + ENTRY(_stext) EXTERN(__start) SECTIONS From 669e6e2b6be2f37269bf4e14bdf494d7a69323d0 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Thu, 23 Feb 2023 11:46:02 +0400 Subject: [PATCH 31/79] arch/risc-v/src/mpfs/Kconfig: Don't source crypto/Kconfig There is no make step executed for this directory before the Kconfigure, so all Kconfig's just need to be in-tree Signed-off-by: Jukka Laitinen --- arch/risc-v/src/mpfs/Kconfig | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/risc-v/src/mpfs/Kconfig b/arch/risc-v/src/mpfs/Kconfig index bd97aff18fee4..825f60c95ea2d 100644 --- a/arch/risc-v/src/mpfs/Kconfig +++ b/arch/risc-v/src/mpfs/Kconfig @@ -813,6 +813,8 @@ config MPFS_CRYPTO bool "Enable MPFS HW crypto" default n -#if MPFS_CRYPTO -source crypto/Kconfig -#endif +if MPFS_CRYPTO +config MPFS_CRYPTO_DMA + bool "Enable MPFS HW crypto DMA" + default y +endif From 9c96ac4cf9ebe0e4fdf77ad968730a4650e37a6b Mon Sep 17 00:00:00 2001 From: Seppo Hirvela Date: Wed, 22 Feb 2023 09:24:33 +0200 Subject: [PATCH 32/79] DP-4881: The latest NuttX OpenAMP version does not work with Saluki HardenedOS --- arch/risc-v/src/mpfs/mpfs_ihc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/risc-v/src/mpfs/mpfs_ihc.c b/arch/risc-v/src/mpfs/mpfs_ihc.c index 18272f418f20e..a9b0e71ec4e8f 100644 --- a/arch/risc-v/src/mpfs/mpfs_ihc.c +++ b/arch/risc-v/src/mpfs/mpfs_ihc.c @@ -87,6 +87,7 @@ #define VRING_ALIGN 0x1000 /* Vring alignment */ #define VRING_NR 256 /* Number of descriptors */ #define VRING_SIZE 612 /* Size of one descriptor */ +#define VDEV_NOTIFYID 4 /* virtio device notify id */ #ifndef CONFIG_MPFS_IHC_RPMSG_CH2 /* This is the RPMSG default channel used with only one RPMSG channel */ @@ -843,6 +844,7 @@ mpfs_rptun_get_resource(struct rptun_dev_s *dev) rpmsg_vdev); rsc->rpmsg_vdev.type = RSC_VDEV; rsc->rpmsg_vdev.id = VIRTIO_ID_RPMSG; + rsc->rpmsg_vdev.notifyid = VDEV_NOTIFYID; rsc->rpmsg_vdev.dfeatures = 1 << VIRTIO_RPMSG_F_NS | 1 << VIRTIO_RPMSG_F_ACK | VIRTIO_RING_F_EVENT_IDX; From 1fa7923cf9549b9b21bc49b66af62f956181ab2f Mon Sep 17 00:00:00 2001 From: Jari Nippula Date: Mon, 6 Mar 2023 10:42:50 +0200 Subject: [PATCH 33/79] arch/risc-v/src/mpfs: symlink pf_crypto submodule --- arch/risc-v/src/mpfs/crypto.defs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/risc-v/src/mpfs/crypto.defs b/arch/risc-v/src/mpfs/crypto.defs index 44e6a4633968c..caf2403be34ab 100644 --- a/arch/risc-v/src/mpfs/crypto.defs +++ b/arch/risc-v/src/mpfs/crypto.defs @@ -1,7 +1,7 @@ MPFS_CRYPTO = mpfs/crypto/.git $(MPFS_CRYPTO): - $(Q) echo "Cloning PolarFire crypto driver" - $(Q) git clone git@github.com:tiiuae/pf_crypto mpfs/crypto + $(Q) echo "Symlink PolarFire crypto driver submodule" + $(Q) $(DIRLINK) $(CURDIR)/../../../../extern/pf_crypto mpfs/crypto context::$(MPFS_CRYPTO) From ccfeb55a9bdbc7d893796ee6d16c6264b6b94b5d Mon Sep 17 00:00:00 2001 From: Jari Nippula Date: Thu, 9 Mar 2023 08:58:02 +0200 Subject: [PATCH 34/79] arch/riscv/src/mpfs/mpfs_ethernet.c: discard err rxframe in int work Workaround to avoid deadlock situation: The RX shall not try to wait for complete frame in case there is RX errors detected. In case mpfs_receive is called, it keeps waiting for complete frame and also keeps the net_lock locked. In the mean while, the TX may run out of free descriptors, but can not get net_lock mutex lock to be able to release used descriptors. If there are no free TX descs it disables RX interrupts because it may require to send response to the received frame. So, TX side keeps RX interrupts disabled due to lack of free descriptors and RX blocks TX to release those descs by stubbornly waiting for complete frame. --- arch/risc-v/src/mpfs/mpfs_ethernet.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_ethernet.c b/arch/risc-v/src/mpfs/mpfs_ethernet.c index d49360255262f..405f2de3f8e84 100644 --- a/arch/risc-v/src/mpfs/mpfs_ethernet.c +++ b/arch/risc-v/src/mpfs/mpfs_ethernet.c @@ -1060,13 +1060,6 @@ static void mpfs_interrupt_work(void *arg) uint32_t rx_error = 0; ninfo("RX: rsr=0x%X\n", rsr); - if ((rsr & RECEIVE_STATUS_FRAME_RECEIVED) != 0) - { - /* Handle the received packet */ - - mpfs_receive(priv, queue); - } - /* Check for Receive Overrun */ if ((rsr & RECEIVE_STATUS_RECEIVE_OVERRUN) != 0) @@ -1108,6 +1101,12 @@ static void mpfs_interrupt_work(void *arg) regval |= NETWORK_CONTROL_ENABLE_RECEIVE; mac_putreg(priv, NETWORK_CONTROL, regval); } + else if ((rsr & RECEIVE_STATUS_FRAME_RECEIVED) != 0) + { + /* Handle the received packet only in case there are no RX errors */ + + mpfs_receive(priv, queue); + } } net_unlock(); From 080730a30102c507a2db3edf9e8aa839bf1313f6 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Thu, 16 Mar 2023 13:00:35 +0200 Subject: [PATCH 35/79] arch/risc-v/src/mpfs/crypto.defs: Update to include mpfs_systemservice.c Signed-off-by: Jukka Laitinen --- arch/risc-v/src/mpfs/crypto.defs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/risc-v/src/mpfs/crypto.defs b/arch/risc-v/src/mpfs/crypto.defs index caf2403be34ab..98f5c330e65c1 100644 --- a/arch/risc-v/src/mpfs/crypto.defs +++ b/arch/risc-v/src/mpfs/crypto.defs @@ -8,7 +8,7 @@ context::$(MPFS_CRYPTO) distclean:: $(Q) rm -rf mpfs/crypto -CHIP_CSRCS += mpfs_crypto.c +CHIP_CSRCS += mpfs_crypto.c mpfs_systemservice.c -DEPPATH += --dep-path crypto --dep-path mpfs/crypto -VPATH += :crypto:mpfs/crypto +DEPPATH += --dep-path mpfs/crypto +VPATH += :mpfs/crypto From 17c79abec977ecc3b12da7e445a462a072af7979 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Mon, 3 Apr 2023 14:30:03 +0300 Subject: [PATCH 36/79] arch/risc-v/src/mpfs: Generate an unique locally administrated MAC address Add a function to read PolarFire's serial number from system controller, and use the first five digits as device's mac address Signed-off-by: Jukka Laitinen --- arch/risc-v/src/mpfs/Make.defs | 2 +- arch/risc-v/src/mpfs/mpfs_dsn.c | 154 +++++++++++++++++++++++++++ arch/risc-v/src/mpfs/mpfs_dsn.h | 81 ++++++++++++++ arch/risc-v/src/mpfs/mpfs_ethernet.c | 13 ++- 4 files changed, 248 insertions(+), 2 deletions(-) create mode 100644 arch/risc-v/src/mpfs/mpfs_dsn.c create mode 100644 arch/risc-v/src/mpfs/mpfs_dsn.h diff --git a/arch/risc-v/src/mpfs/Make.defs b/arch/risc-v/src/mpfs/Make.defs index 8efd0168c9bd3..4059405a44641 100644 --- a/arch/risc-v/src/mpfs/Make.defs +++ b/arch/risc-v/src/mpfs/Make.defs @@ -32,7 +32,7 @@ CHIP_CSRCS += mpfs_irq.c mpfs_irq_dispatch.c CHIP_CSRCS += mpfs_lowputc.c mpfs_serial.c CHIP_CSRCS += mpfs_start.c mpfs_timerisr.c CHIP_CSRCS += mpfs_gpio.c mpfs_systemreset.c -CHIP_CSRCS += mpfs_plic.c +CHIP_CSRCS += mpfs_plic.c mpfs_dsn.c ifeq ($(CONFIG_MPFS_DMA),y) CHIP_CSRCS += mpfs_dma.c diff --git a/arch/risc-v/src/mpfs/mpfs_dsn.c b/arch/risc-v/src/mpfs/mpfs_dsn.c new file mode 100644 index 0000000000000..9558049d54be8 --- /dev/null +++ b/arch/risc-v/src/mpfs/mpfs_dsn.c @@ -0,0 +1,154 @@ +/**************************************************************************** + * arch/risc-v/src/mpfs/mpfs_dsn.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include "mpfs_dsn.h" +#include "riscv_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define MPFS_SCBCTRL_BASE 0x37020000ul +#define SERVICES_CR_OFFSET 0x50 +#define SERVICES_SR_OFFSET 0x54 + +#define SERVICES_CR (MPFS_SCBCTRL_BASE + SERVICES_CR_OFFSET) +#define SERVICES_SR (MPFS_SCBCTRL_BASE + SERVICES_SR_OFFSET) + +/* Command bits */ + +#define SCBCTRL_SERVICESCR_REQ (1 << 0) + +/* Status bits */ + +#define SCBCTRL_SERVICESSR_BUSY (1 << 1) + +/* 2kB long mailbox. */ + +#define MSS_SCBMAILBOX 0x37020800ul + +/* Retry count */ + +#define RETRIES 100 + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mpfs_read_dsn + * + * Description: + * Read n bytes of the device serial number. Full serial number is 16 bytes + * + * Parameters: + * dsn - A pointer to the destination buffer + * len - Number of bytes to read + * + * Returned Value: + * Number of bytes read, -1 on error + * + ****************************************************************************/ + +size_t mpfs_read_dsn(uint8_t *dsn, size_t len) +{ + uint32_t reg; + uint8_t *p = (uint8_t *)MSS_SCBMAILBOX; + irqstate_t flags = enter_critical_section(); + unsigned retries = RETRIES; + + /* Wait until the system controller is not busy. + * Read the SN inside critical section, just in case someone else is + * using the system controller services + */ + + while (getreg32(SERVICES_SR) & SCBCTRL_SERVICESSR_BUSY && retries-- > 0) + { + leave_critical_section(flags); + usleep(1000); + flags = enter_critical_section(); + } + + if (retries == 0) + { + goto out; + } + + /* Read at max MPFS_DSN_LENGTH bytes, set the rest to 0 */ + + if (len > MPFS_DSN_LENGTH) + { + len = MPFS_DSN_LENGTH; + } + + /* Command: bits 0 to 6 is the opcode, bits 7 to 15 is the Mailbox + * offset. In this case, opcode == 0 and offset == 0. + */ + + putreg32(SCBCTRL_SERVICESCR_REQ, SERVICES_CR); + + /* Wait until the system controller has started processing the command */ + + retries = RETRIES; + do + { + reg = getreg32(SERVICES_CR); + } + while (reg & SCBCTRL_SERVICESCR_REQ && retries-- > 0); + + if (retries == 0) + { + goto out; + } + + /* Wait for the completion of the command */ + + retries = RETRIES; + do + { + reg = getreg32(SERVICES_SR); + } + while (reg & SCBCTRL_SERVICESSR_BUSY && retries-- > 0); + + if (retries == 0) + { + goto out; + } + + /* Read the bytes of serial from service mailbox */ + + for (uint8_t i = 0; i < len; i++) + { + dsn[i] = getreg8(p++); + } + +out: + + leave_critical_section(flags); + + return retries > 0 ? len : -ETIMEDOUT; +} diff --git a/arch/risc-v/src/mpfs/mpfs_dsn.h b/arch/risc-v/src/mpfs/mpfs_dsn.h new file mode 100644 index 0000000000000..4843d9a12e06a --- /dev/null +++ b/arch/risc-v/src/mpfs/mpfs_dsn.h @@ -0,0 +1,81 @@ +/**************************************************************************** + * arch/risc-v/src/mpfs/mpfs_dsn.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#ifndef __ARCH_RISCV_SRC_MPFS_MPFS_DSN_H +#define __ARCH_RISCV_SRC_MPFS_MPFS_DSN_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Pre-Processor Declarations + ****************************************************************************/ + +/* This is the length of the serial number */ + +#define MPFS_DSN_LENGTH 16 + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: mpfs_read_dsn + * + * Description: + * Read n bytes of the device serial number. Full serial number is 16 bytes + * + * Parameters: + * dsn - A pointer to the destination buffer + * len - Number of bytes to read + * + * Returned Value: + * Number of bytes read or negated errno + * + ****************************************************************************/ + +size_t mpfs_read_dsn(uint8_t *dsn, size_t len); + +#ifdef __cplusplus +} +#endif +#undef EXTERN + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_RISCV_SRC_MPFS_MPFS_DSN_H */ diff --git a/arch/risc-v/src/mpfs/mpfs_ethernet.c b/arch/risc-v/src/mpfs/mpfs_ethernet.c index 405f2de3f8e84..c72764ebb8c59 100644 --- a/arch/risc-v/src/mpfs/mpfs_ethernet.c +++ b/arch/risc-v/src/mpfs/mpfs_ethernet.c @@ -53,6 +53,7 @@ #include "riscv_internal.h" #include "mpfs_memorymap.h" #include "mpfs_ethernet.h" +#include "mpfs_dsn.h" #if defined(CONFIG_NET) && defined(CONFIG_MPFS_ETHMAC) @@ -1496,7 +1497,7 @@ static int mpfs_ifup(struct net_driver_s *dev) return ret; } - /* Set the MAC address (should have been configured while we were down) */ + /* Set the MAC address */ mpfs_macaddress(priv); @@ -3567,6 +3568,16 @@ int mpfs_ethinitialize(int intf) priv->queue[2].dma_rxbuf_size = (uint32_t *)(base + DMA_RXBUF_SIZE_Q2); priv->queue[3].dma_rxbuf_size = (uint32_t *)(base + DMA_RXBUF_SIZE_Q3); + /* Generate a locally administrated MAC address for this ethernet if */ + + /* Set first byte to 0x02 or 0x06 acc. to the intf */ + + priv->dev.d_mac.ether.ether_addr_octet[0] = 0x02 | ((intf & 1) << 2); + + /* Read the next 5 bytes from the S/N */ + + mpfs_read_dsn(&priv->dev.d_mac.ether.ether_addr_octet[1], 5); + /* MPU hack for ETH DMA if not enabled by bootloader */ #ifdef CONFIG_MPFS_MPU_DMA_ENABLE From f7c0a2d46b06935e3f1344ae43f62142867bc477 Mon Sep 17 00:00:00 2001 From: Jari Nippula Date: Fri, 14 Apr 2023 10:51:57 +0300 Subject: [PATCH 37/79] emmc interrupt blackout issue fix sendfifo() function need enable BWR_IE before checking if BWE is enabled to avoid BWE to be activated between the BWE check and BWR interrupt enabling, which causes the interrupt to be missed and Data Timeout error. --- arch/risc-v/src/mpfs/mpfs_emmcsd.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_emmcsd.c b/arch/risc-v/src/mpfs/mpfs_emmcsd.c index 0b4acd1049477..ca4ec4c5ef4c7 100644 --- a/arch/risc-v/src/mpfs/mpfs_emmcsd.c +++ b/arch/risc-v/src/mpfs/mpfs_emmcsd.c @@ -782,12 +782,22 @@ static void mpfs_sendfifo(struct mpfs_dev_s *priv) * come back when we're good to write again. */ - if (priv->remaining && (!(getreg32(MPFS_EMMCSD_SRS09) & - MPFS_EMMCSD_SRS09_BWE))) + if (priv->remaining) { - modifyreg32(MPFS_EMMCSD_SRS14, 0, MPFS_EMMCSD_SRS14_BWR_IE); + /* Enable BWR before checking BWE bit */ + putreg32(MPFS_EMMCSD_SRS12_BWR, MPFS_EMMCSD_SRS12); - return; + modifyreg32(MPFS_EMMCSD_SRS14, 0, MPFS_EMMCSD_SRS14_BWR_IE); + if (!(getreg32(MPFS_EMMCSD_SRS09) & MPFS_EMMCSD_SRS09_BWE)) + { + return; + } + + /* There is still room for writing to buffer, + * disable BWR and continue. + */ + + modifyreg32(MPFS_EMMCSD_SRS14, MPFS_EMMCSD_SRS14_BWR_IE, 0); } } From 9e10f64a9755d93a7bbb1080eab38e7ab68689a5 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Tue, 18 Apr 2023 15:18:54 +0300 Subject: [PATCH 38/79] mpfs/mpfs_userspace: Increase user space size to 8MB The user i/o area goes over 4MB, so need more page tables --- arch/risc-v/src/mpfs/mpfs_userspace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/risc-v/src/mpfs/mpfs_userspace.c b/arch/risc-v/src/mpfs/mpfs_userspace.c index f457a26f6b949..7c13fd6a41ac3 100644 --- a/arch/risc-v/src/mpfs/mpfs_userspace.c +++ b/arch/risc-v/src/mpfs/mpfs_userspace.c @@ -54,7 +54,7 @@ #define PGT_L1_SIZE (512) /* Enough to map 512 GiB */ #define PGT_L2_SIZE (512) /* Enough to map 1 GiB */ -#define PGT_L3_SIZE (1024) /* Enough to map 4 MiB */ +#define PGT_L3_SIZE (2048) /* Enough to map 8 MiB */ #define SLAB_COUNT (sizeof(m_l3_pgtable) / RV_MMU_PAGE_SIZE) From dd0851bd3a3b5e056d0c9b554b8e5b680ed4aeac Mon Sep 17 00:00:00 2001 From: Eero Nurkkala Date: Mon, 3 Apr 2023 10:22:40 +0300 Subject: [PATCH 39/79] test: bootloader: apply ihc flow control If Linux kernel sends data, block all incoming msgs from the remote end until an ack arrives, which completes the linux send data command. If other than ack arrives, the logic in the Linux is no longer maintained, causing the virtio marked broken. Signed-off-by: Eero Nurkkala --- arch/risc-v/src/mpfs/hardware/mpfs_ihc.h | 4 +- arch/risc-v/src/mpfs/mpfs_ihc_sbi.c | 92 ++++++++++++++++-------- 2 files changed, 63 insertions(+), 33 deletions(-) diff --git a/arch/risc-v/src/mpfs/hardware/mpfs_ihc.h b/arch/risc-v/src/mpfs/hardware/mpfs_ihc.h index af7a081dd949e..9b8bf00571e2a 100644 --- a/arch/risc-v/src/mpfs/hardware/mpfs_ihc.h +++ b/arch/risc-v/src/mpfs/hardware/mpfs_ihc.h @@ -27,8 +27,8 @@ enum mpfs_irq_type_e { - MP_IRQ = 0x0, - ACK_IRQ = 0x1, + MP_IRQ = 0x1, + ACK_IRQ = 0x2, }; #define IHC_MAX_MESSAGE_SIZE 2 diff --git a/arch/risc-v/src/mpfs/mpfs_ihc_sbi.c b/arch/risc-v/src/mpfs/mpfs_ihc_sbi.c index bf90abc20f98a..923faf9d032fe 100644 --- a/arch/risc-v/src/mpfs/mpfs_ihc_sbi.c +++ b/arch/risc-v/src/mpfs/mpfs_ihc_sbi.c @@ -79,6 +79,7 @@ static uint32_t g_connected_harts_c; * mhartid base on the context, not necessarily the actual * mhartid. * is_ack - Boolean that is set true if an ack has been found + * is_mp - Boolean that is set true if a msg is present also * * Returned Value: * Remote hart id @@ -86,7 +87,8 @@ static uint32_t g_connected_harts_c; ****************************************************************************/ static uint32_t mpfs_ihc_sbi_parse_incoming_hartid(uint32_t mhartid, - bool *is_ack) + bool *is_ack, + bool *is_mp) { uint32_t hart_id = 0; uint32_t return_hart_id = UNDEFINED_HART_ID; @@ -112,6 +114,16 @@ static uint32_t mpfs_ihc_sbi_parse_incoming_hartid(uint32_t mhartid, { return_hart_id = hart_id; *is_ack = true; + + /* We might also have a msg present */ + + test_int = (1 << (hart_id * 2)); + + if (msg_avail & test_int) + { + *is_mp = true; + } + break; } } @@ -124,6 +136,7 @@ static uint32_t mpfs_ihc_sbi_parse_incoming_hartid(uint32_t mhartid, { return_hart_id = hart_id; *is_ack = false; + *is_mp = true; break; } } @@ -231,7 +244,6 @@ static uint32_t mpfs_ihc_sbi_context_to_local_hart_id(ihc_channel_t channel) } DEBUGASSERT(hart < MPFS_NUM_HARTS); - return hart; } @@ -259,7 +271,8 @@ static uint32_t mpfs_ihc_sbi_context_to_local_hart_id(ihc_channel_t channel) static void mpfs_ihc_sbi_message_present_handler(uint32_t *message, uint32_t mhartid, uint32_t rhartid, - bool is_ack) + bool is_ack, + bool is_mp) { struct ihc_sbi_rx_msg_s *msg; uintptr_t message_ihc = (uintptr_t)MPFS_IHC_MSG_IN(mhartid, rhartid); @@ -267,17 +280,22 @@ static void mpfs_ihc_sbi_message_present_handler(uint32_t *message, msg = (struct ihc_sbi_rx_msg_s *)message; - if (is_ack) + if (is_ack && !is_mp) { msg->irq_type = ACK_IRQ; /* msg->ihc_msg content doesn't matter here */ } - else + else if (is_mp && !is_ack) { msg->irq_type = MP_IRQ; msg->ihc_msg = *(struct mpfs_ihc_msg_s *)message_ihc; } + else + { + msg->irq_type = ACK_IRQ | MP_IRQ; + msg->ihc_msg = *(struct mpfs_ihc_msg_s *)message_ihc; + } DEBUGASSERT(sizeof(msg->ihc_msg) >= message_size_ihc); } @@ -302,11 +320,9 @@ static void mpfs_ihc_sbi_message_present_handler(uint32_t *message, ****************************************************************************/ static void mpfs_ihc_sbi_rx_message(uint32_t rhartid, uint32_t mhartid, - bool is_ack, uint32_t *msg) + bool is_ack, bool is_mp, uint32_t *msg) { - uint32_t ctrl_reg = getreg32(MPFS_IHC_CTRL(mhartid, rhartid)); - - if (is_ack) + if (is_ack && !is_mp) { if (mhartid == CONTEXTB_HARTID) { @@ -318,10 +334,14 @@ static void mpfs_ihc_sbi_rx_message(uint32_t rhartid, uint32_t mhartid, DEBUGASSERT(msg != NULL); mpfs_ihc_sbi_message_present_handler(msg, mhartid, rhartid, - is_ack); + is_ack, is_mp); + + /* Clear the ack */ + + modifyreg32(MPFS_IHC_CTRL(mhartid, rhartid), ACK_CLR, 0); } } - else if (MP_MESSAGE_PRESENT == (ctrl_reg & MP_MASK)) + else if (is_mp && !is_ack) { /* Check if we have a message */ @@ -335,24 +355,25 @@ static void mpfs_ihc_sbi_rx_message(uint32_t rhartid, uint32_t mhartid, DEBUGASSERT(msg != NULL); mpfs_ihc_sbi_message_present_handler(msg, mhartid, rhartid, - is_ack); + is_ack, is_mp); } /* Set MP to 0. Note this generates an interrupt on the other hart * if it has RMPIE bit set in the control register */ - volatile uint32_t temp = getreg32(MPFS_IHC_CTRL(mhartid, rhartid)) & - ~MP_MASK; - - /* Check if ACKIE_EN is set */ + modifyreg32(MPFS_IHC_CTRL(mhartid, rhartid), MP_MASK, ACK_INT); + } + else if (is_ack && is_mp) + { + DEBUGASSERT(msg != NULL); + mpfs_ihc_sbi_message_present_handler(msg, mhartid, rhartid, + is_ack, is_mp); - if (temp & ACKIE_EN) - { - temp |= ACK_INT; - } + /* Clear the ack and mp */ - putreg32(temp, MPFS_IHC_CTRL(mhartid, rhartid)); + modifyreg32(MPFS_IHC_CTRL(mhartid, rhartid), ACK_CLR | MP_MASK, + ACK_INT); } } @@ -377,22 +398,16 @@ void mpfs_ihc_sbi_message_present_indirect_isr(ihc_channel_t channel, uint32_t *msg) { bool is_ack; + bool is_mp = false; uint32_t mhartid = mpfs_ihc_sbi_context_to_local_hart_id(channel); uint32_t origin_hart = mpfs_ihc_sbi_parse_incoming_hartid(mhartid, - &is_ack); - + &is_ack, + &is_mp); if (origin_hart != UNDEFINED_HART_ID) { /* Process incoming packet */ - mpfs_ihc_sbi_rx_message(origin_hart, mhartid, is_ack, msg); - - if (is_ack) - { - /* Clear the ack */ - - modifyreg32(MPFS_IHC_CTRL(mhartid, origin_hart), ACK_CLR, 0); - } + mpfs_ihc_sbi_rx_message(origin_hart, mhartid, is_ack, is_mp, msg); } } @@ -624,12 +639,27 @@ int mpfs_ihc_sbi_ecall_handler(unsigned long funcid, uint32_t remote_channel, break; case SBI_EXT_IHC_SEND: + /* Send and wait for the ACK: disable all incoming traffic + * meanwhile with the SW flow control. + */ + + modifyreg32(MPFS_IHC_INT_EN(0), 0, 1); /* Flow contol on */ result = mpfs_ihc_sbi_tx_message(remote_channel, message_ptr); break; case SBI_EXT_IHC_RECEIVE: mpfs_ihc_sbi_message_present_indirect_isr(remote_channel, message_ptr); + + /* ACK_IRQ indicates the end of the IHC_SEND transaction */ + + struct ihc_sbi_rx_msg_s *msg; + msg = (struct ihc_sbi_rx_msg_s *)message_ptr; + + if (msg->irq_type & ACK_IRQ) + { + modifyreg32(MPFS_IHC_INT_EN(0), 1, 0); /* Flow contol off */ + } break; default: From 0855101f39f0f6947e99768797435c12b8e80891 Mon Sep 17 00:00:00 2001 From: Eero Nurkkala Date: Wed, 29 Mar 2023 15:53:17 +0300 Subject: [PATCH 40/79] risc-v/mpfs: apply ihc software flow control Utilize the sw flow control. Also detect situations where both ack and msg present is set. In that case, consider both flags. Signed-off-by: Eero Nurkkala --- arch/risc-v/src/mpfs/mpfs_ihc.c | 190 +++++++++++++++++++++++++++----- 1 file changed, 162 insertions(+), 28 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_ihc.c b/arch/risc-v/src/mpfs/mpfs_ihc.c index a9b0e71ec4e8f..cb4f530ddb96a 100644 --- a/arch/risc-v/src/mpfs/mpfs_ihc.c +++ b/arch/risc-v/src/mpfs/mpfs_ihc.c @@ -38,7 +38,9 @@ #include #include #include +#include #include +#include #include #include @@ -138,6 +140,12 @@ struct mpfs_queue_table_s void *data; }; +struct mpfs_ihc_work_arg_s +{ + uint32_t mhartid; + uint32_t rhartid; +}; + /**************************************************************************** * Private Function Prototypes ****************************************************************************/ @@ -189,6 +197,11 @@ static uint16_t g_vq_idx; static int g_plic_irq; static bool g_rptun_initialized; +#ifdef IHC_AVOID_ACK_AND_MP +static struct mpfs_ihc_work_arg_s g_work_arg; +static struct work_s g_ihc_work; +#endif + const uint32_t ihcia_remote_harts[MPFS_NUM_HARTS] = { IHCIA_H0_REMOTE_HARTS, @@ -237,6 +250,7 @@ static const struct rptun_ops_s g_mpfs_rptun_ops = * mhartid base on the context, not necessarily the actual * mhartid. * is_ack - Boolean that is set true if an ack has been found + * is_msg - Boolean that is set true if a message is present * * Returned Value: * Remote hart id @@ -244,7 +258,8 @@ static const struct rptun_ops_s g_mpfs_rptun_ops = ****************************************************************************/ static uint32_t mpfs_ihc_parse_incoming_hartid(uint32_t mhartid, - bool *is_ack) + bool *is_ack, + bool *is_msg) { uint32_t hart_id = 0; uint32_t return_hart_id = UNDEFINED_HART_ID; @@ -262,6 +277,13 @@ static uint32_t mpfs_ihc_parse_incoming_hartid(uint32_t mhartid, { return_hart_id = hart_id; *is_ack = true; + + test_int = (1 << (hart_id * 2)); + + if ((g_connected_hart_ints & test_int) == test_int) + { + *is_msg = true; + } break; } } @@ -273,7 +295,7 @@ static uint32_t mpfs_ihc_parse_incoming_hartid(uint32_t mhartid, if (((g_connected_hart_ints & test_int) == test_int)) { return_hart_id = hart_id; - *is_ack = false; + *is_msg = true; break; } } @@ -423,13 +445,14 @@ static uint32_t mpfs_ihc_context_to_local_hart_id(ihc_channel_t channel) * Input Parameters: * message - Pointer to the incoming message * is_ack - Boolean indicating whether an ack is received + * is_msg - Boolean indicating message presence * * Returned Value: * None * ****************************************************************************/ -static void mpfs_ihc_rx_handler(uint32_t *message, bool is_ack) +static void mpfs_ihc_rx_handler(uint32_t *message, bool is_ack, bool is_msg) { if (is_ack) { @@ -437,7 +460,8 @@ static void mpfs_ihc_rx_handler(uint32_t *message, bool is_ack) nxsem_post(&g_mpfs_ack_sig); } - else + + if (is_msg) { g_vq_idx = message[0]; @@ -448,6 +472,42 @@ static void mpfs_ihc_rx_handler(uint32_t *message, bool is_ack) } } +/**************************************************************************** + * Name: mpfs_ihc_worker + * + * Description: + * This function is used to wait for the remote message present condition, + * after which the ACK is sent. ACK wasn't sent before, as the remote end + * has no way of knowing which one came first: the ACK or RMP. + * + * Input Parameters: + * arg - Pointer to the arguments struct + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef IHC_AVOID_ACK_AND_MP +static void mpfs_ihc_worker(void *arg) +{ + uint32_t ctrl_reg; + uint32_t retries = 5000; + + do + { + ctrl_reg = getreg32(MPFS_IHC_CTRL(g_work_arg.mhartid, + g_work_arg.rhartid)); + } + while ((ctrl_reg & (RMP_MESSAGE_PRESENT)) && --retries); + + DEBUGASSERT(retries != 0); + + modifyreg32(MPFS_IHC_CTRL(g_work_arg.mhartid, + g_work_arg.rhartid), 0, ACK_INT); +} +#endif + /**************************************************************************** * Name: mpfs_ihc_rx_message * @@ -460,6 +520,7 @@ static void mpfs_ihc_rx_handler(uint32_t *message, bool is_ack) * mhartid - Context hart id, not necessarily the absolute mhartid but * rather, the primary hartid of the set of harts. * is_ack - Boolean indicating an ack message + * is_msg - Boolean indicating message presence * msg - For storing data, could be NULL * * Returned Value: @@ -468,18 +529,18 @@ static void mpfs_ihc_rx_handler(uint32_t *message, bool is_ack) ****************************************************************************/ static void mpfs_ihc_rx_message(ihc_channel_t channel, uint32_t mhartid, - bool is_ack, uint32_t *msg) + bool is_ack, bool is_msg, uint32_t *msg) { uint32_t rhartid = mpfs_ihc_context_to_remote_hart_id(channel); uint32_t ctrl_reg = getreg32(MPFS_IHC_CTRL(mhartid, rhartid)); - if (is_ack) + if (is_ack && !is_msg) { if (mhartid == CONTEXTB_HARTID) { uintptr_t msg_in = MPFS_IHC_MSG_IN(mhartid, rhartid); DEBUGASSERT(msg == NULL); - mpfs_ihc_rx_handler((uint32_t *)msg_in, is_ack); + mpfs_ihc_rx_handler((uint32_t *)msg_in, is_ack, is_msg); } else { @@ -488,7 +549,7 @@ static void mpfs_ihc_rx_message(ihc_channel_t channel, uint32_t mhartid, DEBUGPANIC(); } } - else if (MP_MESSAGE_PRESENT == (ctrl_reg & MP_MASK)) + else if (is_msg) { /* Check if we have a message */ @@ -496,7 +557,7 @@ static void mpfs_ihc_rx_message(ihc_channel_t channel, uint32_t mhartid, { uintptr_t msg_in = MPFS_IHC_MSG_IN(mhartid, rhartid); DEBUGASSERT(msg == NULL); - mpfs_ihc_rx_handler((uint32_t *)msg_in, is_ack); + mpfs_ihc_rx_handler((uint32_t *)msg_in, is_ack, is_msg); } else { @@ -509,17 +570,31 @@ static void mpfs_ihc_rx_message(ihc_channel_t channel, uint32_t mhartid, * if it has RMPIE bit set in the control register */ - volatile uint32_t temp = getreg32(MPFS_IHC_CTRL(mhartid, rhartid)) & - ~MP_MASK; - - /* Check if ACKIE_EN is set */ - - if (temp & ACKIE_EN) + ctrl_reg = getreg32(MPFS_IHC_CTRL(mhartid, rhartid)); + if (ctrl_reg & RMP_MESSAGE_PRESENT) { - temp |= ACK_INT; + /* If we send the ACK here, Linux will have the ACK and the + * MP flags sets. IHC_AVOID_ACK_AND_MP assures only one + * is present at once. + */ + +#ifdef IHC_AVOID_ACK_AND_MP + g_work_arg.mhartid = mhartid; + g_work_arg.rhartid = rhartid; + modifyreg32(MPFS_IHC_CTRL(mhartid, rhartid), MP_MASK, 0); + work_queue(HPWORK, &g_ihc_work, mpfs_ihc_worker, NULL, 0); +#else + modifyreg32(MPFS_IHC_CTRL(mhartid, rhartid), MP_MASK, 0); + modifyreg32(MPFS_IHC_CTRL(mhartid, rhartid), 0, ACK_INT); +#endif } + else + { + /* We can send the ACK now and clear the MP */ - putreg32(temp, MPFS_IHC_CTRL(mhartid, rhartid)); + modifyreg32(MPFS_IHC_CTRL(mhartid, rhartid), MP_MASK, 0); + modifyreg32(MPFS_IHC_CTRL(mhartid, rhartid), 0, ACK_INT); + } } } @@ -541,11 +616,13 @@ static void mpfs_ihc_rx_message(ihc_channel_t channel, uint32_t mhartid, static void mpfs_ihc_message_present_isr(void) { uint64_t mhartid = riscv_mhartid(); - bool is_ack; + bool is_ack = false; + bool is_msg = false; /* Check all our channels */ - uint32_t origin_hart = mpfs_ihc_parse_incoming_hartid(mhartid, &is_ack); + uint32_t origin_hart = mpfs_ihc_parse_incoming_hartid(mhartid, &is_ack, + &is_msg); if (origin_hart != UNDEFINED_HART_ID) { @@ -564,7 +641,9 @@ static void mpfs_ihc_message_present_isr(void) /* Process incoming packet */ - mpfs_ihc_rx_message(origin_hart, mhartid, is_ack, NULL); + irqstate_t flags = spin_lock_irqsave(NULL); + + mpfs_ihc_rx_message(origin_hart, mhartid, is_ack, is_msg, NULL); if (is_ack) { @@ -573,6 +652,8 @@ static void mpfs_ihc_message_present_isr(void) modifyreg32(MPFS_IHC_CTRL(mhartid, origin_hart), ACK_CLR, 0); } + + spin_unlock_irqrestore(NULL, flags); } } @@ -662,6 +743,10 @@ static void mpfs_ihc_local_remote_config(uint32_t hart_to_configure, putreg32(ihcia_remote_hart_ints[hart_to_configure], MPFS_IHC_INT_EN(hart_to_configure)); + /* This register INT_EN(0) is used for flow control only */ + + putreg32(0, MPFS_IHC_INT_EN(0)); + modifyreg32(MPFS_IHC_CTRL(hart_to_configure, rhartid), 0, MPIE_EN | ACKIE_EN); } @@ -689,6 +774,7 @@ static int mpfs_ihc_tx_message(ihc_channel_t channel, uint32_t *message) uint32_t message_size = getreg32(MPFS_IHC_MSG_SIZE(mhartid, rhartid)); uint32_t ctrl_reg; uint32_t retries = 10000; + irqstate_t flags; DEBUGASSERT(message_size <= IHC_MAX_MESSAGE_SIZE); @@ -712,6 +798,8 @@ static int mpfs_ihc_tx_message(ihc_channel_t channel, uint32_t *message) } else { + flags = spin_lock_irqsave(NULL); + /* Fill the buffer */ for (i = 0; i < message_size; i++) @@ -719,17 +807,33 @@ static int mpfs_ihc_tx_message(ihc_channel_t channel, uint32_t *message) putreg32(message[i], MPFS_IHC_MSG_OUT(mhartid, rhartid) + i * 4); } + ctrl_reg = getreg32(MPFS_IHC_CTRL(mhartid, rhartid)); + + /* If we're unlucky, we cannot send MP yet.. come back later */ + + if (ctrl_reg & (ACK_INT | MP_MESSAGE_PRESENT)) + { + spin_unlock_irqrestore(NULL, flags); + return -EBUSY; + } + /* Set the MP bit. This will notify other of incoming hart message */ modifyreg32(MPFS_IHC_CTRL(mhartid, rhartid), 0, RMP_MESSAGE_PRESENT); + spin_unlock_irqrestore(NULL, flags); + /* Wait for the ACK to arrive to maintain the logic */ if (mhartid == CONTEXTB_HARTID) { - /* Only applicable for the CONTEXTB_HART */ + /* With some probability, an ACK is lost. Only wait for some + * descent amount of time and continue. Otherwise, this will + * hang and never proceed. + */ - nxsem_wait_uninterruptible(&g_mpfs_ack_sig); + nxsem_tickwait_uninterruptible(&g_mpfs_ack_sig, + MSEC2TICK(10)); } } @@ -846,12 +950,10 @@ mpfs_rptun_get_resource(struct rptun_dev_s *dev) rsc->rpmsg_vdev.id = VIRTIO_ID_RPMSG; rsc->rpmsg_vdev.notifyid = VDEV_NOTIFYID; rsc->rpmsg_vdev.dfeatures = 1 << VIRTIO_RPMSG_F_NS | - 1 << VIRTIO_RPMSG_F_ACK | - VIRTIO_RING_F_EVENT_IDX; + 1 << VIRTIO_RPMSG_F_ACK; rsc->rpmsg_vdev.gfeatures = 1 << VIRTIO_RPMSG_F_NS | - 1 << VIRTIO_RPMSG_F_ACK | - VIRTIO_RING_F_EVENT_IDX; + 1 << VIRTIO_RPMSG_F_ACK; /* Set to VIRTIO_CONFIG_STATUS_DRIVER_OK when master is up */ @@ -980,6 +1082,24 @@ static int mpfs_rptun_stop(struct rptun_dev_s *dev) static int mpfs_rptun_notify(struct rptun_dev_s *dev, uint32_t notifyid) { uint32_t tx_msg[IHC_MAX_MESSAGE_SIZE]; + uint32_t retries = 10000; + uint32_t flow_ctrl_en; + int ret = OK; + + /* INT_EN(0) is used by the bootloader (Linux) to indicate that + * it will be sending data. Wait until it finishes first. + */ + + flow_ctrl_en = getreg32(MPFS_IHC_INT_EN(0)); + + if (flow_ctrl_en != 0) + { + do + { + flow_ctrl_en = getreg32(MPFS_IHC_INT_EN(0)); + } + while ((flow_ctrl_en != 0) && --retries); + } /* We only care about the queue with notifyid VRING0 */ @@ -988,10 +1108,24 @@ static int mpfs_rptun_notify(struct rptun_dev_s *dev, uint32_t notifyid) tx_msg[0] = notifyid; tx_msg[1] = 0; - return mpfs_ihc_tx_message(CONTEXTA_HARTID, tx_msg); + ret = mpfs_ihc_tx_message(CONTEXTA_HARTID, tx_msg); + if (ret != OK) + { + retries = 5; + + /* This failure should happen very rarely */ + + do + { + ret = mpfs_ihc_tx_message(CONTEXTA_HARTID, tx_msg); + } + while ((ret != OK) && --retries); + + DEBUGASSERT(ret == OK); + } } - return OK; + return ret; } /**************************************************************************** From 69a3ed741bd2d0046e9dd607c2f9087d5c6e4e7e Mon Sep 17 00:00:00 2001 From: Eero Nurkkala Date: Mon, 17 Apr 2023 11:49:35 +0300 Subject: [PATCH 41/79] risc-v/mpfs: ihc: use work queue instead of thread The thread conflicts with a HPWORK originated network operation, taking the net_lock() recursive mutex, resulting in a deadlock. Recursive mutexes are OK within the same task (HPWORK), so apply the thread work into a work instead, which would potentially resolve the very random conflict. This increases the data throughput also a bit (10 - 20%). Signed-off-by: Eero Nurkkala --- arch/risc-v/src/mpfs/mpfs_ihc.c | 45 +++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/arch/risc-v/src/mpfs/mpfs_ihc.c b/arch/risc-v/src/mpfs/mpfs_ihc.c index cb4f530ddb96a..aa34f1d603b4c 100644 --- a/arch/risc-v/src/mpfs/mpfs_ihc.c +++ b/arch/risc-v/src/mpfs/mpfs_ihc.c @@ -163,6 +163,7 @@ static int mpfs_rptun_notify(struct rptun_dev_s *dev, uint32_t notifyid); static int mpfs_rptun_register_callback(struct rptun_dev_s *dev, rptun_callback_t callback, void *arg); +static void mpfs_rptun_worker(void *arg); /**************************************************************************** * Private Data @@ -188,7 +189,11 @@ static struct rpmsg_device *g_mpfs_rpmsg_device; static struct rpmsg_virtio_device *g_mpfs_virtio_device; static sem_t g_mpfs_ack_sig = SEM_INITIALIZER(0); +#ifdef MPFS_RPTUN_USE_THREAD static sem_t g_mpfs_rx_sig = SEM_INITIALIZER(0); +#else +static struct work_s g_rptun_work; +#endif static struct list_node g_dev_list = LIST_INITIAL_VALUE(g_dev_list); static uint32_t g_connected_hart_ints; @@ -468,7 +473,11 @@ static void mpfs_ihc_rx_handler(uint32_t *message, bool is_ack, bool is_msg) DEBUGASSERT((g_vq_idx == VRING0_NOTIFYID) || (g_vq_idx == VRING1_NOTIFYID)); +#ifdef MPFS_RPTUN_USE_THREAD nxsem_post(&g_mpfs_rx_sig); +#else + work_queue(HPWORK, &g_rptun_work, mpfs_rptun_worker, NULL, 0); +#endif } } @@ -1287,6 +1296,33 @@ static void mpfs_rpmsg_device_created(struct rpmsg_device *rdev, void *priv_) mpfs_echo_ping_init(rdev, &g_mpgs_echo_ping_ept); } +/**************************************************************************** + * Name: mpfs_rptun_worker + * + * Description: + * This is used to notify the associated virtqueue via the scheduled work. + * This doesn't use a separate thread, but a HPWORK instead, which is a + * way to avoid deadlocks with net_lock() that also originate from HPWORK. + * + * Input Parameters: + * arg - Argument + + * Returned Value: + * None + * + ****************************************************************************/ + +#ifndef MPFS_RPTUN_USE_THREAD +static void mpfs_rptun_worker(void *arg) +{ + struct mpfs_queue_table_s *info; + + DEBUGASSERT((g_vq_idx - VRING0_NOTIFYID) < VRINGS); + info = &g_mpfs_virtqueue_table[g_vq_idx - VRING0_NOTIFYID]; + virtqueue_notification((struct virtqueue *)info->data); +} +#endif + /**************************************************************************** * Name: mpfs_rptun_thread * @@ -1304,6 +1340,7 @@ static void mpfs_rpmsg_device_created(struct rpmsg_device *rdev, void *priv_) * ****************************************************************************/ +#ifdef MPFS_RPTUN_USE_THREAD static int mpfs_rptun_thread(int argc, char *argv[]) { struct mpfs_queue_table_s *info; @@ -1319,6 +1356,7 @@ static int mpfs_rptun_thread(int argc, char *argv[]) return 0; } +#endif /**************************************************************************** * Public Functions @@ -1344,8 +1382,10 @@ static int mpfs_rptun_thread(int argc, char *argv[]) int mpfs_ihc_init(void) { uint32_t mhartid = (uint32_t)riscv_mhartid(); +#ifdef MPFS_RPTUN_USE_THREAD char *argv[3]; char arg1[19]; +#endif uint32_t rhartid; int ret; @@ -1409,6 +1449,8 @@ int mpfs_ihc_init(void) goto init_error; } +#ifdef MPFS_RPTUN_USE_THREAD + /* Thread initialization */ snprintf(arg1, sizeof(arg1), "%p", @@ -1426,6 +1468,9 @@ int mpfs_ihc_init(void) NULL, NULL, NULL); goto init_error; } +#else + +#endif return OK; From 9049acbfd1363c98b9b8b3d4467f60a1bb1a148e Mon Sep 17 00:00:00 2001 From: haitomatic Date: Thu, 27 Apr 2023 12:22:25 +0000 Subject: [PATCH 42/79] canfd: fix hw filter --- arch/risc-v/src/mpfs/mpfs_fpga_canfd.c | 37 ++++++++++++++++++++------ 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c b/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c index 7fa4996cfe697..efe6f2f094e54 100644 --- a/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c +++ b/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c @@ -2049,6 +2049,27 @@ static void mpfs_can_add_hw_filter(struct mpfs_driver_s *priv, fc_reg = getreg32(priv->base + MPFS_CANFD_FILTER_CONTROL_OFFSET); + /* Clean up filter control reg */ + + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FAFE; + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FAFB; + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FANE; + fc_reg &= ~MPFS_CANFD_FILTER_CONTROL_FANB; + + /* Transform fid1, fid2 */ + + uint32_t fid1_trans = (can_id_type == CAN_EXT_ID) ? + (MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_EXT & + (fid1 << MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_EXT_SHIFT)) : + (MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_BASE & + (fid1 << MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_BASE_SHIFT)); + + uint32_t fid2_trans = (can_id_type == CAN_EXT_ID) ? + (MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_EXT & + (fid2 << MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_EXT_SHIFT)) : + (MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_BASE & + (fid2 << MPFS_CANFD_IDENTIFIER_W_IDENTIFIER_BASE_SHIFT)); + switch (filter_type) { case HW_FILTER_A: @@ -2081,8 +2102,8 @@ static void mpfs_can_add_hw_filter(struct mpfs_driver_s *priv, /* Set bit filter value / mask */ - putreg32(fid1, priv->base + MPFS_CANFD_FILTER_A_VAL_OFFSET); - putreg32(fid2, priv->base + MPFS_CANFD_FILTER_A_MASK_OFFSET); + putreg32(fid1_trans, priv->base + MPFS_CANFD_FILTER_A_VAL_OFFSET); + putreg32(fid2_trans, priv->base + MPFS_CANFD_FILTER_A_MASK_OFFSET); break; case HW_FILTER_B: @@ -2115,8 +2136,8 @@ static void mpfs_can_add_hw_filter(struct mpfs_driver_s *priv, /* Set bit filter value / mask */ - putreg32(fid1, priv->base + MPFS_CANFD_FILTER_B_VAL_OFFSET); - putreg32(fid2, priv->base + MPFS_CANFD_FILTER_B_MASK_OFFSET); + putreg32(fid1_trans, priv->base + MPFS_CANFD_FILTER_B_VAL_OFFSET); + putreg32(fid2_trans, priv->base + MPFS_CANFD_FILTER_B_MASK_OFFSET); break; case HW_FILTER_C: @@ -2149,8 +2170,8 @@ static void mpfs_can_add_hw_filter(struct mpfs_driver_s *priv, /* Set bit filter value / mask */ - putreg32(fid1, priv->base + MPFS_CANFD_FILTER_C_VAL_OFFSET); - putreg32(fid2, priv->base + MPFS_CANFD_FILTER_C_MASK_OFFSET); + putreg32(fid1_trans, priv->base + MPFS_CANFD_FILTER_C_VAL_OFFSET); + putreg32(fid2_trans, priv->base + MPFS_CANFD_FILTER_C_MASK_OFFSET); break; case HW_FILTER_RANGE: @@ -2183,8 +2204,8 @@ static void mpfs_can_add_hw_filter(struct mpfs_driver_s *priv, /* Set range filter low / high */ - putreg32(fid1, priv->base + MPFS_CANFD_FILTER_RAN_LOW_OFFSET); - putreg32(fid2, priv->base + MPFS_CANFD_FILTER_RAN_HIGH_OFFSET); + putreg32(fid1_trans, priv->base + MPFS_CANFD_FILTER_RAN_LOW_OFFSET); + putreg32(fid2_trans, priv->base + MPFS_CANFD_FILTER_RAN_HIGH_OFFSET); break; default: From 4b40846ddc0b7d8d6c60ce8ba6a9449096c41d51 Mon Sep 17 00:00:00 2001 From: Eero Nurkkala Date: Tue, 9 May 2023 16:35:12 +0300 Subject: [PATCH 43/79] risc-v/mpfs: serial: add fpga uarts Add FPGA serial support, including console capabilities. FPGA has UARTs from 0-7, so all UARTs starting from 5 depend on FPGA. Signed-off-by: Eero Nurkkala --- arch/risc-v/src/mpfs/Kconfig | 51 +++ .../risc-v/src/mpfs/hardware/mpfs_memorymap.h | 11 + arch/risc-v/src/mpfs/mpfs_config.h | 45 ++- arch/risc-v/src/mpfs/mpfs_lowputc.c | 117 +++++- arch/risc-v/src/mpfs/mpfs_serial.c | 355 +++++++++++++++++- 5 files changed, 562 insertions(+), 17 deletions(-) diff --git a/arch/risc-v/src/mpfs/Kconfig b/arch/risc-v/src/mpfs/Kconfig index 825f60c95ea2d..8b85e8e0dcd3b 100644 --- a/arch/risc-v/src/mpfs/Kconfig +++ b/arch/risc-v/src/mpfs/Kconfig @@ -243,6 +243,27 @@ config MPFS_HAVE_UART4 select UART4_SERIALDRIVER select ARCH_HAVE_SERIAL_TERMIOS +config MPFS_HAVE_UART5 + bool + depends on MPFS_FPGA_UART + default n + select UART5_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS + +config MPFS_HAVE_UART6 + bool + depends on MPFS_FPGA_UART + default n + select UART6_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS + +config MPFS_HAVE_UART7 + bool + depends on MPFS_FPGA_UART + default n + select UART7_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS + # These are the peripheral selections proper config MPFS_SPI0 @@ -253,6 +274,12 @@ config MPFS_SPI1 bool "SPI 1" default n +config MPFS_FPGA_UART + bool "FPGA uarts" + default n + ---help--- + Use FPGA UARTs instead of MSS UARTS. + config MPFS_UART0 bool "UART 0" default n @@ -288,6 +315,30 @@ config MPFS_UART4 select ARCH_HAVE_SERIAL_TERMIOS select MPFS_HAVE_UART4 +config MPFS_UART5 + bool "UART 5" + depends on MPFS_FPGA_UART + default n + select ARCH_HAVE_UART5 + select ARCH_HAVE_SERIAL_TERMIOS + select MPFS_HAVE_UART5 + +config MPFS_UART6 + bool "UART 6" + depends on MPFS_FPGA_UART + default n + select ARCH_HAVE_UART6 + select ARCH_HAVE_SERIAL_TERMIOS + select MPFS_HAVE_UART6 + +config MPFS_UART7 + bool "UART 7" + depends on MPFS_FPGA_UART + default n + select ARCH_HAVE_UART7 + select ARCH_HAVE_SERIAL_TERMIOS + select MPFS_HAVE_UART7 + config MPFS_I2C0 bool "I2C 0" select ARCH_HAVE_I2CRESET diff --git a/arch/risc-v/src/mpfs/hardware/mpfs_memorymap.h b/arch/risc-v/src/mpfs/hardware/mpfs_memorymap.h index 5d93013734d19..cbc55d9f18011 100644 --- a/arch/risc-v/src/mpfs/hardware/mpfs_memorymap.h +++ b/arch/risc-v/src/mpfs/hardware/mpfs_memorymap.h @@ -130,4 +130,15 @@ #define MPFS_UART3_BASE MPFS_UART3_LO_BASE #define MPFS_UART4_BASE MPFS_UART4_LO_BASE +/* FPGA UART defines */ + +#define MPFS_FPGA_UART0_BASE 0x4c000000UL +#define MPFS_FPGA_UART1_BASE 0x4c000100UL +#define MPFS_FPGA_UART2_BASE 0x4c000200UL +#define MPFS_FPGA_UART3_BASE 0x4c000300UL +#define MPFS_FPGA_UART4_BASE 0x4c000400UL +#define MPFS_FPGA_UART5_BASE 0x4c000500UL +#define MPFS_FPGA_UART6_BASE 0x4c000600UL +#define MPFS_FPGA_UART7_BASE 0x4c000700UL + #endif /* __ARCH_RISCV_SRC_MPFS_HARDWARE_MPFS_MEMORYMAP_H */ diff --git a/arch/risc-v/src/mpfs/mpfs_config.h b/arch/risc-v/src/mpfs/mpfs_config.h index ce2007d599822..896036b5c6ac9 100644 --- a/arch/risc-v/src/mpfs/mpfs_config.h +++ b/arch/risc-v/src/mpfs/mpfs_config.h @@ -37,7 +37,8 @@ #undef HAVE_UART_DEVICE #if defined(CONFIG_MPFS_UART0) || defined(CONFIG_MPFS_UART1) || \ defined(CONFIG_MPFS_UART2) || defined(CONFIG_MPFS_UART3) || \ - defined(CONFIG_MPFS_UART4) + defined(CONFIG_MPFS_UART4) || defined(CONFIG_MPFS_UART5) || \ + defined(CONFIG_MPFS_UART6) || defined(CONFIG_MPFS_UART7) # define HAVE_UART_DEVICE 1 #endif @@ -46,30 +47,72 @@ # undef CONFIG_UART2_SERIAL_CONSOLE # undef CONFIG_UART3_SERIAL_CONSOLE # undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_UART5_SERIAL_CONSOLE +# undef CONFIG_UART6_SERIAL_CONSOLE +# undef CONFIG_UART7_SERIAL_CONSOLE # define HAVE_SERIAL_CONSOLE 1 #elif defined(CONFIG_UART1_SERIAL_CONSOLE) && defined(CONFIG_MPFS_UART1) # undef CONFIG_UART0_SERIAL_CONSOLE # undef CONFIG_UART2_SERIAL_CONSOLE # undef CONFIG_UART3_SERIAL_CONSOLE # undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_UART5_SERIAL_CONSOLE +# undef CONFIG_UART6_SERIAL_CONSOLE +# undef CONFIG_UART7_SERIAL_CONSOLE # define HAVE_SERIAL_CONSOLE 1 #elif defined(CONFIG_UART2_SERIAL_CONSOLE) && defined(CONFIG_MPFS_UART2) # undef CONFIG_UART0_SERIAL_CONSOLE # undef CONFIG_UART1_SERIAL_CONSOLE # undef CONFIG_UART3_SERIAL_CONSOLE # undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_UART5_SERIAL_CONSOLE +# undef CONFIG_UART6_SERIAL_CONSOLE +# undef CONFIG_UART7_SERIAL_CONSOLE # define HAVE_SERIAL_CONSOLE 1 #elif defined(CONFIG_UART3_SERIAL_CONSOLE) && defined(CONFIG_MPFS_UART3) # undef CONFIG_UART0_SERIAL_CONSOLE # undef CONFIG_UART1_SERIAL_CONSOLE # undef CONFIG_UART2_SERIAL_CONSOLE # undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_UART5_SERIAL_CONSOLE +# undef CONFIG_UART6_SERIAL_CONSOLE +# undef CONFIG_UART7_SERIAL_CONSOLE # define HAVE_SERIAL_CONSOLE 1 #elif defined(CONFIG_UART4_SERIAL_CONSOLE) && defined(CONFIG_MPFS_UART4) # undef CONFIG_UART0_SERIAL_CONSOLE # undef CONFIG_UART1_SERIAL_CONSOLE # undef CONFIG_UART2_SERIAL_CONSOLE # undef CONFIG_UART3_SERIAL_CONSOLE +# undef CONFIG_UART5_SERIAL_CONSOLE +# undef CONFIG_UART6_SERIAL_CONSOLE +# undef CONFIG_UART7_SERIAL_CONSOLE +# define HAVE_SERIAL_CONSOLE 1 +#elif defined(CONFIG_UART5_SERIAL_CONSOLE) && defined(CONFIG_MPFS_UART5) +# undef CONFIG_UART0_SERIAL_CONSOLE +# undef CONFIG_UART1_SERIAL_CONSOLE +# undef CONFIG_UART2_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_UART6_SERIAL_CONSOLE +# undef CONFIG_UART7_SERIAL_CONSOLE +# define HAVE_SERIAL_CONSOLE 1 +#elif defined(CONFIG_UART6_SERIAL_CONSOLE) && defined(CONFIG_MPFS_UART6) +# undef CONFIG_UART0_SERIAL_CONSOLE +# undef CONFIG_UART1_SERIAL_CONSOLE +# undef CONFIG_UART2_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_UART5_SERIAL_CONSOLE +# undef CONFIG_UART7_SERIAL_CONSOLE +# define HAVE_SERIAL_CONSOLE 1 +#elif defined(CONFIG_UART7_SERIAL_CONSOLE) && defined(CONFIG_MPFS_UART7) +# undef CONFIG_UART0_SERIAL_CONSOLE +# undef CONFIG_UART1_SERIAL_CONSOLE +# undef CONFIG_UART2_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_UART5_SERIAL_CONSOLE +# undef CONFIG_UART6_SERIAL_CONSOLE # define HAVE_SERIAL_CONSOLE 1 #else # undef CONFIG_UART0_SERIAL_CONSOLE diff --git a/arch/risc-v/src/mpfs/mpfs_lowputc.c b/arch/risc-v/src/mpfs/mpfs_lowputc.c index 93dede2fd4ad0..8daa7d6b82f3c 100644 --- a/arch/risc-v/src/mpfs/mpfs_lowputc.c +++ b/arch/risc-v/src/mpfs/mpfs_lowputc.c @@ -40,6 +40,8 @@ ****************************************************************************/ /* Select UART parameters for the selected console */ + +#ifndef CONFIG_MPFS_FPGA_UART #if defined(CONFIG_UART0_SERIAL_CONSOLE) # define MPFS_CONSOLE_BASE MPFS_UART0_BASE # define MPFS_CONSOLE_BAUD CONFIG_UART0_BAUD @@ -89,6 +91,93 @@ # error "No CONFIG_UARTn_SERIAL_CONSOLE Setting" # endif +#else /* CONFIG_MPFS_FPGA_UART */ + +#if defined(CONFIG_UART0_SERIAL_CONSOLE) +# define MPFS_CONSOLE_BASE MPFS_FPGA_UART0_BASE +# define MPFS_CONSOLE_BAUD CONFIG_UART0_BAUD +# define MPFS_CONSOLE_BITS CONFIG_UART0_BITS +# define MPFS_CONSOLE_PARITY CONFIG_UART0_PARITY +# define MPFS_CONSOLE_2STOP CONFIG_UART0_2STOP +# define MPFS_CONSOLE_CLOCKBIT SYSREG_SUBBLK_CLOCK_CR_FIC3 +# define MPFS_CONSOLE_RESETBIT SYSREG_SOFT_RESET_CR_FIC3 | \ + SYSREG_SOFT_RESET_CR_FPGA +# define HAVE_UART +#elif defined(CONFIG_UART1_SERIAL_CONSOLE) +# define MPFS_CONSOLE_BASE MPFS_FPGA_UART1_BASE +# define MPFS_CONSOLE_BAUD CONFIG_UART1_BAUD +# define MPFS_CONSOLE_BITS CONFIG_UART1_BITS +# define MPFS_CONSOLE_PARITY CONFIG_UART1_PARITY +# define MPFS_CONSOLE_2STOP CONFIG_UART1_2STOP +# define MPFS_CONSOLE_CLOCKBIT SYSREG_SUBBLK_CLOCK_CR_FIC3 +# define MPFS_CONSOLE_RESETBIT SYSREG_SOFT_RESET_CR_FIC3 | \ + SYSREG_SOFT_RESET_CR_FPGA +# define HAVE_UART +#elif defined(CONFIG_UART2_SERIAL_CONSOLE) +# define MPFS_CONSOLE_BASE MPFS_FPGA_UART2_BASE +# define MPFS_CONSOLE_BAUD CONFIG_UART2_BAUD +# define MPFS_CONSOLE_BITS CONFIG_UART2_BITS +# define MPFS_CONSOLE_PARITY CONFIG_UART2_PARITY +# define MPFS_CONSOLE_2STOP CONFIG_UART2_2STOP +# define MPFS_CONSOLE_CLOCKBIT SYSREG_SUBBLK_CLOCK_CR_FIC3 +# define MPFS_CONSOLE_RESETBIT SYSREG_SOFT_RESET_CR_FIC3 | \ + SYSREG_SOFT_RESET_CR_FPGA +# define HAVE_UART +# elif defined(CONFIG_UART3_SERIAL_CONSOLE) +# define MPFS_CONSOLE_BASE MPFS_FPGA_UART3_BASE +# define MPFS_CONSOLE_BAUD CONFIG_UART3_BAUD +# define MPFS_CONSOLE_BITS CONFIG_UART3_BITS +# define MPFS_CONSOLE_PARITY CONFIG_UART3_PARITY +# define MPFS_CONSOLE_2STOP CONFIG_UART3_2STOP +# define MPFS_CONSOLE_CLOCKBIT SYSREG_SUBBLK_CLOCK_CR_FIC3 +# define MPFS_CONSOLE_RESETBIT SYSREG_SOFT_RESET_CR_FIC3 | \ + SYSREG_SOFT_RESET_CR_FPGA +# define HAVE_UART +#elif defined(CONFIG_UART4_SERIAL_CONSOLE) +# define MPFS_CONSOLE_BASE MPFS_FPGA_UART4_BASE +# define MPFS_CONSOLE_BAUD CONFIG_UART4_BAUD +# define MPFS_CONSOLE_BITS CONFIG_UART4_BITS +# define MPFS_CONSOLE_PARITY CONFIG_UART4_PARITY +# define MPFS_CONSOLE_2STOP CONFIG_UART4_2STOP +# define MPFS_CONSOLE_CLOCKBIT SYSREG_SUBBLK_CLOCK_CR_FIC3 +# define MPFS_CONSOLE_RESETBIT SYSREG_SOFT_RESET_CR_FIC3 | \ + SYSREG_SOFT_RESET_CR_FPGA +# define HAVE_UART +#elif defined(CONFIG_UART5_SERIAL_CONSOLE) +# define MPFS_CONSOLE_BASE MPFS_FPGA_UART5_BASE +# define MPFS_CONSOLE_BAUD CONFIG_UART5_BAUD +# define MPFS_CONSOLE_BITS CONFIG_UART5_BITS +# define MPFS_CONSOLE_PARITY CONFIG_UART5_PARITY +# define MPFS_CONSOLE_2STOP CONFIG_UART5_2STOP +# define MPFS_CONSOLE_CLOCKBIT SYSREG_SUBBLK_CLOCK_CR_FIC3 +# define MPFS_CONSOLE_RESETBIT SYSREG_SOFT_RESET_CR_FIC3 | \ + SYSREG_SOFT_RESET_CR_FPGA +# define HAVE_UART +#elif defined(CONFIG_UART6_SERIAL_CONSOLE) +# define MPFS_CONSOLE_BASE MPFS_FPGA_UART6_BASE +# define MPFS_CONSOLE_BAUD CONFIG_UART6_BAUD +# define MPFS_CONSOLE_BITS CONFIG_UART6_BITS +# define MPFS_CONSOLE_PARITY CONFIG_UART6_PARITY +# define MPFS_CONSOLE_2STOP CONFIG_UART6_2STOP +# define MPFS_CONSOLE_CLOCKBIT SYSREG_SUBBLK_CLOCK_CR_FIC3 +# define MPFS_CONSOLE_RESETBIT SYSREG_SOFT_RESET_CR_FIC3 | \ + SYSREG_SOFT_RESET_CR_FPGA +# define HAVE_UART +#elif defined(CONFIG_UART7_SERIAL_CONSOLE) +# define MPFS_CONSOLE_BASE MPFS_FPGA_UART7_BASE +# define MPFS_CONSOLE_BAUD CONFIG_UART7_BAUD +# define MPFS_CONSOLE_BITS CONFIG_UART7_BITS +# define MPFS_CONSOLE_PARITY CONFIG_UART7_PARITY +# define MPFS_CONSOLE_2STOP CONFIG_UART7_2STOP +# define MPFS_CONSOLE_CLOCKBIT SYSREG_SUBBLK_CLOCK_CR_FIC3 +# define MPFS_CONSOLE_RESETBIT SYSREG_SOFT_RESET_CR_FIC3 | \ + SYSREG_SOFT_RESET_CR_FPGA +# define HAVE_UART +#elif defined(HAVE_UART) +# error "No CONFIG_UARTn_SERIAL_CONSOLE Setting" +#endif +#endif /* CONFIG_MPFS_FPGA_UART */ + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -111,7 +200,16 @@ static void config_baud_divisors(void) uint32_t fractional_baud_value; uint64_t pclk_freq; - pclk_freq = MPFS_MSS_APB_AHB_CLK; + if (MPFS_CONSOLE_CLOCKBIT == SYSREG_SUBBLK_CLOCK_CR_FIC3) + { + /* This is an FPGA UART */ + + pclk_freq = MPFS_FPGA_PERIPHERAL_CLK; + } + else + { + pclk_freq = MPFS_MSS_APB_AHB_CLK; + } /* Compute baud value based on requested baud rate and PCLK frequency. * The baud value is computed using the following equation: @@ -189,20 +287,23 @@ void mpfs_lowsetup(void) #if defined(HAVE_SERIAL_CONSOLE) && !defined(CONFIG_SUPPRESS_UART_CONFIG) uint32_t lcr = 0; - /* reset on */ + /* reset on - only for non-FPGA uarts */ - modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SOFT_RESET_CR_OFFSET, - 0, MPFS_CONSOLE_RESETBIT); + if (SYSREG_SUBBLK_CLOCK_CR_FIC3 != MPFS_CONSOLE_CLOCKBIT) + { + modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SOFT_RESET_CR_OFFSET, 0, + MPFS_CONSOLE_RESETBIT); + } /* reset off */ - modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SUBBLK_CLOCK_CR_OFFSET, - 0, MPFS_CONSOLE_CLOCKBIT); + modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SOFT_RESET_CR_OFFSET, + MPFS_CONSOLE_RESETBIT, 0); /* clock on */ - modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SOFT_RESET_CR_OFFSET, - MPFS_CONSOLE_RESETBIT, 0); + modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SUBBLK_CLOCK_CR_OFFSET, + 0, MPFS_CONSOLE_CLOCKBIT); switch (MPFS_CONSOLE_BITS) { diff --git a/arch/risc-v/src/mpfs/mpfs_serial.c b/arch/risc-v/src/mpfs/mpfs_serial.c index ec9ab908cf712..64dcfee59620c 100644 --- a/arch/risc-v/src/mpfs/mpfs_serial.c +++ b/arch/risc-v/src/mpfs/mpfs_serial.c @@ -80,6 +80,15 @@ # elif defined(CONFIG_UART4_SERIAL_CONSOLE) # define CONSOLE_DEV g_uart4port /* UART4 is console */ # define SERIAL_CONSOLE 5 +# elif defined(CONFIG_UART5_SERIAL_CONSOLE) +# define CONSOLE_DEV g_uart5port /* UART5 is console */ +# define SERIAL_CONSOLE 6 +# elif defined(CONFIG_UART6_SERIAL_CONSOLE) +# define CONSOLE_DEV g_uart6port /* UART6 is console */ +# define SERIAL_CONSOLE 7 +# elif defined(CONFIG_UART7_SERIAL_CONSOLE) +# define CONSOLE_DEV g_uart7port /* UART7 is console */ +# define SERIAL_CONSOLE 8 # else # error "I'm confused... Do we have a serial console or not?" # endif @@ -100,6 +109,12 @@ # define SERIAL_CONSOLE 4 # elif defined(CONFIG_MPFS_UART4) # define SERIAL_CONSOLE 5 +# elif defined(CONFIG_MPFS_UART5) +# define SERIAL_CONSOLE 6 +# elif defined(CONFIG_MPFS_UART6) +# define SERIAL_CONSOLE 7 +# elif defined(CONFIG_MPFS_UART7) +# define SERIAL_CONSOLE 8 # else # undef TTYS0_DEV # undef TTYS1_DEV @@ -127,6 +142,7 @@ struct up_dev_s uint8_t parity; /* 0=none, 1=odd, 2=even */ uint8_t bits; /* Number of bits (7 or 8) */ bool stopbits2; /* true: Configure with 2 stop bits instead of 1 */ + bool fpga; /* true: this is an FPGA based driver */ }; /**************************************************************************** @@ -197,6 +213,22 @@ static char g_uart4rxbuffer[CONFIG_UART4_RXBUFSIZE]; static char g_uart4txbuffer[CONFIG_UART4_TXBUFSIZE]; #endif +#ifdef CONFIG_MPFS_UART5 +static char g_uart5rxbuffer[CONFIG_UART5_RXBUFSIZE]; +static char g_uart5txbuffer[CONFIG_UART5_TXBUFSIZE]; +#endif + +#ifdef CONFIG_MPFS_UART6 +static char g_uart6rxbuffer[CONFIG_UART6_RXBUFSIZE]; +static char g_uart6txbuffer[CONFIG_UART6_TXBUFSIZE]; +#endif + +#ifdef CONFIG_MPFS_UART7 +static char g_uart7rxbuffer[CONFIG_UART7_RXBUFSIZE]; +static char g_uart7txbuffer[CONFIG_UART7_TXBUFSIZE]; +#endif + +#ifndef CONFIG_MPFS_FPGA_UART #ifdef CONFIG_MPFS_UART0 static struct up_dev_s g_uart0priv = { @@ -206,6 +238,7 @@ static struct up_dev_s g_uart0priv = .parity = CONFIG_UART0_PARITY, .bits = CONFIG_UART0_BITS, .stopbits2 = CONFIG_UART0_2STOP, + .fpga = false, }; static uart_dev_t g_uart0port = @@ -237,6 +270,7 @@ static struct up_dev_s g_uart1priv = .parity = CONFIG_UART1_PARITY, .bits = CONFIG_UART1_BITS, .stopbits2 = CONFIG_UART1_2STOP, + .fpga = false, }; static uart_dev_t g_uart1port = @@ -268,6 +302,7 @@ static struct up_dev_s g_uart2priv = .parity = CONFIG_UART2_PARITY, .bits = CONFIG_UART2_BITS, .stopbits2 = CONFIG_UART2_2STOP, + .fpga = false, }; static uart_dev_t g_uart2port = @@ -299,6 +334,7 @@ static struct up_dev_s g_uart3priv = .parity = CONFIG_UART3_PARITY, .bits = CONFIG_UART3_BITS, .stopbits2 = CONFIG_UART3_2STOP, + .fpga = false, }; static uart_dev_t g_uart3port = @@ -330,6 +366,169 @@ static struct up_dev_s g_uart4priv = .parity = CONFIG_UART4_PARITY, .bits = CONFIG_UART4_BITS, .stopbits2 = CONFIG_UART4_2STOP, + .fpga = false, +}; + +static uart_dev_t g_uart4port = +{ +#if SERIAL_CONSOLE == 5 + .isconsole = 1, +#endif + .recv = + { + .size = CONFIG_UART4_RXBUFSIZE, + .buffer = g_uart4rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART4_TXBUFSIZE, + .buffer = g_uart4txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart4priv, +}; +#endif + +#else /* CONFIG_MPFS_FPGA_UART */ + +#ifdef CONFIG_MPFS_UART0 +static struct up_dev_s g_uart0priv = +{ + .uartbase = MPFS_FPGA_UART0_BASE, + .baud = CONFIG_UART0_BAUD, + .irq = MPFS_IRQ_FABRIC_F2H_12, + .parity = CONFIG_UART0_PARITY, + .bits = CONFIG_UART0_BITS, + .stopbits2 = CONFIG_UART0_2STOP, + .fpga = true, +}; + +static uart_dev_t g_uart0port = +{ +#if SERIAL_CONSOLE == 1 + .isconsole = 1, +#endif + .recv = + { + .size = CONFIG_UART0_RXBUFSIZE, + .buffer = g_uart0rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART0_TXBUFSIZE, + .buffer = g_uart0txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart0priv, +}; +#endif + +#ifdef CONFIG_MPFS_UART1 +static struct up_dev_s g_uart1priv = +{ + .uartbase = MPFS_FPGA_UART1_BASE, + .baud = CONFIG_UART1_BAUD, + .irq = MPFS_IRQ_FABRIC_F2H_13, + .parity = CONFIG_UART1_PARITY, + .bits = CONFIG_UART1_BITS, + .stopbits2 = CONFIG_UART1_2STOP, + .fpga = true, +}; + +static uart_dev_t g_uart1port = +{ +#if SERIAL_CONSOLE == 2 + .isconsole = 1, +#endif + .recv = + { + .size = CONFIG_UART1_RXBUFSIZE, + .buffer = g_uart1rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART1_TXBUFSIZE, + .buffer = g_uart1txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart1priv, +}; +#endif + +#ifdef CONFIG_MPFS_UART2 +static struct up_dev_s g_uart2priv = +{ + .uartbase = MPFS_FPGA_UART2_BASE, + .baud = CONFIG_UART2_BAUD, + .irq = MPFS_IRQ_FABRIC_F2H_14, + .parity = CONFIG_UART2_PARITY, + .bits = CONFIG_UART2_BITS, + .stopbits2 = CONFIG_UART2_2STOP, + .fpga = true, +}; + +static uart_dev_t g_uart2port = +{ +#if SERIAL_CONSOLE == 3 + .isconsole = 1, +#endif + .recv = + { + .size = CONFIG_UART2_RXBUFSIZE, + .buffer = g_uart2rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART2_TXBUFSIZE, + .buffer = g_uart2txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart2priv, +}; +#endif + +#ifdef CONFIG_MPFS_UART3 +static struct up_dev_s g_uart3priv = +{ + .uartbase = MPFS_FPGA_UART3_BASE, + .baud = CONFIG_UART3_BAUD, + .irq = MPFS_IRQ_FABRIC_F2H_15, + .parity = CONFIG_UART3_PARITY, + .bits = CONFIG_UART3_BITS, + .stopbits2 = CONFIG_UART3_2STOP, + .fpga = true, +}; + +static uart_dev_t g_uart3port = +{ +#if SERIAL_CONSOLE == 4 + .isconsole = 1, +#endif + .recv = + { + .size = CONFIG_UART3_RXBUFSIZE, + .buffer = g_uart3rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART3_TXBUFSIZE, + .buffer = g_uart3txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart3priv, +}; +#endif + +#ifdef CONFIG_MPFS_UART4 +static struct up_dev_s g_uart4priv = +{ + .uartbase = MPFS_FPGA_UART4_BASE, + .baud = CONFIG_UART4_BAUD, + .irq = MPFS_IRQ_FABRIC_F2H_16, + .parity = CONFIG_UART4_PARITY, + .bits = CONFIG_UART4_BITS, + .stopbits2 = CONFIG_UART4_2STOP, + .fpga = true, }; static uart_dev_t g_uart4port = @@ -352,6 +551,104 @@ static uart_dev_t g_uart4port = }; #endif +#ifdef CONFIG_MPFS_UART5 +static struct up_dev_s g_uart5priv = +{ + .uartbase = MPFS_FPGA_UART5_BASE, + .baud = CONFIG_UART5_BAUD, + .irq = MPFS_IRQ_FABRIC_F2H_17, + .parity = CONFIG_UART5_PARITY, + .bits = CONFIG_UART5_BITS, + .stopbits2 = CONFIG_UART5_2STOP, + .fpga = true, +}; + +static uart_dev_t g_uart5port = +{ +#if SERIAL_CONSOLE == 6 + .isconsole = 1, +#endif + .recv = + { + .size = CONFIG_UART5_RXBUFSIZE, + .buffer = g_uart5rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART5_TXBUFSIZE, + .buffer = g_uart5txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart5priv, +}; +#endif + +#ifdef CONFIG_MPFS_UART6 +static struct up_dev_s g_uart6priv = +{ + .uartbase = MPFS_FPGA_UART6_BASE, + .baud = CONFIG_UART6_BAUD, + .irq = MPFS_IRQ_FABRIC_F2H_18, + .parity = CONFIG_UART6_PARITY, + .bits = CONFIG_UART6_BITS, + .stopbits2 = CONFIG_UART6_2STOP, + .fpga = true, +}; + +static uart_dev_t g_uart6port = +{ +#if SERIAL_CONSOLE == 7 + .isconsole = 1, +#endif + .recv = + { + .size = CONFIG_UART6_RXBUFSIZE, + .buffer = g_uart6rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART6_TXBUFSIZE, + .buffer = g_uart6txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart6priv, +}; +#endif + +#ifdef CONFIG_MPFS_UART7 +static struct up_dev_s g_uart7priv = +{ + .uartbase = MPFS_FPGA_UART7_BASE, + .baud = CONFIG_UART7_BAUD, + .irq = MPFS_IRQ_FABRIC_F2H_19, + .parity = CONFIG_UART7_PARITY, + .bits = CONFIG_UART7_BITS, + .stopbits2 = CONFIG_UART7_2STOP, + .fpga = true, +}; + +static uart_dev_t g_uart7port = +{ +#if SERIAL_CONSOLE == 7 + .isconsole = 1, +#endif + .recv = + { + .size = CONFIG_UART7_RXBUFSIZE, + .buffer = g_uart7rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART7_TXBUFSIZE, + .buffer = g_uart7txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart7priv, +}; +#endif + +#endif /* CONFIG_MPFS_FPGA_UART */ + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -447,27 +744,41 @@ static void up_enable_uart(struct up_dev_s *priv, bool enable) clock_bit = SYSREG_SUBBLK_CLOCK_CR_MMUART4; reset_bit = SYSREG_SOFT_RESET_CR_MMUART4; break; + case MPFS_FPGA_UART0_BASE: + case MPFS_FPGA_UART1_BASE: + case MPFS_FPGA_UART2_BASE: + case MPFS_FPGA_UART3_BASE: + case MPFS_FPGA_UART4_BASE: + case MPFS_FPGA_UART5_BASE: + case MPFS_FPGA_UART6_BASE: + case MPFS_FPGA_UART7_BASE: + clock_bit = SYSREG_SUBBLK_CLOCK_CR_FIC3; + reset_bit = SYSREG_SOFT_RESET_CR_FIC3 | SYSREG_SOFT_RESET_CR_FPGA; + break; default: return; } - /* reset on */ + /* reset on for non-fpga */ - modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SOFT_RESET_CR_OFFSET, - 0, reset_bit); + if (!priv->fpga) + { + modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SOFT_RESET_CR_OFFSET, + 0, reset_bit); + } if (enable) { /* reset off */ - modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SUBBLK_CLOCK_CR_OFFSET, - 0, reset_bit); + modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SOFT_RESET_CR_OFFSET, + reset_bit, 0); /* clock on */ - modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SOFT_RESET_CR_OFFSET, - clock_bit, 0); + modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SUBBLK_CLOCK_CR_OFFSET, + 0, clock_bit); } else { @@ -494,7 +805,14 @@ static void up_config_baud_divisors(struct up_dev_s *priv, uint32_t baudrate) uint32_t fractional_baud_value; uint64_t pclk_freq; - pclk_freq = MPFS_MSS_APB_AHB_CLK; + if (!priv->fpga) + { + pclk_freq = MPFS_MSS_APB_AHB_CLK; + } + else + { + pclk_freq = MPFS_FPGA_PERIPHERAL_CLK; + } /* Compute baud value based on requested baud rate and PCLK frequency. * The baud value is computed using the following equation: @@ -1140,6 +1458,18 @@ void riscv_earlyserialinit(void) up_disableuartint(g_uart4port.priv, NULL); #endif +#ifdef CONFIG_MPFS_UART5 + up_disableuartint(g_uart5port.priv, NULL); +#endif + +#ifdef CONFIG_MPFS_UART6 + up_disableuartint(g_uart6port.priv, NULL); +#endif + +#ifdef CONFIG_MPFS_UART7 + up_disableuartint(g_uart7port.priv, NULL); +#endif + /* Configuration whichever one is the console */ #ifdef HAVE_SERIAL_CONSOLE @@ -1183,6 +1513,15 @@ void riscv_serialinit(void) #ifdef CONFIG_MPFS_UART4 uart_register("/dev/ttyS4", &g_uart4port); #endif +#ifdef CONFIG_MPFS_UART5 + uart_register("/dev/ttyS5", &g_uart5port); +#endif +#ifdef CONFIG_MPFS_UART6 + uart_register("/dev/ttyS6", &g_uart6port); +#endif +#ifdef CONFIG_MPFS_UART7 + uart_register("/dev/ttyS7", &g_uart7port); +#endif } /**************************************************************************** From e278e436c0852a8ffdfce0404121120a8aaacaa6 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Fri, 12 May 2023 10:22:00 +0300 Subject: [PATCH 44/79] Add CONFIG_MPFS_SPI flag to define using SOC hard-ip SPI block Signed-off-by: Jukka Laitinen --- arch/risc-v/src/mpfs/Kconfig | 6 ++++++ arch/risc-v/src/mpfs/Make.defs | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/risc-v/src/mpfs/Kconfig b/arch/risc-v/src/mpfs/Kconfig index 8b85e8e0dcd3b..611770262c175 100644 --- a/arch/risc-v/src/mpfs/Kconfig +++ b/arch/risc-v/src/mpfs/Kconfig @@ -266,13 +266,19 @@ config MPFS_HAVE_UART7 # These are the peripheral selections proper +config MPFS_SPI + bool + default n + config MPFS_SPI0 bool "SPI 0" default n + select MPFS_SPI config MPFS_SPI1 bool "SPI 1" default n + select MPFS_SPI config MPFS_FPGA_UART bool "FPGA uarts" diff --git a/arch/risc-v/src/mpfs/Make.defs b/arch/risc-v/src/mpfs/Make.defs index 4059405a44641..eb09e52a7bd62 100644 --- a/arch/risc-v/src/mpfs/Make.defs +++ b/arch/risc-v/src/mpfs/Make.defs @@ -50,7 +50,7 @@ ifeq ($(CONFIG_MM_PGALLOC),y) CHIP_CSRCS += mpfs_pgalloc.c endif -ifeq ($(CONFIG_SPI),y) +ifeq ($(CONFIG_MPFS_SPI),y) CHIP_CSRCS += mpfs_spi.c endif From a4c60b82c5c7d10feb3084bd3d6e741d820a7e5b Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Fri, 12 May 2023 10:23:31 +0300 Subject: [PATCH 45/79] arch/risc-v/src/mpfs: Remove CONFIG_MPFS_COREPWMx_PWMCLK configs These are always the same as FPGA peripheral clock, so use that directly Signed-off-by: Jukka Laitinen --- arch/risc-v/src/mpfs/Kconfig | 12 ------------ arch/risc-v/src/mpfs/mpfs_corepwm.c | 9 +++------ 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/arch/risc-v/src/mpfs/Kconfig b/arch/risc-v/src/mpfs/Kconfig index 611770262c175..3a893f93dfe35 100644 --- a/arch/risc-v/src/mpfs/Kconfig +++ b/arch/risc-v/src/mpfs/Kconfig @@ -622,12 +622,6 @@ config MPFS_COREPWM0_BASE default 0x44000000 depends on MPFS_COREPWM0 -config MPFS_COREPWM0_PWMCLK - int "Clock frequency of the CorePWM0 block (Hz)" - default 25000000 - range 1000000 100000000 - depends on MPFS_COREPWM0 - config MPFS_COREPWM0_REGWIDTH int "Width of the PWM register (8, 16 or 32 bits)" default 32 @@ -651,12 +645,6 @@ config MPFS_COREPWM1_BASE default 0x45000000 depends on MPFS_COREPWM1 -config MPFS_COREPWM1_PWMCLK - int "Clock frequency of the CorePWM1 block (Hz)" - default 25000000 - range 1000000 100000000 - depends on MPFS_COREPWM1 - config MPFS_COREPWM1_REGWIDTH int "Width of the PWM register (8, 16 or 32 bits)" default 32 diff --git a/arch/risc-v/src/mpfs/mpfs_corepwm.c b/arch/risc-v/src/mpfs/mpfs_corepwm.c index 1734c6d610fc9..408afb7b43f16 100644 --- a/arch/risc-v/src/mpfs/mpfs_corepwm.c +++ b/arch/risc-v/src/mpfs/mpfs_corepwm.c @@ -76,7 +76,6 @@ struct mpfs_pwmtimer_s struct mpfs_pwmchan_s channels[MPFS_MAX_PWM_CHANNELS]; uint32_t frequency; /* Current frequency setting */ uintptr_t base; /* The base address of the pwm block */ - uint32_t pwmclk; /* The frequency of the pwm clock */ }; /**************************************************************************** @@ -187,7 +186,6 @@ static struct mpfs_pwmtimer_s g_pwm0dev = } }, .base = CONFIG_MPFS_COREPWM0_BASE, - .pwmclk = CONFIG_MPFS_COREPWM0_PWMCLK, }; #endif @@ -249,7 +247,6 @@ static struct mpfs_pwmtimer_s g_pwm1dev = } }, .base = CONFIG_MPFS_COREPWM1_BASE, - .pwmclk = CONFIG_MPFS_COREPWM1_PWMCLK, }; #endif @@ -404,12 +401,12 @@ static int pwm_timer(struct mpfs_pwmtimer_s *priv, * PERIOD = pwmclk / frequency = 25,000,000 / 50 = 500,000 */ - pwminfo("PWM%u frequency: %u PWMCLK: %u prescaler: %u\n", - priv->pwmid, info->frequency, priv->pwmclk, prescaler); + pwminfo("PWM%u frequency: %u PWMCLK: %lu prescaler: %u\n", + priv->pwmid, info->frequency, MPFS_FPGA_PERIPHERAL_CLK, prescaler); /* Set the reload and prescaler values */ - period = priv->pwmclk / info->frequency; + period = MPFS_FPGA_PERIPHERAL_CLK / info->frequency; pwm_putreg(priv, MPFS_COREPWM_PERIOD_OFFSET, period); pwm_putreg(priv, MPFS_COREPWM_PRESCALE_OFFSET, prescaler); From 64351a174aef9ec1fd30b4e6b387fa4f9144a144 Mon Sep 17 00:00:00 2001 From: Eero Nurkkala Date: Fri, 12 May 2023 15:26:15 +0300 Subject: [PATCH 46/79] risc-v/mpfs: serial: fix uart closing Don't turn off FIC3 clk which would terminate all other peripherals depending on it. Also add a few missing undefs. Signed-off-by: Eero Nurkkala --- arch/risc-v/src/mpfs/mpfs_serial.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_serial.c b/arch/risc-v/src/mpfs/mpfs_serial.c index 64dcfee59620c..8fb857274a557 100644 --- a/arch/risc-v/src/mpfs/mpfs_serial.c +++ b/arch/risc-v/src/mpfs/mpfs_serial.c @@ -99,6 +99,9 @@ # undef CONFIG_UART2_SERIAL_CONSOLE # undef CONFIG_UART3_SERIAL_CONSOLE # undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_UART5_SERIAL_CONSOLE +# undef CONFIG_UART6_SERIAL_CONSOLE +# undef CONFIG_UART7_SERIAL_CONSOLE # if defined(CONFIG_MPFS_UART0) # define SERIAL_CONSOLE 1 # elif defined(CONFIG_MPFS_UART1) @@ -782,10 +785,17 @@ static void up_enable_uart(struct up_dev_s *priv, bool enable) } else { - /* clock off */ + /* clock off for non-fpga */ - modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SUBBLK_CLOCK_CR_OFFSET, - clock_bit, 0); + if (!priv->fpga) + { + /* Turning off FPGA clk would disable it for all other FPGA + * peripherals as well. Don't touch it without refcnt mechanism. + */ + + modifyreg32(MPFS_SYSREG_BASE + MPFS_SYSREG_SUBBLK_CLOCK_CR_OFFSET, + clock_bit, 0); + } } } From 6afcf2101070cb5c0d1755aedd9a799578f2ff3a Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Mon, 15 May 2023 16:14:06 +0300 Subject: [PATCH 47/79] Change MPFS_FPGA_UARTx_BASE addresses to 4k aligned as per new FPGA image Signed-off-by: Jukka Laitinen --- arch/risc-v/src/mpfs/hardware/mpfs_memorymap.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/risc-v/src/mpfs/hardware/mpfs_memorymap.h b/arch/risc-v/src/mpfs/hardware/mpfs_memorymap.h index cbc55d9f18011..54d9fda0c2d2c 100644 --- a/arch/risc-v/src/mpfs/hardware/mpfs_memorymap.h +++ b/arch/risc-v/src/mpfs/hardware/mpfs_memorymap.h @@ -133,12 +133,12 @@ /* FPGA UART defines */ #define MPFS_FPGA_UART0_BASE 0x4c000000UL -#define MPFS_FPGA_UART1_BASE 0x4c000100UL -#define MPFS_FPGA_UART2_BASE 0x4c000200UL -#define MPFS_FPGA_UART3_BASE 0x4c000300UL -#define MPFS_FPGA_UART4_BASE 0x4c000400UL -#define MPFS_FPGA_UART5_BASE 0x4c000500UL -#define MPFS_FPGA_UART6_BASE 0x4c000600UL -#define MPFS_FPGA_UART7_BASE 0x4c000700UL +#define MPFS_FPGA_UART1_BASE 0x4c001000UL +#define MPFS_FPGA_UART2_BASE 0x4c002000UL +#define MPFS_FPGA_UART3_BASE 0x4c003000UL +#define MPFS_FPGA_UART4_BASE 0x4c004000UL +#define MPFS_FPGA_UART5_BASE 0x4c005000UL +#define MPFS_FPGA_UART6_BASE 0x4c006000UL +#define MPFS_FPGA_UART7_BASE 0x4c007000UL #endif /* __ARCH_RISCV_SRC_MPFS_HARDWARE_MPFS_MEMORYMAP_H */ From f5b0d4bdbc847caf8c95faa82363de6028191b7b Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Wed, 17 May 2023 13:25:21 +0300 Subject: [PATCH 48/79] [REVERTME] arch/risc-v/src/mpfs/mpfs_corespi.c: Hack around a bug in nuttx nxsem_tickwait_uninterruptible bug The nxsem_tickwait_uninterruptible seems to timeout randomly one tick too soon. Add one tick to timeout to make sure it is long enough. This can be reverted when the actual bug is fixed. Signed-off-by: Jukka Laitinen --- arch/risc-v/src/mpfs/mpfs_corespi.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/risc-v/src/mpfs/mpfs_corespi.c b/arch/risc-v/src/mpfs/mpfs_corespi.c index 43b1cacf3abe5..874293a83e365 100644 --- a/arch/risc-v/src/mpfs/mpfs_corespi.c +++ b/arch/risc-v/src/mpfs/mpfs_corespi.c @@ -709,7 +709,13 @@ static int mpfs_spi_sem_waitdone(struct mpfs_spi_priv_s *priv) { uint32_t timeout = SPI_TTOA_US(priv->txwords * priv->nbits, priv->actual); timeout += SPI_TTOA_MARGIN_US; - return nxsem_tickwait_uninterruptible(&priv->sem_isr, USEC2TICK(timeout)); + + /* Hack: add +1 to timeout due to some bug in NuttX. It randomly timeouts + * one tick too early + */ + + return nxsem_tickwait_uninterruptible(&priv->sem_isr, USEC2TICK(timeout) + + 1); } /**************************************************************************** From e67f54a5798883a2a6e06ae147b9de51222e9d63 Mon Sep 17 00:00:00 2001 From: haitomatic Date: Wed, 10 May 2023 10:04:52 +0000 Subject: [PATCH 49/79] Add support for 2xCAN --- arch/risc-v/src/mpfs/Kconfig | 57 ++++- arch/risc-v/src/mpfs/Make.defs | 2 +- arch/risc-v/src/mpfs/mpfs_fpga_canfd.c | 239 ++++++++++++++---- arch/risc-v/src/mpfs/mpfs_fpga_canfd.h | 4 +- .../mpfs/icicle/configs/canfd/defconfig | 2 +- 5 files changed, 236 insertions(+), 68 deletions(-) diff --git a/arch/risc-v/src/mpfs/Kconfig b/arch/risc-v/src/mpfs/Kconfig index 3a893f93dfe35..d55c1418d432c 100644 --- a/arch/risc-v/src/mpfs/Kconfig +++ b/arch/risc-v/src/mpfs/Kconfig @@ -659,7 +659,7 @@ config MPFS_COREPWM1_NCHANNELS comment "CAN-FD Options" -config MPFS_CANFD +config MPFS_HAVE_CANFD bool "CAN FD" select ARCH_HAVE_CAN_ERRORS select NET_CAN_HAVE_CANFD @@ -667,26 +667,57 @@ config MPFS_CANFD select NET_CAN_HAVE_TX_DEADLINE default n -config MPFS_CANFD_BASE - hex "Base address for the instance" +config MPFS_CANFD0 + bool "MPFS FPGA CANFD0 IP block configured" + default n + depends on MPFS_HAVE_CANFD + +config MPFS_CANFD_BASE0 + hex "Base address for the CANFD0 instance" default 0x46000000 - depends on MPFS_CANFD + depends on MPFS_CANFD0 + +config MPFS_CANFD_CLK0 + int "Clock frequency of the CANFD0 block (Hz)" + default 62500000 + range 1000000 100000000 + depends on MPFS_CANFD0 + +config MPFS_CANFD_ARBI_BITRATE0 + int "CANFD0 Arbitration phase bitrate" + default 1000000 + depends on MPFS_CANFD0 + +config MPFS_CANFD_DATA_BITRATE0 + int "CANFD0 Data phase bitrate" + default 4000000 + depends on MPFS_CANFD0 + +config MPFS_CANFD1 + bool "MPFS FPGA CANFD1 IP block configured" + default n + depends on MPFS_HAVE_CANFD + +config MPFS_CANFD_BASE1 + hex "Base address for the CANFD1 instance" + default 0x47000000 + depends on MPFS_CANFD1 -config MPFS_CANFD_CLK - int "Clock frequency of the CANFD block (Hz)" +config MPFS_CANFD_CLK1 + int "Clock frequency of the CANFD1 block (Hz)" default 62500000 range 1000000 100000000 - depends on MPFS_CANFD + depends on MPFS_CANFD1 -config MPFS_CANFD_ARBI_BITRATE - int "CAN FD Arbitration phase bitrate" +config MPFS_CANFD_ARBI_BITRATE1 + int "CANFD1 Arbitration phase bitrate" default 1000000 - depends on MPFS_CANFD + depends on MPFS_CANFD1 -config MPFS_CANFD_DATA_BITRATE - int "CAN Arbitration phase bitrate" +config MPFS_CANFD_DATA_BITRATE1 + int "CANFD1 Data phase bitrate" default 4000000 - depends on MPFS_CANFD + depends on MPFS_CANFD1 endmenu diff --git a/arch/risc-v/src/mpfs/Make.defs b/arch/risc-v/src/mpfs/Make.defs index eb09e52a7bd62..bbe2a0642dd5c 100644 --- a/arch/risc-v/src/mpfs/Make.defs +++ b/arch/risc-v/src/mpfs/Make.defs @@ -74,7 +74,7 @@ ifeq (${CONFIG_MPFS_HAVE_COREPWM},y) CHIP_CSRCS += mpfs_corepwm.c endif -ifeq (${CONFIG_MPFS_CANFD}, y) +ifeq (${CONFIG_MPFS_HAVE_CANFD}, y) CHIP_CSRCS += mpfs_fpga_canfd.c endif diff --git a/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c b/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c index efe6f2f094e54..6262fa0869dd4 100644 --- a/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c +++ b/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c @@ -58,18 +58,18 @@ # define OK 0 #endif -/* This module only compiles if the CAN-FD IP core instance +/* This module only compiles if the CANFD IP core instance * is configured to the FPGA */ -#ifndef CONFIG_MPFS_CANFD -# error This should not be compiled as CAN-FD FPGA block is not defined +#ifndef CONFIG_MPFS_HAVE_CANFD +# error This should not be compiled as CANFD FPGA block is not defined #endif /* This module only compiles if Nuttx socketCAN interface supports CANFD */ #ifndef CONFIG_NET_CAN_CANFD -# error This should not be compiled as CAN-FD driver relies on socket CAN +# error This should not be compiled as CANFD driver relies on socket CAN #endif /* Clock reset and enabling */ @@ -83,7 +83,7 @@ #define MPFS_CANFD_ID 0xCAFD -/* For allocating the tx and rx CAN-FD frame buffer */ +/* For allocating the tx and rx CANFD frame buffer */ #define POOL_SIZE 1 #define TIMESTAMP_SIZE sizeof(struct timeval) /* To support @@ -332,13 +332,21 @@ enum mpfs_canfd_can_frame_format struct mpfs_config_s { - uint32_t canfd_fpga_irq; /* the only CAN-FD FPGA IRQ */ + uint32_t canfd_fpga_irq; /* the only CANFD FPGA IRQ */ }; -static const struct mpfs_config_s mpfs_fpga_canfd_config = +#ifdef CONFIG_MPFS_CANFD0 +static const struct mpfs_config_s mpfs_fpga_canfd_config0 = { .canfd_fpga_irq = MPFS_IRQ_FABRIC_F2H_0, }; +#endif +#ifdef CONFIG_MPFS_CANFD1 +static const struct mpfs_config_s mpfs_fpga_canfd_config1 = +{ + .canfd_fpga_irq = MPFS_IRQ_FABRIC_F2H_9, +}; +#endif /**************************************************************************** * The mpfs_driver_s encapsulates all state information for a single @@ -390,12 +398,23 @@ struct mpfs_driver_s * Private Data ****************************************************************************/ -static struct mpfs_driver_s g_canfd; +#ifdef CONFIG_MPFS_CANFD0 +static struct mpfs_driver_s g_canfd0; + +static uint8_t g_tx_pool0[(sizeof(struct canfd_frame) + TIMESTAMP_SIZE) * + POOL_SIZE]; +static uint8_t g_rx_pool0[(sizeof(struct canfd_frame) + TIMESTAMP_SIZE) * + POOL_SIZE]; +#endif + +#ifdef CONFIG_MPFS_CANFD1 +static struct mpfs_driver_s g_canfd1; -static uint8_t g_tx_pool[(sizeof(struct canfd_frame) + TIMESTAMP_SIZE) * +static uint8_t g_tx_pool1[(sizeof(struct canfd_frame) + TIMESTAMP_SIZE) * POOL_SIZE]; -static uint8_t g_rx_pool[(sizeof(struct canfd_frame) + TIMESTAMP_SIZE) * +static uint8_t g_rx_pool1[(sizeof(struct canfd_frame) + TIMESTAMP_SIZE) * POOL_SIZE]; +#endif /**************************************************************************** * Private Function Prototypes @@ -971,7 +990,7 @@ static enum mpfs_can_state_e return CAN_STATE_BUS_OFF; } - canwarn("Invalid FPGA CAN-FD error state\n"); + canwarn("Invalid FPGA CANFD error state\n"); return CAN_STATE_ERROR_PASSIVE; } @@ -1059,6 +1078,7 @@ static void mpfs_err_interrupt(struct mpfs_driver_s *priv, uint32_t isr) switch (state) { case CAN_STATE_BUS_OFF: + priv->can.can_stats.bus_off++; canwarn("Change to BUS_OFF error state\n"); break; case CAN_STATE_ERROR_PASSIVE: @@ -1196,6 +1216,8 @@ static int mpfs_interrupt(int irq, void *context, void *arg) if (isr & MPFS_CANFD_INT_STAT_TXBHCI) { + canerr("TXBHCI interrupt\n"); + #ifdef CONFIG_DEBUG_CAN_INFO caninfo("txb_sent=0x%08x txb_processed=0x%08x\n", priv->txb_sent, priv->txb_processed); @@ -1219,6 +1241,8 @@ static int mpfs_interrupt(int irq, void *context, void *arg) if (isr & MPFS_CANFD_INT_STAT_DOI) { + canerr("DOI interrupt\n"); + /* Notify to socket interface */ NETDEV_RXERRORS(&priv->dev); @@ -2468,6 +2492,8 @@ static int mpfs_reset(struct mpfs_driver_s *priv) nxsig_usleep(200); } while (1); + + priv->can.can_stats.restarts++; } /**************************************************************************** @@ -2499,9 +2525,6 @@ static int mpfs_ifup(struct net_driver_s *dev) priv->bifup = true; - priv->txdesc = (struct canfd_frame *)&g_tx_pool; - priv->rxdesc = (struct canfd_frame *)&g_rx_pool; - priv->dev.d_buf = (uint8_t *)priv->txdesc; /* Set interrupts */ @@ -2833,7 +2856,7 @@ defined(CONFIG_NETDEV_CAN_FILTER_IOCTL) * Initialize the CAN controller and driver * * Returned Value: - * On success, a pointer to the MPFS CAN-FD driver is + * On success, a pointer to the MPFS CANFD driver is * returned. NULL is returned on any failure. * * Assumptions: @@ -2843,91 +2866,205 @@ defined(CONFIG_NETDEV_CAN_FILTER_IOCTL) int mpfs_fpga_canfd_init(void) { - caninfo("Initialize CAN-FD driver...\n"); - struct mpfs_driver_s *priv; - priv = &g_canfd; - memset(priv, 0, sizeof(struct mpfs_driver_s)); +#ifdef CONFIG_MPFS_CANFD0 + caninfo("Initialize CANFD0 driver...\n"); + struct mpfs_driver_s *priv0; + priv0 = &g_canfd0; + memset(priv0, 0, sizeof(struct mpfs_driver_s)); - priv->base = CONFIG_MPFS_CANFD_BASE; - priv->config = &mpfs_fpga_canfd_config; + priv0->base = CONFIG_MPFS_CANFD_BASE0; + priv0->config = &mpfs_fpga_canfd_config0; /* Initialize the CAN common private data structure */ - priv->can.state = CAN_STATE_ERROR_ACTIVE; - priv->ntxbufs = 2; - priv->can.bittiming_const = &mpfs_can_bit_timing_range; - priv->can.data_bittiming_const = &mpfs_can_bit_timing_data_range; + priv0->can.state = CAN_STATE_ERROR_ACTIVE; + priv0->ntxbufs = 2; + priv0->can.bittiming_const = &mpfs_can_bit_timing_range; + priv0->can.data_bittiming_const = &mpfs_can_bit_timing_data_range; + + priv0->can.can_stats.arbitration_lost = 0; + priv0->can.can_stats.bus_error = 0; + priv0->can.can_stats.bus_off = 0; + priv0->can.can_stats.error_warning = 0; + priv0->can.can_stats.error_passive = 0; + priv0->can.can_stats.restarts = 0; /* Get the can_clk info */ - priv->can.clock.freq = CONFIG_MPFS_CANFD_CLK; + priv0->can.clock.freq = CONFIG_MPFS_CANFD_CLK0; /* Needed for timing adjustment to be performed as soon as possible */ - priv->can.bittiming.bitrate = CONFIG_MPFS_CANFD_ARBI_BITRATE; - priv->can.data_bittiming.bitrate = CONFIG_MPFS_CANFD_DATA_BITRATE; - priv->can.bittiming.sjw = 5; - priv->can.data_bittiming.sjw = 5; + priv0->can.bittiming.bitrate = CONFIG_MPFS_CANFD_ARBI_BITRATE0; + priv0->can.data_bittiming.bitrate = CONFIG_MPFS_CANFD_DATA_BITRATE0; + priv0->can.bittiming.sjw = 5; + priv0->can.data_bittiming.sjw = 5; /* Calculate nominal and data bit timing */ - mpfs_can_btr_compute(priv, - &priv->can.bittiming, - priv->can.bittiming_const); - mpfs_can_btr_compute(priv, - &priv->can.data_bittiming, - priv->can.data_bittiming_const); + mpfs_can_btr_compute(priv0, + &priv0->can.bittiming, + priv0->can.bittiming_const); + mpfs_can_btr_compute(priv0, + &priv0->can.data_bittiming, + priv0->can.data_bittiming_const); #ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL /* Init hw filter runtime var */ - priv->used_bit_filter_number = 0; - priv->used_range_filter = false; + priv0->used_bit_filter_number = 0; + priv0->used_range_filter = false; +#endif /* CONFIG_NETDEV_CAN_FILTER_IOCTL */ + + /* Set CAN control modes */ + + priv0->can.ctrlmode = CAN_CTRLMODE_FD + | CAN_CTRLMODE_BERR_REPORTING; + + /* Attach the interrupt handler */ + + if (irq_attach(priv0->config->canfd_fpga_irq, mpfs_interrupt, priv0)) + { + /* We could not attach the ISR to the interrupt */ + + canerr("ERROR: Failed to attach to CAN0 IRQ\n"); + return -EAGAIN; + } + + /* Initialize TX/RX descriptor structure */ + + priv0->txdesc = (struct canfd_frame *)&g_tx_pool0; + priv0->rxdesc = (struct canfd_frame *)&g_rx_pool0; + + /* Initialize the driver network device structure */ + + priv0->dev.d_ifup = mpfs_ifup; /* I/F up (new IP address) callback */ + priv0->dev.d_ifdown = mpfs_ifdown; /* I/F down callback */ + priv0->dev.d_txavail = mpfs_txavail; /* New TX data callback */ +#ifdef CONFIG_NETDEV_IOCTL + priv0->dev.d_ioctl = mpfs_ioctl; /* Support CAN ioctl() calls */ +#endif + priv0->dev.d_private = priv0; /* Used to recover private state from dev */ + + /* Reset controller */ + + if (mpfs_reset(priv0) < 0) + { + return -1; + } + + caninfo("CANFD0 driver init done\n"); + + /* Put the interface in the down state. This usually amounts to resetting + * the device and/or calling mpfs_ifdown(). + */ + + mpfs_ifdown(&priv0->dev); + + /* Register the device with the OS so that socket IOCTLs can be performed */ + + netdev_register(&priv0->dev, NET_LL_CAN); +#endif /* CONFIG_MPFS_CANFD0 */ + +#ifdef CONFIG_MPFS_CANFD1 + caninfo("Initialize CANFD1 driver...\n"); + struct mpfs_driver_s *priv1; + priv1 = &g_canfd1; + memset(priv1, 0, sizeof(struct mpfs_driver_s)); + + priv1->base = CONFIG_MPFS_CANFD_BASE1; + priv1->config = &mpfs_fpga_canfd_config1; + + /* Initialize the CAN common private data structure */ + + priv1->can.state = CAN_STATE_ERROR_ACTIVE; + priv1->ntxbufs = 2; + priv1->can.bittiming_const = &mpfs_can_bit_timing_range; + priv1->can.data_bittiming_const = &mpfs_can_bit_timing_data_range; + + priv1->can.can_stats.arbitration_lost = 0; + priv1->can.can_stats.bus_error = 0; + priv1->can.can_stats.bus_off = 0; + priv1->can.can_stats.error_warning = 0; + priv1->can.can_stats.error_passive = 0; + priv1->can.can_stats.restarts = 0; + + /* Get the can_clk info */ + + priv1->can.clock.freq = CONFIG_MPFS_CANFD_CLK1; + + /* Needed for timing adjustment to be performed as soon as possible */ + + priv1->can.bittiming.bitrate = CONFIG_MPFS_CANFD_ARBI_BITRATE1; + priv1->can.data_bittiming.bitrate = CONFIG_MPFS_CANFD_DATA_BITRATE1; + priv1->can.bittiming.sjw = 5; + priv1->can.data_bittiming.sjw = 5; + + /* Calculate nominal and data bit timing */ + + mpfs_can_btr_compute(priv1, + &priv1->can.bittiming, + priv1->can.bittiming_const); + mpfs_can_btr_compute(priv1, + &priv1->can.data_bittiming, + priv1->can.data_bittiming_const); + +#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL + /* Init hw filter runtime var */ + + priv1->used_bit_filter_number = 0; + priv1->used_range_filter = false; #endif /* CONFIG_NETDEV_CAN_FILTER_IOCTL */ /* Set CAN control modes */ - priv->can.ctrlmode = CAN_CTRLMODE_FD + priv1->can.ctrlmode = CAN_CTRLMODE_FD | CAN_CTRLMODE_BERR_REPORTING; /* Attach the interrupt handler */ - if (irq_attach(priv->config->canfd_fpga_irq, mpfs_interrupt, priv)) + if (irq_attach(priv1->config->canfd_fpga_irq, mpfs_interrupt, priv1)) { /* We could not attach the ISR to the interrupt */ - canerr("ERROR: Failed to attach to CAN IRQ\n"); + canerr("ERROR: Failed to attach to CAN1 IRQ\n"); return -EAGAIN; } - /* Initialize the driver structure */ + /* Initialize TX/RX descriptor structure */ + + priv1->txdesc = (struct canfd_frame *)&g_tx_pool1; + priv1->rxdesc = (struct canfd_frame *)&g_rx_pool1; + + /* Initialize the driver network device structure */ - priv->dev.d_ifup = mpfs_ifup; /* I/F up (new IP address) callback */ - priv->dev.d_ifdown = mpfs_ifdown; /* I/F down callback */ - priv->dev.d_txavail = mpfs_txavail; /* New TX data callback */ + priv1->dev.d_ifup = mpfs_ifup; /* I/F up (new IP address) callback */ + priv1->dev.d_ifdown = mpfs_ifdown; /* I/F down callback */ + priv1->dev.d_txavail = mpfs_txavail; /* New TX data callback */ #ifdef CONFIG_NETDEV_IOCTL - priv->dev.d_ioctl = mpfs_ioctl; /* Support CAN ioctl() calls */ + priv1->dev.d_ioctl = mpfs_ioctl; /* Support CAN ioctl() calls */ #endif - priv->dev.d_private = priv; /* Used to recover private state from dev */ + priv1->dev.d_private = priv1; /* Used to recover private state from dev */ /* Reset controller */ - if (mpfs_reset(priv) < 0) + if (mpfs_reset(priv1) < 0) { return -1; } - caninfo("CAN-FD driver init done\n"); + caninfo("CANFD1 driver init done\n"); /* Put the interface in the down state. This usually amounts to resetting * the device and/or calling mpfs_ifdown(). */ - mpfs_ifdown(&priv->dev); + mpfs_ifdown(&priv1->dev); /* Register the device with the OS so that socket IOCTLs can be performed */ - netdev_register(&priv->dev, NET_LL_CAN); + netdev_register(&priv1->dev, NET_LL_CAN); +#endif /* CONFIG_MPFS_CANFD1 */ return OK; } diff --git a/arch/risc-v/src/mpfs/mpfs_fpga_canfd.h b/arch/risc-v/src/mpfs/mpfs_fpga_canfd.h index 4d925560b7d9f..d7dc98098bba0 100644 --- a/arch/risc-v/src/mpfs/mpfs_fpga_canfd.h +++ b/arch/risc-v/src/mpfs/mpfs_fpga_canfd.h @@ -35,7 +35,7 @@ /* Check if CAN-FD support is enabled. */ -#ifdef CONFIG_MPFS_CANFD +#ifdef CONFIG_MPFS_HAVE_CANFD /**************************************************************************** * Included Files @@ -90,5 +90,5 @@ int mpfs_fpga_canfd_init(void); #endif #endif /* __ASSEMBLY__ */ -#endif /* CONFIG_MPFS_CANFD */ +#endif /* CONFIG_MPFS_HAVE_CANFD */ #endif /* __ARCH_RISCV_SRC_MPFS_MPFS_FPGA_CANFD_H */ diff --git a/boards/risc-v/mpfs/icicle/configs/canfd/defconfig b/boards/risc-v/mpfs/icicle/configs/canfd/defconfig index 32507993c60e8..0c1101b582987 100644 --- a/boards/risc-v/mpfs/icicle/configs/canfd/defconfig +++ b/boards/risc-v/mpfs/icicle/configs/canfd/defconfig @@ -46,7 +46,7 @@ CONFIG_LIBC_PERROR_STDOUT=y CONFIG_LIBC_STRERROR=y CONFIG_MEMSET_64BIT=y CONFIG_MEMSET_OPTSPEED=y -CONFIG_MPFS_CANFD=y +CONFIG_MPFS_HAVE_CANFD=y CONFIG_MPFS_ENABLE_DPFPU=y CONFIG_MPFS_UART1=y CONFIG_NET=y From b9fa47812191f8cbee8c012aa8ad5e2fe6834aa1 Mon Sep 17 00:00:00 2001 From: haitomatic Date: Tue, 16 May 2023 10:00:40 +0000 Subject: [PATCH 50/79] canfd : add missing configs for 2xCAN support --- boards/risc-v/mpfs/icicle/configs/canfd/defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/boards/risc-v/mpfs/icicle/configs/canfd/defconfig b/boards/risc-v/mpfs/icicle/configs/canfd/defconfig index 0c1101b582987..97d0ac1545c59 100644 --- a/boards/risc-v/mpfs/icicle/configs/canfd/defconfig +++ b/boards/risc-v/mpfs/icicle/configs/canfd/defconfig @@ -47,6 +47,8 @@ CONFIG_LIBC_STRERROR=y CONFIG_MEMSET_64BIT=y CONFIG_MEMSET_OPTSPEED=y CONFIG_MPFS_HAVE_CANFD=y +CONFIG_MPFS_CANFD0=y +CONFIG_MPFS_CANFD1=y CONFIG_MPFS_ENABLE_DPFPU=y CONFIG_MPFS_UART1=y CONFIG_NET=y From f83649ce06581d11fadf2f912a2d8e20fc1b0ded Mon Sep 17 00:00:00 2001 From: haitomatic Date: Tue, 16 May 2023 10:29:48 +0000 Subject: [PATCH 51/79] canfd : use board peripheral clock --- arch/risc-v/src/mpfs/Kconfig | 12 ------------ arch/risc-v/src/mpfs/mpfs_fpga_canfd.c | 4 ++-- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/arch/risc-v/src/mpfs/Kconfig b/arch/risc-v/src/mpfs/Kconfig index d55c1418d432c..a13d98ad3a86d 100644 --- a/arch/risc-v/src/mpfs/Kconfig +++ b/arch/risc-v/src/mpfs/Kconfig @@ -677,12 +677,6 @@ config MPFS_CANFD_BASE0 default 0x46000000 depends on MPFS_CANFD0 -config MPFS_CANFD_CLK0 - int "Clock frequency of the CANFD0 block (Hz)" - default 62500000 - range 1000000 100000000 - depends on MPFS_CANFD0 - config MPFS_CANFD_ARBI_BITRATE0 int "CANFD0 Arbitration phase bitrate" default 1000000 @@ -703,12 +697,6 @@ config MPFS_CANFD_BASE1 default 0x47000000 depends on MPFS_CANFD1 -config MPFS_CANFD_CLK1 - int "Clock frequency of the CANFD1 block (Hz)" - default 62500000 - range 1000000 100000000 - depends on MPFS_CANFD1 - config MPFS_CANFD_ARBI_BITRATE1 int "CANFD1 Arbitration phase bitrate" default 1000000 diff --git a/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c b/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c index 6262fa0869dd4..64910be0287eb 100644 --- a/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c +++ b/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c @@ -2891,7 +2891,7 @@ int mpfs_fpga_canfd_init(void) /* Get the can_clk info */ - priv0->can.clock.freq = CONFIG_MPFS_CANFD_CLK0; + priv0->can.clock.freq = MPFS_FPGA_PERIPHERAL_CLK; /* Needed for timing adjustment to be performed as soon as possible */ @@ -2991,7 +2991,7 @@ int mpfs_fpga_canfd_init(void) /* Get the can_clk info */ - priv1->can.clock.freq = CONFIG_MPFS_CANFD_CLK1; + priv1->can.clock.freq = MPFS_FPGA_PERIPHERAL_CLK; /* Needed for timing adjustment to be performed as soon as possible */ From 71c4864999b3728f68a42a0f86c45da35e971d2b Mon Sep 17 00:00:00 2001 From: haitomatic Date: Wed, 17 May 2023 10:59:20 +0000 Subject: [PATCH 52/79] canfd : normalize defconfig --- boards/risc-v/mpfs/icicle/configs/canfd/defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/risc-v/mpfs/icicle/configs/canfd/defconfig b/boards/risc-v/mpfs/icicle/configs/canfd/defconfig index 97d0ac1545c59..7bcc1380138d6 100644 --- a/boards/risc-v/mpfs/icicle/configs/canfd/defconfig +++ b/boards/risc-v/mpfs/icicle/configs/canfd/defconfig @@ -46,10 +46,10 @@ CONFIG_LIBC_PERROR_STDOUT=y CONFIG_LIBC_STRERROR=y CONFIG_MEMSET_64BIT=y CONFIG_MEMSET_OPTSPEED=y -CONFIG_MPFS_HAVE_CANFD=y CONFIG_MPFS_CANFD0=y CONFIG_MPFS_CANFD1=y CONFIG_MPFS_ENABLE_DPFPU=y +CONFIG_MPFS_HAVE_CANFD=y CONFIG_MPFS_UART1=y CONFIG_NET=y CONFIG_NETDEV_IFINDEX=y From 64290847f855852926f765d7e1a52bfa4cad0be4 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Fri, 19 May 2023 15:36:14 +0300 Subject: [PATCH 53/79] arch/risc-v/src/mpfs/mpfs_timerisr.c: Partially revert common mtime driver change Revert: commit 19758788356f8623bac5f439419e231ff81cac14 Author: Huang Qi Date: Mon Apr 11 18:42:24 2022 +0800 arch/risc-v: Apply common mtime driver to mtime based chps Signed-off-by: Huang Qi As this breaks the systick Signed-off-by: Jukka Laitinen --- arch/risc-v/src/mpfs/mpfs_timerisr.c | 76 ++++++++++++++++++++++++---- 1 file changed, 66 insertions(+), 10 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_timerisr.c b/arch/risc-v/src/mpfs/mpfs_timerisr.c index 3a43fa278f18e..b9db1e760d23c 100644 --- a/arch/risc-v/src/mpfs/mpfs_timerisr.c +++ b/arch/risc-v/src/mpfs/mpfs_timerisr.c @@ -24,7 +24,6 @@ #include -#include #include #include #include @@ -32,11 +31,8 @@ #include #include #include -#include -#include "hardware/mpfs_clint.h" #include "riscv_internal.h" -#include "riscv_mtimer.h" #include "mpfs.h" #include "mpfs_clockconfig.h" @@ -45,7 +41,62 @@ * Pre-processor Definitions ****************************************************************************/ -#define MTIMER_FREQ MPFS_MSS_RTC_TOGGLE_CLK +#define TICK_COUNT (MPFS_MSS_RTC_TOGGLE_CLK / TICK_PER_SEC) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static bool _b_tick_started; +static uint64_t *_mtime_cmp; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mpfs_reload_mtimecmp + ****************************************************************************/ + +static void mpfs_reload_mtimecmp(void) +{ + irqstate_t flags = spin_lock_irqsave(NULL); + + uint64_t current; + uint64_t next; + + if (!_b_tick_started) + { + _b_tick_started = true; + current = getreg64(MPFS_CLINT_MTIME); + } + else + { + current = getreg64(_mtime_cmp); + } + + uint64_t tick = TICK_COUNT; + next = current + tick; + + putreg64(next, _mtime_cmp); + + spin_unlock_irqrestore(NULL, flags); +} + +/**************************************************************************** + * Name: mpfs_timerisr + ****************************************************************************/ + +static int mpfs_timerisr(int irq, void *context, void *arg) +{ + mpfs_reload_mtimecmp(); + + /* Process timer interrupt */ + + nxsched_process_timer(); + + return 0; +} /**************************************************************************** * Public Functions @@ -65,12 +116,17 @@ void up_timer_initialize(void) /* what is our timecmp address for this hart */ uintptr_t hart_id = riscv_mhartid(); + _mtime_cmp = (uint64_t *)MPFS_CLINT_MTIMECMP0 + hart_id; + + /* Attach timer interrupt handler */ + + irq_attach(RISCV_IRQ_MTIMER, mpfs_timerisr, NULL); + + /* Reload CLINT mtimecmp */ - struct oneshot_lowerhalf_s *lower = riscv_mtimer_initialize( - MPFS_CLINT_MTIME, MPFS_CLINT_MTIMECMP0 + hart_id * sizeof(uintptr_t), - RISCV_IRQ_TIMER, MTIMER_FREQ); + mpfs_reload_mtimecmp(); - DEBUGASSERT(lower); + /* And enable the timer interrupt */ - up_alarm_set_lowerhalf(lower); + up_enable_irq(RISCV_IRQ_MTIMER); } From f34ce01ee06b756dfb874c8e08115d81cd609604 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Wed, 24 May 2023 07:09:52 +0300 Subject: [PATCH 54/79] arch/risc-v/src/mpfs: Make mpfs_hart_index2id table modifiable by bootloader This is actually the same table as entrypoints, so just use the same data, which can be set before booting any of the harts Signed-off-by: Jukka Laitinen --- arch/risc-v/src/mpfs/mpfs_entrypoints.c | 24 +++++++++++++++++++ arch/risc-v/src/mpfs/mpfs_entrypoints.h | 16 +++++++++++++ arch/risc-v/src/mpfs/mpfs_opensbi.c | 32 +++++++------------------ 3 files changed, 48 insertions(+), 24 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_entrypoints.c b/arch/risc-v/src/mpfs/mpfs_entrypoints.c index 44fe89f7117f0..7847a62aefc09 100644 --- a/arch/risc-v/src/mpfs/mpfs_entrypoints.c +++ b/arch/risc-v/src/mpfs/mpfs_entrypoints.c @@ -185,4 +185,28 @@ int mpfs_set_use_sbi(uint64_t hartid, bool use_sbi) return ERROR; } +/**************************************************************************** + * Name: mpfs_get_use_sbi + * + * Description: + * Get if hart boots via SBI. + * + * Input Parameters: + * hartid - hart id to check + * + * Returned value: + * true if SBI is used, false otherwise + * + ****************************************************************************/ + +bool mpfs_get_use_sbi(uint64_t hartid) +{ + if (hartid < ENTRYPT_CNT) + { + return (g_hart_use_sbi & (1 << hartid)) != 0; + } + + return false; +} + #endif /* CONFIG_MPFS_BOOTLOADER */ diff --git a/arch/risc-v/src/mpfs/mpfs_entrypoints.h b/arch/risc-v/src/mpfs/mpfs_entrypoints.h index 949972db74f2c..794b01974a691 100644 --- a/arch/risc-v/src/mpfs/mpfs_entrypoints.h +++ b/arch/risc-v/src/mpfs/mpfs_entrypoints.h @@ -86,6 +86,22 @@ int mpfs_set_entrypt(uint64_t hartid, uintptr_t entry); int mpfs_set_use_sbi(uint64_t hartid, bool use_sbi); +/**************************************************************************** + * Name: mpfs_get_use_sbi + * + * Description: + * Get if hart boots via SBI. + * + * Input Parameters: + * hartid - hart id to check + * + * Returned value: + * true if SBI is used, false otherwise + * + ****************************************************************************/ + +bool mpfs_get_use_sbi(uint64_t hartid); + #if defined(__cplusplus) } #endif diff --git a/arch/risc-v/src/mpfs/mpfs_opensbi.c b/arch/risc-v/src/mpfs/mpfs_opensbi.c index 769e9075a0d7b..c7d5a84d93d47 100644 --- a/arch/risc-v/src/mpfs/mpfs_opensbi.c +++ b/arch/risc-v/src/mpfs/mpfs_opensbi.c @@ -185,30 +185,7 @@ static struct aclint_mswi_data mpfs_mswi = * Unused hart is marked with -1. Mpfs will always have the hart0 unused. */ -static const u32 mpfs_hart_index2id[MPFS_HART_COUNT] = -{ - [0] = -1, -#ifdef CONFIG_MPFS_HART1_SBI - [1] = 1, -#else - [1] = -1, -#endif -#ifdef CONFIG_MPFS_HART2_SBI - [2] = 2, -#else - [2] = -1, -#endif -#ifdef CONFIG_MPFS_HART3_SBI - [3] = 3, -#else - [3] = -1, -#endif -#ifdef CONFIG_MPFS_HART4_SBI - [4] = 4, -#else - [4] = -1, -#endif -}; +static u32 mpfs_hart_index2id[MPFS_HART_COUNT]; static const struct sbi_platform platform = { @@ -602,6 +579,13 @@ static int mpfs_opensbi_ecall_handler(long extid, long funcid, void __attribute__((noreturn)) mpfs_opensbi_setup(void) { uint32_t hartid = current_hartid(); + size_t i; + + for (i = 0; i < sizeof(mpfs_hart_index2id) / sizeof(mpfs_hart_index2id[0]); + i++) + { + mpfs_hart_index2id[i] = mpfs_get_use_sbi(i) ? i : -1; + } mpfs_opensbi_pmp_setup(); From b400e7ae57d4d77ff10cae1d31b36599f11d957a Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Wed, 24 May 2023 11:47:59 +0300 Subject: [PATCH 55/79] Revert "[REVERTME] arch/risc-v/src/mpfs/mpfs_corespi.c: Hack around a bug in nuttx nxsem_tickwait_uninterruptible bug" This reverts commit c9a794c8290e314d4824d2f2c086f309b97d6fcf. --- arch/risc-v/src/mpfs/mpfs_corespi.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_corespi.c b/arch/risc-v/src/mpfs/mpfs_corespi.c index 874293a83e365..43b1cacf3abe5 100644 --- a/arch/risc-v/src/mpfs/mpfs_corespi.c +++ b/arch/risc-v/src/mpfs/mpfs_corespi.c @@ -709,13 +709,7 @@ static int mpfs_spi_sem_waitdone(struct mpfs_spi_priv_s *priv) { uint32_t timeout = SPI_TTOA_US(priv->txwords * priv->nbits, priv->actual); timeout += SPI_TTOA_MARGIN_US; - - /* Hack: add +1 to timeout due to some bug in NuttX. It randomly timeouts - * one tick too early - */ - - return nxsem_tickwait_uninterruptible(&priv->sem_isr, USEC2TICK(timeout) + - 1); + return nxsem_tickwait_uninterruptible(&priv->sem_isr, USEC2TICK(timeout)); } /**************************************************************************** From d9c727601f3df8421dd0e83c9fa501fecf0585e5 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Wed, 24 May 2023 12:55:54 +0300 Subject: [PATCH 56/79] mpfs_timerisr: Add patch to make the code work in CONFIG_BUILD_KERNEL --- arch/risc-v/src/mpfs/mpfs_timerisr.c | 47 ++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_timerisr.c b/arch/risc-v/src/mpfs/mpfs_timerisr.c index b9db1e760d23c..b8c635811fef9 100644 --- a/arch/risc-v/src/mpfs/mpfs_timerisr.c +++ b/arch/risc-v/src/mpfs/mpfs_timerisr.c @@ -47,13 +47,41 @@ * Private Data ****************************************************************************/ +#ifndef CONFIG_BUILD_KERNEL static bool _b_tick_started; static uint64_t *_mtime_cmp; +#endif /**************************************************************************** * Private Functions ****************************************************************************/ +static uint64_t get_current(void) +{ +#ifndef CONFIG_BUILD_KERNEL + if (!_b_tick_started) + { + _b_tick_started = true; + return getreg64(MPFS_CLINT_MTIME); + } + else + { + return getreg64(_mtime_cmp); + } +#else + return riscv_sbi_get_time(); +#endif +} + +static void set_next(uint64_t next) +{ +#ifndef CONFIG_BUILD_KERNEL + putreg64(next, _mtime_cmp); +#else + riscv_sbi_set_timer(next); +#endif +} + /**************************************************************************** * Name: mpfs_reload_mtimecmp ****************************************************************************/ @@ -65,20 +93,11 @@ static void mpfs_reload_mtimecmp(void) uint64_t current; uint64_t next; - if (!_b_tick_started) - { - _b_tick_started = true; - current = getreg64(MPFS_CLINT_MTIME); - } - else - { - current = getreg64(_mtime_cmp); - } - + current = get_current(); uint64_t tick = TICK_COUNT; next = current + tick; - putreg64(next, _mtime_cmp); + set_next(next); spin_unlock_irqrestore(NULL, flags); } @@ -113,14 +132,16 @@ static int mpfs_timerisr(int irq, void *context, void *arg) void up_timer_initialize(void) { +#ifndef CONFIG_BUILD_KERNEL /* what is our timecmp address for this hart */ uintptr_t hart_id = riscv_mhartid(); _mtime_cmp = (uint64_t *)MPFS_CLINT_MTIMECMP0 + hart_id; +#endif /* Attach timer interrupt handler */ - irq_attach(RISCV_IRQ_MTIMER, mpfs_timerisr, NULL); + irq_attach(RISCV_IRQ_TIMER, mpfs_timerisr, NULL); /* Reload CLINT mtimecmp */ @@ -128,5 +149,5 @@ void up_timer_initialize(void) /* And enable the timer interrupt */ - up_enable_irq(RISCV_IRQ_MTIMER); + up_enable_irq(RISCV_IRQ_TIMER); } From c312a3bcef27aaca9f0f77a34a1a80dafab34ab5 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Thu, 25 May 2023 10:19:50 +0300 Subject: [PATCH 57/79] arch/risc-v/src/mpfs/mpfs_opensbi.c: Fix conflicting datatypes defined by NuttX vs. opensbi Signed-off-by: Jukka Laitinen --- arch/risc-v/src/mpfs/mpfs_opensbi.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_opensbi.c b/arch/risc-v/src/mpfs/mpfs_opensbi.c index c7d5a84d93d47..7544ec493b503 100644 --- a/arch/risc-v/src/mpfs/mpfs_opensbi.c +++ b/arch/risc-v/src/mpfs/mpfs_opensbi.c @@ -28,8 +28,31 @@ #include #ifdef CONFIG_MPFS_IHC_SBI #include +#include +#endif +#include "mpfs_entrypoints.h" + +/* Make sure that anything that intefraces with the SBI uses the same data + * types as the SBI code (e.g. same "bool") + */ + +#ifdef bool +#undef bool +#endif + +#ifdef true +#undef true #endif +#ifdef false +#undef false +#endif + +#ifdef NULL +#undef NULL +#endif + +#include #include #include #include @@ -41,10 +64,6 @@ #include #include -#ifdef CONFIG_MPFS_IHC_SBI -#include -#endif - /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ From c688040137d51841fd6999163c5cea3417f6bb9c Mon Sep 17 00:00:00 2001 From: haitomatic Date: Mon, 22 May 2023 13:11:36 +0000 Subject: [PATCH 58/79] net/can, net/devif: fix CAN RX/TX iob free semcount runaway issue --- net/can/can_callback.c | 16 +++++++++++++++ net/can/can_recvmsg.c | 45 +++++++++++++++++++++++------------------- net/devif/devif_send.c | 7 ++++++- 3 files changed, 47 insertions(+), 21 deletions(-) diff --git a/net/can/can_callback.c b/net/can/can_callback.c index d8ebfc65506ef..ac5de920937f5 100644 --- a/net/can/can_callback.c +++ b/net/can/can_callback.c @@ -62,6 +62,9 @@ can_data_event(FAR struct net_driver_s *dev, FAR struct can_conn_s *conn, uint16_t flags) { int buflen = dev->d_len; +#ifdef CONFIG_NET_TIMESTAMP + buflen -= sizeof(struct timeval); +#endif uint16_t recvlen; uint16_t ret; @@ -133,6 +136,19 @@ uint16_t can_callback(FAR struct net_driver_s *dev, if ((flags & CAN_NEWDATA) != 0) { + if (dev->d_iob->io_flink != NULL || + dev->d_iob->io_pktlen == 0 || + dev->d_iob->io_offset <= 0) + { + if (dev->d_iob->io_flink == NULL) + { + iob_free(dev->d_iob); + } + + netdev_iob_clear(dev); + return flags; + } + #ifdef CONFIG_NET_TIMESTAMP /* TIMESTAMP sockopt is activated, * create timestamp and copy to iob diff --git a/net/can/can_recvmsg.c b/net/can/can_recvmsg.c index 66639d42eee22..b03344bdcd10c 100644 --- a/net/can/can_recvmsg.c +++ b/net/can/can_recvmsg.c @@ -232,6 +232,19 @@ static inline int can_readahead(struct can_recvfrom_s *pstate) if ((iob = iob_peek_queue(&conn->readahead)) != NULL && pstate->pr_buflen > 0) { + if (iob->io_flink != NULL || + iob->io_pktlen == 0 || + iob->io_offset <= 0) + { + if (iob->io_pktlen == 0 || iob->io_offset <= 0) + { + iob_free(iob); + } + + iob_remove_queue(&conn->readahead); + return 0; + } + DEBUGASSERT(iob->io_pktlen > 0); #ifdef CONFIG_NET_TIMESTAMP @@ -254,31 +267,23 @@ static inline int can_readahead(struct can_recvfrom_s *pstate) * beginning of the I/O buffer chain. */ - if (recvlen >= iob->io_pktlen) - { - FAR struct iob_s *tmp; + /* No trimming needed since one CAN/CANFD frame can perfectly + * fit in one iob + */ - /* Remove the I/O buffer chain from the head of the read-ahead - * buffer queue. - */ + FAR struct iob_s *tmp; - tmp = iob_remove_queue(&conn->readahead); - DEBUGASSERT(tmp == iob); - UNUSED(tmp); + /* Remove the I/O buffer chain from the head of the read-ahead + * buffer queue. + */ - /* And free the I/O buffer chain */ + tmp = iob_remove_queue(&conn->readahead); + DEBUGASSERT(tmp == iob); + UNUSED(tmp); - iob_free_chain(iob); - } - else - { - /* The bytes that we have received from the head of the I/O - * buffer chain (probably changing the head of the I/O - * buffer queue). - */ + /* And free the I/O buffer chain */ - iob_trimhead_queue(&conn->readahead, recvlen); - } + iob_free_chain(iob); /* do not pass frames with DLC > 8 to a legacy socket */ #if defined(CONFIG_NET_CANPROTO_OPTIONS) && defined(CONFIG_NET_CAN_CANFD) diff --git a/net/devif/devif_send.c b/net/devif/devif_send.c index 943b737bbdba4..15ec735f7cfbf 100644 --- a/net/devif/devif_send.c +++ b/net/devif/devif_send.c @@ -102,7 +102,12 @@ int devif_send(FAR struct net_driver_s *dev, FAR const void *buf, /* Prepare device buffer before poll callback */ - iob_update_pktlen(dev->d_iob, offset, false); + /* if pktlen is 0, no need to update */ + + if (offset != 0) + { + iob_update_pktlen(dev->d_iob, offset, false); + } ret = iob_trycopyin(dev->d_iob, buf, len, offset, false); if (ret != len) From 226dbd98f2d9ff7e45fe5e7117294b4d267ddd31 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Fri, 16 Jun 2023 09:41:43 +0300 Subject: [PATCH 59/79] arch/risc-v/src/mpfs/mpfs_dsn: Correct serial number reading routine - Fix retry counter handling and increase the maximum number of retries. - Add some parenthesis for clarity. - Change return type to signed int, as it may return -ETIMEDOUT - Correct comment for returned value Signed-off-by: Jukka Laitinen --- arch/risc-v/src/mpfs/mpfs_dsn.c | 12 ++++++------ arch/risc-v/src/mpfs/mpfs_dsn.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_dsn.c b/arch/risc-v/src/mpfs/mpfs_dsn.c index 9558049d54be8..e745976253b07 100644 --- a/arch/risc-v/src/mpfs/mpfs_dsn.c +++ b/arch/risc-v/src/mpfs/mpfs_dsn.c @@ -53,7 +53,7 @@ /* Retry count */ -#define RETRIES 100 +#define RETRIES 500 /**************************************************************************** * Public Functions @@ -70,11 +70,11 @@ * len - Number of bytes to read * * Returned Value: - * Number of bytes read, -1 on error + * Number of bytes read, -ETIMEDOUT on error * ****************************************************************************/ -size_t mpfs_read_dsn(uint8_t *dsn, size_t len) +int mpfs_read_dsn(uint8_t *dsn, size_t len) { uint32_t reg; uint8_t *p = (uint8_t *)MSS_SCBMAILBOX; @@ -86,7 +86,7 @@ size_t mpfs_read_dsn(uint8_t *dsn, size_t len) * using the system controller services */ - while (getreg32(SERVICES_SR) & SCBCTRL_SERVICESSR_BUSY && retries-- > 0) + while ((getreg32(SERVICES_SR) & SCBCTRL_SERVICESSR_BUSY) && --retries > 0) { leave_critical_section(flags); usleep(1000); @@ -118,7 +118,7 @@ size_t mpfs_read_dsn(uint8_t *dsn, size_t len) { reg = getreg32(SERVICES_CR); } - while (reg & SCBCTRL_SERVICESCR_REQ && retries-- > 0); + while ((reg & SCBCTRL_SERVICESCR_REQ) && --retries); if (retries == 0) { @@ -132,7 +132,7 @@ size_t mpfs_read_dsn(uint8_t *dsn, size_t len) { reg = getreg32(SERVICES_SR); } - while (reg & SCBCTRL_SERVICESSR_BUSY && retries-- > 0); + while ((reg & SCBCTRL_SERVICESSR_BUSY) && --retries); if (retries == 0) { diff --git a/arch/risc-v/src/mpfs/mpfs_dsn.h b/arch/risc-v/src/mpfs/mpfs_dsn.h index 4843d9a12e06a..825d3019a41a1 100644 --- a/arch/risc-v/src/mpfs/mpfs_dsn.h +++ b/arch/risc-v/src/mpfs/mpfs_dsn.h @@ -70,7 +70,7 @@ extern "C" * ****************************************************************************/ -size_t mpfs_read_dsn(uint8_t *dsn, size_t len); +int mpfs_read_dsn(uint8_t *dsn, size_t len); #ifdef __cplusplus } From 96cc3b4827cb25c71219c82d9ddbc3a074ed5147 Mon Sep 17 00:00:00 2001 From: Eero Nurkkala Date: Wed, 21 Jun 2023 15:11:05 +0300 Subject: [PATCH 60/79] risc-v/mpfs: clean up ihc for rpmsg This cleans the unnecessary flow control that's no longer needed. Probably the support for simultaneous MP and ACK changed the environment. Also reorganize the mpfs_opensbi_*.S so that the trap handler is easily relocated in the tlinker .ld file without the need to relocate the utils.S. This makes it easier to follow the jump into other segment, eg. zerodevice. Signed-off-by: Eero Nurkkala --- arch/risc-v/src/mpfs/Make.defs | 1 + arch/risc-v/src/mpfs/mpfs_ihc.c | 51 +---- arch/risc-v/src/mpfs/mpfs_ihc_sbi.c | 58 ++++-- arch/risc-v/src/mpfs/mpfs_opensbi_trap.S | 224 ++++++++++++++++++++++ arch/risc-v/src/mpfs/mpfs_opensbi_utils.S | 206 ++------------------ 5 files changed, 286 insertions(+), 254 deletions(-) create mode 100644 arch/risc-v/src/mpfs/mpfs_opensbi_trap.S diff --git a/arch/risc-v/src/mpfs/Make.defs b/arch/risc-v/src/mpfs/Make.defs index bbe2a0642dd5c..2692647db7a59 100644 --- a/arch/risc-v/src/mpfs/Make.defs +++ b/arch/risc-v/src/mpfs/Make.defs @@ -88,6 +88,7 @@ endif ifeq (${CONFIG_MPFS_OPENSBI},y) CHIP_ASRCS += mpfs_opensbi_utils.S +CHIP_ASRCS += mpfs_opensbi_trap.S CHIP_CSRCS += mpfs_opensbi.c endif diff --git a/arch/risc-v/src/mpfs/mpfs_ihc.c b/arch/risc-v/src/mpfs/mpfs_ihc.c index aa34f1d603b4c..c031af596beee 100644 --- a/arch/risc-v/src/mpfs/mpfs_ihc.c +++ b/arch/risc-v/src/mpfs/mpfs_ihc.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include @@ -650,8 +649,6 @@ static void mpfs_ihc_message_present_isr(void) /* Process incoming packet */ - irqstate_t flags = spin_lock_irqsave(NULL); - mpfs_ihc_rx_message(origin_hart, mhartid, is_ack, is_msg, NULL); if (is_ack) @@ -661,8 +658,6 @@ static void mpfs_ihc_message_present_isr(void) modifyreg32(MPFS_IHC_CTRL(mhartid, origin_hart), ACK_CLR, 0); } - - spin_unlock_irqrestore(NULL, flags); } } @@ -783,7 +778,6 @@ static int mpfs_ihc_tx_message(ihc_channel_t channel, uint32_t *message) uint32_t message_size = getreg32(MPFS_IHC_MSG_SIZE(mhartid, rhartid)); uint32_t ctrl_reg; uint32_t retries = 10000; - irqstate_t flags; DEBUGASSERT(message_size <= IHC_MAX_MESSAGE_SIZE); @@ -807,8 +801,6 @@ static int mpfs_ihc_tx_message(ihc_channel_t channel, uint32_t *message) } else { - flags = spin_lock_irqsave(NULL); - /* Fill the buffer */ for (i = 0; i < message_size; i++) @@ -820,9 +812,8 @@ static int mpfs_ihc_tx_message(ihc_channel_t channel, uint32_t *message) /* If we're unlucky, we cannot send MP yet.. come back later */ - if (ctrl_reg & (ACK_INT | MP_MESSAGE_PRESENT)) + if (ctrl_reg & (MP_MESSAGE_PRESENT)) { - spin_unlock_irqrestore(NULL, flags); return -EBUSY; } @@ -830,8 +821,6 @@ static int mpfs_ihc_tx_message(ihc_channel_t channel, uint32_t *message) modifyreg32(MPFS_IHC_CTRL(mhartid, rhartid), 0, RMP_MESSAGE_PRESENT); - spin_unlock_irqrestore(NULL, flags); - /* Wait for the ACK to arrive to maintain the logic */ if (mhartid == CONTEXTB_HARTID) @@ -1091,25 +1080,9 @@ static int mpfs_rptun_stop(struct rptun_dev_s *dev) static int mpfs_rptun_notify(struct rptun_dev_s *dev, uint32_t notifyid) { uint32_t tx_msg[IHC_MAX_MESSAGE_SIZE]; - uint32_t retries = 10000; - uint32_t flow_ctrl_en; + uint32_t retries = 5; int ret = OK; - /* INT_EN(0) is used by the bootloader (Linux) to indicate that - * it will be sending data. Wait until it finishes first. - */ - - flow_ctrl_en = getreg32(MPFS_IHC_INT_EN(0)); - - if (flow_ctrl_en != 0) - { - do - { - flow_ctrl_en = getreg32(MPFS_IHC_INT_EN(0)); - } - while ((flow_ctrl_en != 0) && --retries); - } - /* We only care about the queue with notifyid VRING0 */ if (notifyid == VRING0_NOTIFYID) @@ -1117,21 +1090,15 @@ static int mpfs_rptun_notify(struct rptun_dev_s *dev, uint32_t notifyid) tx_msg[0] = notifyid; tx_msg[1] = 0; - ret = mpfs_ihc_tx_message(CONTEXTA_HARTID, tx_msg); - if (ret != OK) - { - retries = 5; - - /* This failure should happen very rarely */ - - do - { - ret = mpfs_ihc_tx_message(CONTEXTA_HARTID, tx_msg); - } - while ((ret != OK) && --retries); + /* This failure should happen very rarely */ - DEBUGASSERT(ret == OK); + do + { + ret = mpfs_ihc_tx_message(CONTEXTA_HARTID, tx_msg); } + while ((ret != OK) && --retries); + + DEBUGASSERT(ret == OK); } return ret; diff --git a/arch/risc-v/src/mpfs/mpfs_ihc_sbi.c b/arch/risc-v/src/mpfs/mpfs_ihc_sbi.c index 923faf9d032fe..aa77f022fd2b3 100644 --- a/arch/risc-v/src/mpfs/mpfs_ihc_sbi.c +++ b/arch/risc-v/src/mpfs/mpfs_ihc_sbi.c @@ -67,6 +67,34 @@ static uint32_t g_connected_harts_c; * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: mpfs_modifyreg32 + * + * Description: + * This is a copy of modifyreg32() without spinlock. That function is a + * real danger here as it is likely located in eNVM, thus being a real + * bottleneck. + * + * Input Parameters: + * addr - Address to perform the operation + * clearbits - Bits to clear + * setbits - Bits to set + * + * Returned Value: + * Remote hart id + * + ****************************************************************************/ + +void mpfs_modifyreg32(uintptr_t addr, uint32_t clearbits, uint32_t setbits) +{ + uint32_t regval; + + regval = getreg32(addr); + regval &= ~clearbits; + regval |= setbits; + putreg32(regval, addr); +} + /**************************************************************************** * Name: mpfs_ihc_sbi_parse_incoming_hartid * @@ -338,7 +366,7 @@ static void mpfs_ihc_sbi_rx_message(uint32_t rhartid, uint32_t mhartid, /* Clear the ack */ - modifyreg32(MPFS_IHC_CTRL(mhartid, rhartid), ACK_CLR, 0); + mpfs_modifyreg32(MPFS_IHC_CTRL(mhartid, rhartid), ACK_CLR, 0); } } else if (is_mp && !is_ack) @@ -362,7 +390,7 @@ static void mpfs_ihc_sbi_rx_message(uint32_t rhartid, uint32_t mhartid, * if it has RMPIE bit set in the control register */ - modifyreg32(MPFS_IHC_CTRL(mhartid, rhartid), MP_MASK, ACK_INT); + mpfs_modifyreg32(MPFS_IHC_CTRL(mhartid, rhartid), MP_MASK, ACK_INT); } else if (is_ack && is_mp) { @@ -372,8 +400,8 @@ static void mpfs_ihc_sbi_rx_message(uint32_t rhartid, uint32_t mhartid, /* Clear the ack and mp */ - modifyreg32(MPFS_IHC_CTRL(mhartid, rhartid), ACK_CLR | MP_MASK, - ACK_INT); + mpfs_modifyreg32(MPFS_IHC_CTRL(mhartid, rhartid), ACK_CLR | MP_MASK, + ACK_INT); } } @@ -485,16 +513,16 @@ static void mpfs_ihc_sbi_local_remote_config(uint32_t hart_to_configure, } #endif - modifyreg32(MPFS_IHC_CTRL(hart_to_configure, rhartid), 0, MPIE_EN | - ACKIE_EN); + mpfs_modifyreg32(MPFS_IHC_CTRL(hart_to_configure, rhartid), 0, MPIE_EN | + ACKIE_EN); /* OpenSBI extension may configure 2x consecutive harts */ #ifdef CONFIG_MPFS_IHC_TWO_RPMSG_CHANNELS if ((hart_to_configure + 1) < MPFS_NUM_HARTS) { - modifyreg32(MPFS_IHC_CTRL(hart_to_configure + 1, rhartid + 1), 0, - MPIE_EN | ACKIE_EN); + mpfs_modifyreg32(MPFS_IHC_CTRL(hart_to_configure + 1, rhartid + 1), 0, + MPIE_EN | ACKIE_EN); } #endif } @@ -554,7 +582,8 @@ static int mpfs_ihc_sbi_tx_message(ihc_channel_t channel, uint32_t *message) /* Set the MP bit. This will notify other of incoming hart message */ - modifyreg32(MPFS_IHC_CTRL(mhartid, rhartid), 0, RMP_MESSAGE_PRESENT); + mpfs_modifyreg32(MPFS_IHC_CTRL(mhartid, rhartid), 0, + RMP_MESSAGE_PRESENT); } return OK; @@ -643,23 +672,12 @@ int mpfs_ihc_sbi_ecall_handler(unsigned long funcid, uint32_t remote_channel, * meanwhile with the SW flow control. */ - modifyreg32(MPFS_IHC_INT_EN(0), 0, 1); /* Flow contol on */ result = mpfs_ihc_sbi_tx_message(remote_channel, message_ptr); break; case SBI_EXT_IHC_RECEIVE: mpfs_ihc_sbi_message_present_indirect_isr(remote_channel, message_ptr); - - /* ACK_IRQ indicates the end of the IHC_SEND transaction */ - - struct ihc_sbi_rx_msg_s *msg; - msg = (struct ihc_sbi_rx_msg_s *)message_ptr; - - if (msg->irq_type & ACK_IRQ) - { - modifyreg32(MPFS_IHC_INT_EN(0), 1, 0); /* Flow contol off */ - } break; default: diff --git a/arch/risc-v/src/mpfs/mpfs_opensbi_trap.S b/arch/risc-v/src/mpfs/mpfs_opensbi_trap.S new file mode 100644 index 0000000000000..e046861201e13 --- /dev/null +++ b/arch/risc-v/src/mpfs/mpfs_opensbi_trap.S @@ -0,0 +1,224 @@ +/**************************************************************************** + * arch/risc-v/src/mpfs/mpfs_opensbi_trap.S + * + * mpfs_exception_opensbi function is based on OpenSBI fw_base.S + * + * The 2-Clause BSD License + * SPDX short identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates and other + * contributors. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Symbols + ****************************************************************************/ + + .global mpfs_exception_opensbi + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +mpfs_global_pointer: + .dword __global_pointer$ + +/**************************************************************************** + * Name: mpfs_exception_opensbi: + * + * Description: + * This is the trap entry into OpenSBI. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + + .align 3 + mpfs_exception_opensbi: + /* Swap TP and MSCRATCH */ + + csrrw tp, CSR_MSCRATCH, tp + + /* Save T0 in scratch space */ + + REG_S t0, SBI_SCRATCH_TMP0_OFFSET(tp) + + /* + * Set T0 to appropriate exception stack + * + * Came_From_M_Mode = ((MSTATUS.MPP < PRV_M) ? 1 : 0) - 1; + * Exception_Stack = TP ^ (Came_From_M_Mode & (SP ^ TP)) + * + * Came_From_M_Mode = 0 ==> Exception_Stack = TP + * Came_From_M_Mode = -1 ==> Exception_Stack = SP + */ + + csrr t0, CSR_MSTATUS + srl t0, t0, MSTATUS_MPP_SHIFT + and t0, t0, PRV_M + slti t0, t0, PRV_M + add t0, t0, -1 + xor sp, sp, tp + and t0, t0, sp + xor sp, sp, tp + xor t0, tp, t0 + + /* Save original SP on exception stack */ + + REG_S sp, (SBI_TRAP_REGS_OFFSET(sp) - SBI_TRAP_REGS_SIZE)(t0) + + /* Set SP to exception stack and make room for trap registers */ + + add sp, t0, -(SBI_TRAP_REGS_SIZE) + + /* Restore T0 from scratch space */ + + REG_L t0, SBI_SCRATCH_TMP0_OFFSET(tp) + + /* Save T0 on stack */ + + REG_S t0, SBI_TRAP_REGS_OFFSET(t0)(sp) + + /* Swap TP and MSCRATCH */ + + csrrw tp, CSR_MSCRATCH, tp + + /* Save MEPC and MSTATUS CSRs */ + + csrr t0, CSR_MEPC + REG_S t0, SBI_TRAP_REGS_OFFSET(mepc)(sp) + csrr t0, CSR_MSTATUS + REG_S t0, SBI_TRAP_REGS_OFFSET(mstatus)(sp) + REG_S zero, SBI_TRAP_REGS_OFFSET(mstatusH)(sp) + + /* Save all general regisers except SP and T0 */ + + REG_S zero, SBI_TRAP_REGS_OFFSET(zero)(sp) + REG_S ra, SBI_TRAP_REGS_OFFSET(ra)(sp) + REG_S gp, SBI_TRAP_REGS_OFFSET(gp)(sp) + REG_S tp, SBI_TRAP_REGS_OFFSET(tp)(sp) + REG_S t1, SBI_TRAP_REGS_OFFSET(t1)(sp) + REG_S t2, SBI_TRAP_REGS_OFFSET(t2)(sp) + REG_S s0, SBI_TRAP_REGS_OFFSET(s0)(sp) + REG_S s1, SBI_TRAP_REGS_OFFSET(s1)(sp) + REG_S a0, SBI_TRAP_REGS_OFFSET(a0)(sp) + REG_S a1, SBI_TRAP_REGS_OFFSET(a1)(sp) + REG_S a2, SBI_TRAP_REGS_OFFSET(a2)(sp) + REG_S a3, SBI_TRAP_REGS_OFFSET(a3)(sp) + REG_S a4, SBI_TRAP_REGS_OFFSET(a4)(sp) + REG_S a5, SBI_TRAP_REGS_OFFSET(a5)(sp) + REG_S a6, SBI_TRAP_REGS_OFFSET(a6)(sp) + REG_S a7, SBI_TRAP_REGS_OFFSET(a7)(sp) + REG_S s2, SBI_TRAP_REGS_OFFSET(s2)(sp) + REG_S s3, SBI_TRAP_REGS_OFFSET(s3)(sp) + REG_S s4, SBI_TRAP_REGS_OFFSET(s4)(sp) + REG_S s5, SBI_TRAP_REGS_OFFSET(s5)(sp) + REG_S s6, SBI_TRAP_REGS_OFFSET(s6)(sp) + REG_S s7, SBI_TRAP_REGS_OFFSET(s7)(sp) + REG_S s8, SBI_TRAP_REGS_OFFSET(s8)(sp) + REG_S s9, SBI_TRAP_REGS_OFFSET(s9)(sp) + REG_S s10, SBI_TRAP_REGS_OFFSET(s10)(sp) + REG_S s11, SBI_TRAP_REGS_OFFSET(s11)(sp) + REG_S t3, SBI_TRAP_REGS_OFFSET(t3)(sp) + REG_S t4, SBI_TRAP_REGS_OFFSET(t4)(sp) + REG_S t5, SBI_TRAP_REGS_OFFSET(t5)(sp) + REG_S t6, SBI_TRAP_REGS_OFFSET(t6)(sp) + + /* Restore GP */ + + la a0, mpfs_global_pointer + ld gp, 0(a0) + + /* Call C routine */ + + add a0, sp, zero + call sbi_trap_handler + + /* Restore all general regisers except A0 and T0 */ + + REG_L ra, SBI_TRAP_REGS_OFFSET(ra)(a0) + REG_L sp, SBI_TRAP_REGS_OFFSET(sp)(a0) + REG_L gp, SBI_TRAP_REGS_OFFSET(gp)(a0) + REG_L tp, SBI_TRAP_REGS_OFFSET(tp)(a0) + REG_L t1, SBI_TRAP_REGS_OFFSET(t1)(a0) + REG_L t2, SBI_TRAP_REGS_OFFSET(t2)(a0) + REG_L s0, SBI_TRAP_REGS_OFFSET(s0)(a0) + REG_L s1, SBI_TRAP_REGS_OFFSET(s1)(a0) + REG_L a1, SBI_TRAP_REGS_OFFSET(a1)(a0) + REG_L a2, SBI_TRAP_REGS_OFFSET(a2)(a0) + REG_L a3, SBI_TRAP_REGS_OFFSET(a3)(a0) + REG_L a4, SBI_TRAP_REGS_OFFSET(a4)(a0) + REG_L a5, SBI_TRAP_REGS_OFFSET(a5)(a0) + REG_L a6, SBI_TRAP_REGS_OFFSET(a6)(a0) + REG_L a7, SBI_TRAP_REGS_OFFSET(a7)(a0) + REG_L s2, SBI_TRAP_REGS_OFFSET(s2)(a0) + REG_L s3, SBI_TRAP_REGS_OFFSET(s3)(a0) + REG_L s4, SBI_TRAP_REGS_OFFSET(s4)(a0) + REG_L s5, SBI_TRAP_REGS_OFFSET(s5)(a0) + REG_L s6, SBI_TRAP_REGS_OFFSET(s6)(a0) + REG_L s7, SBI_TRAP_REGS_OFFSET(s7)(a0) + REG_L s8, SBI_TRAP_REGS_OFFSET(s8)(a0) + REG_L s9, SBI_TRAP_REGS_OFFSET(s9)(a0) + REG_L s10, SBI_TRAP_REGS_OFFSET(s10)(a0) + REG_L s11, SBI_TRAP_REGS_OFFSET(s11)(a0) + REG_L t3, SBI_TRAP_REGS_OFFSET(t3)(a0) + REG_L t4, SBI_TRAP_REGS_OFFSET(t4)(a0) + REG_L t5, SBI_TRAP_REGS_OFFSET(t5)(a0) + REG_L t6, SBI_TRAP_REGS_OFFSET(t6)(a0) + + /* Restore MEPC and MSTATUS CSRs */ + + REG_L t0, SBI_TRAP_REGS_OFFSET(mepc)(a0) + csrw CSR_MEPC, t0 + REG_L t0, SBI_TRAP_REGS_OFFSET(mstatus)(a0) + csrw CSR_MSTATUS, t0 + + /* Restore T0 */ + + REG_L t0, SBI_TRAP_REGS_OFFSET(t0)(a0) + + /* Restore A0 */ + + REG_L a0, SBI_TRAP_REGS_OFFSET(a0)(a0) + + mret diff --git a/arch/risc-v/src/mpfs/mpfs_opensbi_utils.S b/arch/risc-v/src/mpfs/mpfs_opensbi_utils.S index b933bdb5d4495..db8f8fff7f738 100644 --- a/arch/risc-v/src/mpfs/mpfs_opensbi_utils.S +++ b/arch/risc-v/src/mpfs/mpfs_opensbi_utils.S @@ -1,34 +1,22 @@ /**************************************************************************** * arch/risc-v/src/mpfs/mpfs_opensbi_utils.S * - * mpfs_exception_opensbi function is based on OpenSBI fw_base.S + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at * - * The 2-Clause BSD License - * SPDX short identifier: BSD-2-Clause + * http://www.apache.org/licenses/LICENSE-2.0 * - * Copyright (c) 2019 Western Digital Corporation or its affiliates and other - * contributors. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ + ****************************************************************************/ /**************************************************************************** * Included Files @@ -51,7 +39,6 @@ ****************************************************************************/ .global mpfs_opensbi_prepare_hart - .global mpfs_exception_opensbi /**************************************************************************** * Private Data @@ -103,169 +90,4 @@ mpfs_opensbi_prepare_hart: mul t0, a0, t1 la sp, g_scratches add sp, sp, t0 - jal mpfs_opensbi_setup - -/**************************************************************************** - * Name: mpfs_exception_opensbi: - * - * Description: - * This is the trap entry into OpenSBI. - * - * Input Parameters: - * None - * - * Returned Value: - * None - * - ****************************************************************************/ - - .align 3 -mpfs_exception_opensbi: - - /* Swap TP and MSCRATCH */ - - csrrw tp, CSR_MSCRATCH, tp - - /* Save T0 in scratch space */ - - REG_S t0, SBI_SCRATCH_TMP0_OFFSET(tp) - - /* - * Set T0 to appropriate exception stack - * - * Came_From_M_Mode = ((MSTATUS.MPP < PRV_M) ? 1 : 0) - 1; - * Exception_Stack = TP ^ (Came_From_M_Mode & (SP ^ TP)) - * - * Came_From_M_Mode = 0 ==> Exception_Stack = TP - * Came_From_M_Mode = -1 ==> Exception_Stack = SP - */ - - csrr t0, CSR_MSTATUS - srl t0, t0, MSTATUS_MPP_SHIFT - and t0, t0, PRV_M - slti t0, t0, PRV_M - add t0, t0, -1 - xor sp, sp, tp - and t0, t0, sp - xor sp, sp, tp - xor t0, tp, t0 - - /* Save original SP on exception stack */ - - REG_S sp, (SBI_TRAP_REGS_OFFSET(sp) - SBI_TRAP_REGS_SIZE)(t0) - - /* Set SP to exception stack and make room for trap registers */ - - add sp, t0, -(SBI_TRAP_REGS_SIZE) - - /* Restore T0 from scratch space */ - - REG_L t0, SBI_SCRATCH_TMP0_OFFSET(tp) - - /* Save T0 on stack */ - - REG_S t0, SBI_TRAP_REGS_OFFSET(t0)(sp) - - /* Swap TP and MSCRATCH */ - - csrrw tp, CSR_MSCRATCH, tp - - /* Save MEPC and MSTATUS CSRs */ - - csrr t0, CSR_MEPC - REG_S t0, SBI_TRAP_REGS_OFFSET(mepc)(sp) - csrr t0, CSR_MSTATUS - REG_S t0, SBI_TRAP_REGS_OFFSET(mstatus)(sp) - REG_S zero, SBI_TRAP_REGS_OFFSET(mstatusH)(sp) - - /* Save all general regisers except SP and T0 */ - - REG_S zero, SBI_TRAP_REGS_OFFSET(zero)(sp) - REG_S ra, SBI_TRAP_REGS_OFFSET(ra)(sp) - REG_S gp, SBI_TRAP_REGS_OFFSET(gp)(sp) - REG_S tp, SBI_TRAP_REGS_OFFSET(tp)(sp) - REG_S t1, SBI_TRAP_REGS_OFFSET(t1)(sp) - REG_S t2, SBI_TRAP_REGS_OFFSET(t2)(sp) - REG_S s0, SBI_TRAP_REGS_OFFSET(s0)(sp) - REG_S s1, SBI_TRAP_REGS_OFFSET(s1)(sp) - REG_S a0, SBI_TRAP_REGS_OFFSET(a0)(sp) - REG_S a1, SBI_TRAP_REGS_OFFSET(a1)(sp) - REG_S a2, SBI_TRAP_REGS_OFFSET(a2)(sp) - REG_S a3, SBI_TRAP_REGS_OFFSET(a3)(sp) - REG_S a4, SBI_TRAP_REGS_OFFSET(a4)(sp) - REG_S a5, SBI_TRAP_REGS_OFFSET(a5)(sp) - REG_S a6, SBI_TRAP_REGS_OFFSET(a6)(sp) - REG_S a7, SBI_TRAP_REGS_OFFSET(a7)(sp) - REG_S s2, SBI_TRAP_REGS_OFFSET(s2)(sp) - REG_S s3, SBI_TRAP_REGS_OFFSET(s3)(sp) - REG_S s4, SBI_TRAP_REGS_OFFSET(s4)(sp) - REG_S s5, SBI_TRAP_REGS_OFFSET(s5)(sp) - REG_S s6, SBI_TRAP_REGS_OFFSET(s6)(sp) - REG_S s7, SBI_TRAP_REGS_OFFSET(s7)(sp) - REG_S s8, SBI_TRAP_REGS_OFFSET(s8)(sp) - REG_S s9, SBI_TRAP_REGS_OFFSET(s9)(sp) - REG_S s10, SBI_TRAP_REGS_OFFSET(s10)(sp) - REG_S s11, SBI_TRAP_REGS_OFFSET(s11)(sp) - REG_S t3, SBI_TRAP_REGS_OFFSET(t3)(sp) - REG_S t4, SBI_TRAP_REGS_OFFSET(t4)(sp) - REG_S t5, SBI_TRAP_REGS_OFFSET(t5)(sp) - REG_S t6, SBI_TRAP_REGS_OFFSET(t6)(sp) - - /* Restore GP */ - - la a0, mpfs_global_pointer - ld gp, 0(a0) - - /* Call C routine */ - - add a0, sp, zero - call sbi_trap_handler - - /* Restore all general regisers except A0 and T0 */ - - REG_L ra, SBI_TRAP_REGS_OFFSET(ra)(a0) - REG_L sp, SBI_TRAP_REGS_OFFSET(sp)(a0) - REG_L gp, SBI_TRAP_REGS_OFFSET(gp)(a0) - REG_L tp, SBI_TRAP_REGS_OFFSET(tp)(a0) - REG_L t1, SBI_TRAP_REGS_OFFSET(t1)(a0) - REG_L t2, SBI_TRAP_REGS_OFFSET(t2)(a0) - REG_L s0, SBI_TRAP_REGS_OFFSET(s0)(a0) - REG_L s1, SBI_TRAP_REGS_OFFSET(s1)(a0) - REG_L a1, SBI_TRAP_REGS_OFFSET(a1)(a0) - REG_L a2, SBI_TRAP_REGS_OFFSET(a2)(a0) - REG_L a3, SBI_TRAP_REGS_OFFSET(a3)(a0) - REG_L a4, SBI_TRAP_REGS_OFFSET(a4)(a0) - REG_L a5, SBI_TRAP_REGS_OFFSET(a5)(a0) - REG_L a6, SBI_TRAP_REGS_OFFSET(a6)(a0) - REG_L a7, SBI_TRAP_REGS_OFFSET(a7)(a0) - REG_L s2, SBI_TRAP_REGS_OFFSET(s2)(a0) - REG_L s3, SBI_TRAP_REGS_OFFSET(s3)(a0) - REG_L s4, SBI_TRAP_REGS_OFFSET(s4)(a0) - REG_L s5, SBI_TRAP_REGS_OFFSET(s5)(a0) - REG_L s6, SBI_TRAP_REGS_OFFSET(s6)(a0) - REG_L s7, SBI_TRAP_REGS_OFFSET(s7)(a0) - REG_L s8, SBI_TRAP_REGS_OFFSET(s8)(a0) - REG_L s9, SBI_TRAP_REGS_OFFSET(s9)(a0) - REG_L s10, SBI_TRAP_REGS_OFFSET(s10)(a0) - REG_L s11, SBI_TRAP_REGS_OFFSET(s11)(a0) - REG_L t3, SBI_TRAP_REGS_OFFSET(t3)(a0) - REG_L t4, SBI_TRAP_REGS_OFFSET(t4)(a0) - REG_L t5, SBI_TRAP_REGS_OFFSET(t5)(a0) - REG_L t6, SBI_TRAP_REGS_OFFSET(t6)(a0) - - /* Restore MEPC and MSTATUS CSRs */ - - REG_L t0, SBI_TRAP_REGS_OFFSET(mepc)(a0) - csrw CSR_MEPC, t0 - REG_L t0, SBI_TRAP_REGS_OFFSET(mstatus)(a0) - csrw CSR_MSTATUS, t0 - - /* Restore T0 */ - - REG_L t0, SBI_TRAP_REGS_OFFSET(t0)(a0) - - /* Restore A0 */ - - REG_L a0, SBI_TRAP_REGS_OFFSET(a0)(a0) - - mret + tail mpfs_opensbi_setup From a5d1e67afe4a7b1c1c945b5fa82ce39ff9c1838d Mon Sep 17 00:00:00 2001 From: Eero Nurkkala Date: Thu, 22 Jun 2023 15:45:44 +0300 Subject: [PATCH 61/79] mpfs_opensbi_utils.S: relocate OpenSBI into l2zerodevice This loads the OpenSBI from eNVM into the zerodevice. Signed-off-by: Eero Nurkkala --- arch/risc-v/src/mpfs/mpfs_opensbi_utils.S | 45 +++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/arch/risc-v/src/mpfs/mpfs_opensbi_utils.S b/arch/risc-v/src/mpfs/mpfs_opensbi_utils.S index db8f8fff7f738..9f43b5bb16621 100644 --- a/arch/risc-v/src/mpfs/mpfs_opensbi_utils.S +++ b/arch/risc-v/src/mpfs/mpfs_opensbi_utils.S @@ -39,6 +39,22 @@ ****************************************************************************/ .global mpfs_opensbi_prepare_hart + .global mpfs_opensbi_relocate_from_envm + + /* Add some weak default values to make this compile without */ + + .weak _sbi_zerodev_loadaddr + .weak _ssbi_zerodev + .weak _esbi_zerodev + + /* These are the weak pointless variables, only to get this PR compile */ + +_sbi_zerodev_loadaddr: + .dword 0x0a006000 +_ssbi_zerodev: + .dword _stext +_esbi_zerodev: + .dword _stext /**************************************************************************** * Private Data @@ -68,9 +84,38 @@ mpfs_global_pointer: * ****************************************************************************/ + .align 3 +mpfs_opensbi_relocate_from_envm: + + /* Relocate the code from eNVM into L2 zero device */ + + la a0, _sbi_zerodev_loadaddr + la a1, _ssbi_zerodev + la a2, _esbi_zerodev +.check_if_opensbi_copy_done: + bge a1, a2, .opensbi_copy_done + ld a3, 0(a0) + sd a3, 0(a1) + addi a0, a0, 8 + addi a1, a1, 8 + j .check_if_opensbi_copy_done +.opensbi_copy_done: + + /* To make a store to instruction memory visible to all RISC-V harts, the + * writing hart has to execute a data FENCE before requesting that all + * remote RISC-V harts execute a FENCE.I. This is hart0 only. + */ + + fence + ret + .align 3 mpfs_opensbi_prepare_hart: + /* These are harts other than 0. Thus, fence.i */ + + fence.i + /* Setup OpenSBI exception handler */ la t0, mpfs_exception_opensbi From b1c7173792791944d5a62b042fb4d208c2700fa4 Mon Sep 17 00:00:00 2001 From: Eero Nurkkala Date: Tue, 27 Jun 2023 14:26:50 +0300 Subject: [PATCH 62/79] opensbi: update to contain shrinked version Update to have 2k smaller version of OpenSBI. Signed-off-by: Eero Nurkkala --- arch/risc-v/src/opensbi/Make.defs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/risc-v/src/opensbi/Make.defs b/arch/risc-v/src/opensbi/Make.defs index 8bee7d102c77e..a522f7e638d44 100644 --- a/arch/risc-v/src/opensbi/Make.defs +++ b/arch/risc-v/src/opensbi/Make.defs @@ -37,10 +37,10 @@ INCLUDES += ${INCDIR_PREFIX}$(ARCH_SRCDIR)$(DELIM)opensbi$(DELIM)opensbi-3rdpar SBI_DIR := opensbi OPENSBI_UNPACK = opensbi-3rdparty -OPENSBI_COMMIT = b18bb7ce78d4e5504a9cbd8df7b57d795f489a0a +OPENSBI_COMMIT = 5546c21701b21eaf6c8b0bff551e77b1a241d8ef OPENSBI_URL = https://github.com/tiiuae/opensbi/tarball OPENSBI_TARBALL = opensbi.tar.gz -OPENSBI_DIR = tiiuae-opensbi-b18bb7c +OPENSBI_DIR = tiiuae-opensbi-5546c21 $(OPENSBI_TARBALL): $(call DOWNLOAD,$(OPENSBI_URL),$(OPENSBI_COMMIT),opensbi/$(OPENSBI_TARBALL)) From ef92a6c1e678b92f07660021ed0a6e8cb189ac26 Mon Sep 17 00:00:00 2001 From: Jari Nippula Date: Wed, 28 Jun 2023 15:09:44 +0300 Subject: [PATCH 63/79] Revert "opensbi: update to contain shrinked version" This reverts commit 95e02b03068cbac3b88d8894fb82706d98d2fb71. --- arch/risc-v/src/opensbi/Make.defs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/risc-v/src/opensbi/Make.defs b/arch/risc-v/src/opensbi/Make.defs index a522f7e638d44..8bee7d102c77e 100644 --- a/arch/risc-v/src/opensbi/Make.defs +++ b/arch/risc-v/src/opensbi/Make.defs @@ -37,10 +37,10 @@ INCLUDES += ${INCDIR_PREFIX}$(ARCH_SRCDIR)$(DELIM)opensbi$(DELIM)opensbi-3rdpar SBI_DIR := opensbi OPENSBI_UNPACK = opensbi-3rdparty -OPENSBI_COMMIT = 5546c21701b21eaf6c8b0bff551e77b1a241d8ef +OPENSBI_COMMIT = b18bb7ce78d4e5504a9cbd8df7b57d795f489a0a OPENSBI_URL = https://github.com/tiiuae/opensbi/tarball OPENSBI_TARBALL = opensbi.tar.gz -OPENSBI_DIR = tiiuae-opensbi-5546c21 +OPENSBI_DIR = tiiuae-opensbi-b18bb7c $(OPENSBI_TARBALL): $(call DOWNLOAD,$(OPENSBI_URL),$(OPENSBI_COMMIT),opensbi/$(OPENSBI_TARBALL)) From a50511342e08355a6d6fb898559f07e932b0a2a7 Mon Sep 17 00:00:00 2001 From: Jari Nippula Date: Wed, 28 Jun 2023 14:57:57 +0300 Subject: [PATCH 64/79] opensbi: update to contain shrinked version --- arch/risc-v/src/opensbi/Make.defs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/risc-v/src/opensbi/Make.defs b/arch/risc-v/src/opensbi/Make.defs index 8bee7d102c77e..b7d0ca61e232d 100644 --- a/arch/risc-v/src/opensbi/Make.defs +++ b/arch/risc-v/src/opensbi/Make.defs @@ -37,10 +37,10 @@ INCLUDES += ${INCDIR_PREFIX}$(ARCH_SRCDIR)$(DELIM)opensbi$(DELIM)opensbi-3rdpar SBI_DIR := opensbi OPENSBI_UNPACK = opensbi-3rdparty -OPENSBI_COMMIT = b18bb7ce78d4e5504a9cbd8df7b57d795f489a0a +OPENSBI_COMMIT = a082fb83f218a647d2009b565e573dac8f179cb9 OPENSBI_URL = https://github.com/tiiuae/opensbi/tarball OPENSBI_TARBALL = opensbi.tar.gz -OPENSBI_DIR = tiiuae-opensbi-b18bb7c +OPENSBI_DIR = tiiuae-opensbi-a082fb8 $(OPENSBI_TARBALL): $(call DOWNLOAD,$(OPENSBI_URL),$(OPENSBI_COMMIT),opensbi/$(OPENSBI_TARBALL)) From 6f2db08343ea94a7072eba1ad4325afc5acbb95c Mon Sep 17 00:00:00 2001 From: Eero Nurkkala Date: Wed, 9 Aug 2023 13:21:32 +0300 Subject: [PATCH 65/79] risc-v/mpfs: ihc: don't wait for a remote ack RPMSG is associated with the use of HPWORK / LPWORK queues. After sending a message to the remote end (Linux), it waits for an ack before proceeding. Unfortunately this may take sometimes more than 0x3000 CLINT MTIME cycles. Ack waiting is also unnecessary: nothing is done with that information. Even worse, the net_lock() is also held during the blocked time so it blocks other network stacks that are unrelated to this. The logic is still maintained with the message present (MP) flag. No new message will be sent until that is cleared by the romote. Signed-off-by: Eero Nurkkala --- arch/risc-v/src/mpfs/mpfs_ihc.c | 140 +++++++++++--------------------- 1 file changed, 46 insertions(+), 94 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_ihc.c b/arch/risc-v/src/mpfs/mpfs_ihc.c index c031af596beee..037cb2de5cc80 100644 --- a/arch/risc-v/src/mpfs/mpfs_ihc.c +++ b/arch/risc-v/src/mpfs/mpfs_ihc.c @@ -187,7 +187,6 @@ static struct mpfs_rptun_shmem_s g_shmem; static struct rpmsg_device *g_mpfs_rpmsg_device; static struct rpmsg_virtio_device *g_mpfs_virtio_device; -static sem_t g_mpfs_ack_sig = SEM_INITIALIZER(0); #ifdef MPFS_RPTUN_USE_THREAD static sem_t g_mpfs_rx_sig = SEM_INITIALIZER(0); #else @@ -441,43 +440,30 @@ static uint32_t mpfs_ihc_context_to_local_hart_id(ihc_channel_t channel) * Name: mpfs_ihc_rx_handler * * Description: - * This handles the received information and either lets the vq to proceed - * via posting g_mpfs_ack_sig, or lets the mpfs_rptun_thread() run as it - * waits for the g_mpfs_rx_sig. virtqueue_notification() cannot be called - * from the interrupt context, thus the thread that will perform it. + * This handles the received information and lets the vq to proceed. + * virtqueue_notification() cannot be called from the interrupt context, + * thus the thread or work queue that will perform it. * * Input Parameters: * message - Pointer to the incoming message - * is_ack - Boolean indicating whether an ack is received - * is_msg - Boolean indicating message presence * * Returned Value: * None * ****************************************************************************/ -static void mpfs_ihc_rx_handler(uint32_t *message, bool is_ack, bool is_msg) +static void mpfs_ihc_rx_handler(uint32_t *message) { - if (is_ack) - { - /* Received the ack */ - - nxsem_post(&g_mpfs_ack_sig); - } + g_vq_idx = message[0]; - if (is_msg) - { - g_vq_idx = message[0]; - - DEBUGASSERT((g_vq_idx == VRING0_NOTIFYID) || - (g_vq_idx == VRING1_NOTIFYID)); + DEBUGASSERT((g_vq_idx == VRING0_NOTIFYID) || + (g_vq_idx == VRING1_NOTIFYID)); #ifdef MPFS_RPTUN_USE_THREAD - nxsem_post(&g_mpfs_rx_sig); + nxsem_post(&g_mpfs_rx_sig); #else - work_queue(HPWORK, &g_rptun_work, mpfs_rptun_worker, NULL, 0); + work_queue(HPWORK, &g_rptun_work, mpfs_rptun_worker, NULL, 0); #endif - } } /**************************************************************************** @@ -527,8 +513,6 @@ static void mpfs_ihc_worker(void *arg) * channel - Enum that describes the channel used. * mhartid - Context hart id, not necessarily the absolute mhartid but * rather, the primary hartid of the set of harts. - * is_ack - Boolean indicating an ack message - * is_msg - Boolean indicating message presence * msg - For storing data, could be NULL * * Returned Value: @@ -537,72 +521,54 @@ static void mpfs_ihc_worker(void *arg) ****************************************************************************/ static void mpfs_ihc_rx_message(ihc_channel_t channel, uint32_t mhartid, - bool is_ack, bool is_msg, uint32_t *msg) + uint32_t *msg) { uint32_t rhartid = mpfs_ihc_context_to_remote_hart_id(channel); uint32_t ctrl_reg = getreg32(MPFS_IHC_CTRL(mhartid, rhartid)); - if (is_ack && !is_msg) - { - if (mhartid == CONTEXTB_HARTID) - { - uintptr_t msg_in = MPFS_IHC_MSG_IN(mhartid, rhartid); - DEBUGASSERT(msg == NULL); - mpfs_ihc_rx_handler((uint32_t *)msg_in, is_ack, is_msg); - } - else - { - /* This path is meant for the OpenSBI vendor extension only */ + /* Check if we have a message */ - DEBUGPANIC(); - } + if (mhartid == CONTEXTB_HARTID) + { + uintptr_t msg_in = MPFS_IHC_MSG_IN(mhartid, rhartid); + DEBUGASSERT(msg == NULL); + mpfs_ihc_rx_handler((uint32_t *)msg_in); } - else if (is_msg) + else { - /* Check if we have a message */ + /* This path is meant for the OpenSBI vendor extension only */ - if (mhartid == CONTEXTB_HARTID) - { - uintptr_t msg_in = MPFS_IHC_MSG_IN(mhartid, rhartid); - DEBUGASSERT(msg == NULL); - mpfs_ihc_rx_handler((uint32_t *)msg_in, is_ack, is_msg); - } - else - { - /* This path is meant for the OpenSBI vendor extension only */ + DEBUGPANIC(); + } - DEBUGPANIC(); - } + /* Set MP to 0. Note this generates an interrupt on the other hart + * if it has RMPIE bit set in the control register + */ - /* Set MP to 0. Note this generates an interrupt on the other hart - * if it has RMPIE bit set in the control register + ctrl_reg = getreg32(MPFS_IHC_CTRL(mhartid, rhartid)); + if (ctrl_reg & RMP_MESSAGE_PRESENT) + { + /* If we send the ACK here, Linux will have the ACK and the + * MP flags sets. IHC_AVOID_ACK_AND_MP assures only one + * is present at once. */ - ctrl_reg = getreg32(MPFS_IHC_CTRL(mhartid, rhartid)); - if (ctrl_reg & RMP_MESSAGE_PRESENT) - { - /* If we send the ACK here, Linux will have the ACK and the - * MP flags sets. IHC_AVOID_ACK_AND_MP assures only one - * is present at once. - */ - #ifdef IHC_AVOID_ACK_AND_MP - g_work_arg.mhartid = mhartid; - g_work_arg.rhartid = rhartid; - modifyreg32(MPFS_IHC_CTRL(mhartid, rhartid), MP_MASK, 0); - work_queue(HPWORK, &g_ihc_work, mpfs_ihc_worker, NULL, 0); + g_work_arg.mhartid = mhartid; + g_work_arg.rhartid = rhartid; + modifyreg32(MPFS_IHC_CTRL(mhartid, rhartid), MP_MASK, 0); + work_queue(HPWORK, &g_ihc_work, mpfs_ihc_worker, NULL, 0); #else - modifyreg32(MPFS_IHC_CTRL(mhartid, rhartid), MP_MASK, 0); - modifyreg32(MPFS_IHC_CTRL(mhartid, rhartid), 0, ACK_INT); + modifyreg32(MPFS_IHC_CTRL(mhartid, rhartid), MP_MASK, 0); + modifyreg32(MPFS_IHC_CTRL(mhartid, rhartid), 0, ACK_INT); #endif - } - else - { - /* We can send the ACK now and clear the MP */ + } + else + { + /* We can send the ACK now and clear the MP */ - modifyreg32(MPFS_IHC_CTRL(mhartid, rhartid), MP_MASK, 0); - modifyreg32(MPFS_IHC_CTRL(mhartid, rhartid), 0, ACK_INT); - } + modifyreg32(MPFS_IHC_CTRL(mhartid, rhartid), MP_MASK, 0); + modifyreg32(MPFS_IHC_CTRL(mhartid, rhartid), 0, ACK_INT); } } @@ -649,7 +615,10 @@ static void mpfs_ihc_message_present_isr(void) /* Process incoming packet */ - mpfs_ihc_rx_message(origin_hart, mhartid, is_ack, is_msg, NULL); + if (is_msg) + { + mpfs_ihc_rx_message(origin_hart, mhartid, NULL); + } if (is_ack) { @@ -787,7 +756,7 @@ static int mpfs_ihc_tx_message(ihc_channel_t channel, uint32_t *message) { ctrl_reg = getreg32(MPFS_IHC_CTRL(mhartid, rhartid)); } - while ((ctrl_reg & (RMP_MESSAGE_PRESENT | ACK_INT)) && --retries); + while ((ctrl_reg & (RMP_MESSAGE_PRESENT)) && --retries); /* Return if RMP bit 1 indicating busy */ @@ -795,10 +764,6 @@ static int mpfs_ihc_tx_message(ihc_channel_t channel, uint32_t *message) { return -EBUSY; } - else if (ACK_INT == (ctrl_reg & ACK_INT_MASK)) - { - return -EBUSY; - } else { /* Fill the buffer */ @@ -820,19 +785,6 @@ static int mpfs_ihc_tx_message(ihc_channel_t channel, uint32_t *message) /* Set the MP bit. This will notify other of incoming hart message */ modifyreg32(MPFS_IHC_CTRL(mhartid, rhartid), 0, RMP_MESSAGE_PRESENT); - - /* Wait for the ACK to arrive to maintain the logic */ - - if (mhartid == CONTEXTB_HARTID) - { - /* With some probability, an ACK is lost. Only wait for some - * descent amount of time and continue. Otherwise, this will - * hang and never proceed. - */ - - nxsem_tickwait_uninterruptible(&g_mpfs_ack_sig, - MSEC2TICK(10)); - } } return OK; From dd9fee04c7214b7e9cc00fc340565ba2c65f5d9e Mon Sep 17 00:00:00 2001 From: Jari Nippula Date: Wed, 9 Aug 2023 15:06:39 +0300 Subject: [PATCH 66/79] Disable linker relaxed addressing when loading gp --- arch/risc-v/src/mpfs/mpfs_opensbi_trap.S | 6 ++++-- arch/risc-v/src/mpfs/mpfs_opensbi_utils.S | 7 ------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_opensbi_trap.S b/arch/risc-v/src/mpfs/mpfs_opensbi_trap.S index e046861201e13..87000330c4b9c 100644 --- a/arch/risc-v/src/mpfs/mpfs_opensbi_trap.S +++ b/arch/risc-v/src/mpfs/mpfs_opensbi_trap.S @@ -166,8 +166,10 @@ mpfs_global_pointer: /* Restore GP */ - la a0, mpfs_global_pointer - ld gp, 0(a0) + .option push + .option norelax + la gp, __global_pointer$ + .option pop /* Call C routine */ diff --git a/arch/risc-v/src/mpfs/mpfs_opensbi_utils.S b/arch/risc-v/src/mpfs/mpfs_opensbi_utils.S index 9f43b5bb16621..6f623ed560def 100644 --- a/arch/risc-v/src/mpfs/mpfs_opensbi_utils.S +++ b/arch/risc-v/src/mpfs/mpfs_opensbi_utils.S @@ -121,13 +121,6 @@ mpfs_opensbi_prepare_hart: la t0, mpfs_exception_opensbi csrw mtvec, t0 - /* la gp, __global_pointer$ will not work. We want to have the gp as seen - * in the .map file exactly. We need to restore gp in the trap handler. - */ - - la t0, mpfs_global_pointer - ld gp, 0(t0) - /* Setup stacks per hart, the stack top is the end of the hart's scratch */ csrr a0, mhartid From ec68b3d4f438d8271387cf6365e0a699ad0c0c1e Mon Sep 17 00:00:00 2001 From: Eero Nurkkala Date: Tue, 15 Aug 2023 11:54:03 +0300 Subject: [PATCH 67/79] risc-v/mpfs: clear L2 before use SiFive document: "ECC Error Handling Guide" states: "Any SRAM block or cache memory containing ECC functionality needs to be initialized prior to use. ECC will correct defective bits based on memory contents, so if memory is not first initialized to a known state, then ECC will not operate as expected. It is recommended to use a DMA, if available, to write the entire SRAM or cache to zeros prior to enabling ECC reporting. If no DMA is present, use store instructions issued from the processor." Clean the cache at this early stage so no ECC errors will be flooding later. Signed-off-by: Eero Nurkkala --- arch/risc-v/src/mpfs/mpfs_head.S | 10 ++++++++++ .../risc-v/mpfs/icicle/scripts/ld-envm-opensbi.script | 3 +++ boards/risc-v/mpfs/icicle/scripts/ld-envm.script | 3 +++ 3 files changed, 16 insertions(+) diff --git a/arch/risc-v/src/mpfs/mpfs_head.S b/arch/risc-v/src/mpfs/mpfs_head.S index af25f49b98ed5..465cf1f0f60a5 100644 --- a/arch/risc-v/src/mpfs/mpfs_head.S +++ b/arch/risc-v/src/mpfs/mpfs_head.S @@ -166,6 +166,16 @@ __start: .continue_boot: + /* L2 needs to be zeroed before ECC (error correction) is enabled later. */ + + la a4, __l2lim_start + la a5, __l2lim_end + +.clear_l2lim: + sd x0, 0(a4) + add a4, a4, 8 + blt a4, a5, .clear_l2lim + /* Clear PMP */ csrw pmpcfg0, zero diff --git a/boards/risc-v/mpfs/icicle/scripts/ld-envm-opensbi.script b/boards/risc-v/mpfs/icicle/scripts/ld-envm-opensbi.script index 7843d3f82af4d..c17cd90439c2e 100644 --- a/boards/risc-v/mpfs/icicle/scripts/ld-envm-opensbi.script +++ b/boards/risc-v/mpfs/icicle/scripts/ld-envm-opensbi.script @@ -32,6 +32,9 @@ ENTRY(_stext) EXTERN(__start) SECTIONS { + PROVIDE(__l2lim_start = ORIGIN(l2lim)); + PROVIDE(__l2lim_end = ORIGIN(l2lim) + LENGTH(l2lim)); + .text.sbi : { sbi* riscv_atomic* diff --git a/boards/risc-v/mpfs/icicle/scripts/ld-envm.script b/boards/risc-v/mpfs/icicle/scripts/ld-envm.script index ceaf236ef4655..08072e667e7b4 100644 --- a/boards/risc-v/mpfs/icicle/scripts/ld-envm.script +++ b/boards/risc-v/mpfs/icicle/scripts/ld-envm.script @@ -35,6 +35,9 @@ ENTRY(_stext) EXTERN(__start) SECTIONS { + PROVIDE(__l2lim_start = ORIGIN(lim)); + PROVIDE(__l2lim_end = ORIGIN(lim) + LENGTH(lim)); + .text : { _stext = ABSOLUTE(.); *(.start .start.*) From 1fc7d2b511c4616dfd8f926e3af304ceb5f1ce34 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Thu, 24 Aug 2023 10:58:09 +0300 Subject: [PATCH 68/79] arch/risc-v/src/mpfs/mpfs_ddr.c: Correct the DDR training dq/dqs status check It was checking a wrong register for dq/dqs window size. Signed-off-by: Jukka Laitinen --- arch/risc-v/src/mpfs/hardware/mpfs_sgmii.h | 1 + arch/risc-v/src/mpfs/mpfs_ddr.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/risc-v/src/mpfs/hardware/mpfs_sgmii.h b/arch/risc-v/src/mpfs/hardware/mpfs_sgmii.h index 65959492beef2..566e1fe654b3b 100644 --- a/arch/risc-v/src/mpfs/hardware/mpfs_sgmii.h +++ b/arch/risc-v/src/mpfs/hardware/mpfs_sgmii.h @@ -654,6 +654,7 @@ #define MPFS_CFG_DDR_SGMII_PHY_GT_ERR_COMB (MPFS_CFG_DDR_SGMII_PHY_BASE + MPFS_CFG_DDR_SGMII_PHY_GT_ERR_COMB_OFFSET) #define MPFS_CFG_DDR_SGMII_PHY_DQ_DQS_ERR_DONE (MPFS_CFG_DDR_SGMII_PHY_BASE + MPFS_CFG_DDR_SGMII_PHY_DQ_DQS_ERR_DONE_OFFSET) #define MPFS_CFG_DDR_SGMII_PHY_DQDQS_STATUS1 (MPFS_CFG_DDR_SGMII_PHY_BASE + MPFS_CFG_DDR_SGMII_PHY_DQDQS_STATUS1_OFFSET) +#define MPFS_CFG_DDR_SGMII_PHY_DQDQS_STATUS2 (MPFS_CFG_DDR_SGMII_PHY_BASE + MPFS_CFG_DDR_SGMII_PHY_DQDQS_STATUS2_OFFSET) #define MPFS_CFG_DDR_SGMII_PHY_GT_CLK_SEL (MPFS_CFG_DDR_SGMII_PHY_BASE + MPFS_CFG_DDR_SGMII_PHY_GT_CLK_SEL_OFFSET) #define MPFS_CFG_DDR_SGMII_PHY_GT_TXDLY (MPFS_CFG_DDR_SGMII_PHY_BASE + MPFS_CFG_DDR_SGMII_PHY_GT_TXDLY_OFFSET) #define MPFS_CFG_DDR_SGMII_PHY_DYN_CNTL (MPFS_CFG_DDR_SGMII_PHY_BASE + MPFS_CFG_DDR_SGMII_PHY_DYN_CNTL_OFFSET) diff --git a/arch/risc-v/src/mpfs/mpfs_ddr.c b/arch/risc-v/src/mpfs/mpfs_ddr.c index b2f8b368ec1d4..3b5806c07a15a 100644 --- a/arch/risc-v/src/mpfs/mpfs_ddr.c +++ b/arch/risc-v/src/mpfs/mpfs_ddr.c @@ -3532,7 +3532,7 @@ static int mpfs_training_verify(void) /* Check that DQ/DQS calculated window is above 5 taps. */ - if (getreg32(MPFS_CFG_DDR_SGMII_PHY_DQDQS_STATUS1) < DQ_DQS_NUM_TAPS) + if (getreg32(MPFS_CFG_DDR_SGMII_PHY_DQDQS_STATUS2) < DQ_DQS_NUM_TAPS) { t_status |= 0x01; } From c524902c5a735a54bef504a4bc7801aef0bad292 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Thu, 24 Aug 2023 11:02:30 +0300 Subject: [PATCH 69/79] arch/risc-v/src/mpfs/mpfs_ddr.c: Don't auto-determine the write latency It doesn't make sense to try to auto-determine write latency, it may pass with too low value. Keep the existing implementation if the write latency has been set to minimum value, otherwise just set it. Signed-off-by: Jukka Laitinen --- arch/risc-v/src/mpfs/mpfs_ddr.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_ddr.c b/arch/risc-v/src/mpfs/mpfs_ddr.c index 3b5806c07a15a..dcd9879281817 100644 --- a/arch/risc-v/src/mpfs/mpfs_ddr.c +++ b/arch/risc-v/src/mpfs/mpfs_ddr.c @@ -3725,14 +3725,22 @@ static int mpfs_training_write_calibration(struct mpfs_ddr_priv_s *priv) #endif - /* Find the proper write latency by using mtc test */ + if (LIBERO_SETTING_CFG_WRITE_LATENCY_SET == 0) + { + /* Find the proper write latency by using mtc test */ - do + do + { + putreg32(write_latency, MPFS_DDR_CSR_APB_CFG_DFI_T_PHY_WRLAT); + error = mpfs_write_calibration_using_mtc(priv); + } + while (error && ++write_latency <= WR_LATENCY_MAX); + } + else { putreg32(write_latency, MPFS_DDR_CSR_APB_CFG_DFI_T_PHY_WRLAT); error = mpfs_write_calibration_using_mtc(priv); } - while (error && ++write_latency <= WR_LATENCY_MAX); /* Return error if mtc test failed on all allowed latency values */ From 1f9b2ba6c8f732eac84dc0b8226f5c4300590fa1 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Thu, 24 Aug 2023 10:53:01 +0300 Subject: [PATCH 70/79] arch/risc-v/src/mpfs/mpfs_ddr.c: Correct memory test timeouts Especially the write calibration must bail out if the memory test timeouts, otherwise the device will get stuck in running the memory test in sequence, and it will always timeout. Negative error value was also not properly returned from mpfs_mtc_test. Signed-off-by: Jukka Laitinen --- arch/risc-v/src/mpfs/mpfs_ddr.c | 163 ++++++++++++++++---------------- 1 file changed, 82 insertions(+), 81 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_ddr.c b/arch/risc-v/src/mpfs/mpfs_ddr.c index dcd9879281817..8c61e54b4c380 100644 --- a/arch/risc-v/src/mpfs/mpfs_ddr.c +++ b/arch/risc-v/src/mpfs/mpfs_ddr.c @@ -1722,10 +1722,10 @@ static void mpfs_load_dq(uint8_t lane) * ****************************************************************************/ -static uint8_t mpfs_mtc_test(uint8_t mask, uint64_t start_address, - uint32_t size, - enum mtc_pattern_e data_pattern, - enum mtc_add_pattern_e add_pattern) +static int mpfs_mtc_test(uint8_t mask, uint64_t start_address, + uint32_t size, + enum mtc_pattern_e data_pattern, + enum mtc_add_pattern_e add_pattern) { /* Write calibration: * Configure common memory test interface by writing registers: @@ -1898,6 +1898,65 @@ static uint8_t mpfs_mtc_test(uint8_t mask, uint64_t start_address, return getreg32(MPFS_DDR_CSR_APB_MT_ERROR_STS) & 0x01; } +/**************************************************************************** + * Name: mpfs_mtc_test_all + * + * Description: + * This performs a memory test with the NWL memory test core + * using all available test patterns. + * + * Input Parameters: + * mask - Test bitmask + * start_address - Test start address + * size - Size of the area to test + * add_pattern - Data modifier pattern + * + * Returned Value: + * Zero (OK) is returned on success. A nonzero value indicates a fail. + * + ****************************************************************************/ + +static int mpfs_mtc_test_all(uint8_t mask, uint64_t start_address, + uint32_t size, + enum mtc_add_pattern_e add_pattern) +{ + int result; + enum mtc_pattern_e test_pattern; + + /* Read once to flush MTC. During write calibration the first MTC + * read must be discarded as it is unreliable after a series of + * bad writes. Only check -ETIMEDOUT; if that occurs, we'll bail out + */ + + result = mpfs_mtc_test(mask, start_address, size, + MTC_COUNTING_PATTERN, + add_pattern); + if (result == -ETIMEDOUT) + { + return result; + } + + /* Test all patterns except MTC_USER */ + + for (test_pattern = MTC_COUNTING_PATTERN; + test_pattern <= MTC_PSEUDO_RANDOM_8BIT && result == 0; + test_pattern++) + { + if (test_pattern == MTC_USER) + { + continue; + } + + /* Read using different patterns */ + + result = mpfs_mtc_test(mask, start_address, size, + test_pattern, + add_pattern); + } + + return result; +} + /**************************************************************************** * Name: mpfs_set_write_calib * @@ -1962,8 +2021,8 @@ static void mpfs_set_write_calib(struct mpfs_ddr_priv_s *priv) static int mpfs_write_calibration_using_mtc(struct mpfs_ddr_priv_s *priv) { uint64_t start_address = 0x00; - uint32_t size = ONE_MB_MTC; - uint32_t result = 0; + uint32_t size = ONE_MB_MTC; + int result = 0; uint8_t lane_to_test; uint32_t cal_data; uint32_t lanes; @@ -1983,44 +2042,18 @@ static int mpfs_write_calibration_using_mtc(struct mpfs_ddr_priv_s *priv) * with the respect to the address and command for each lane. */ - for (cal_data = 0x00000; cal_data < 0xfffff; cal_data += 0x11111) + for (cal_data = 0x00000; cal_data < 0xfffff && result != -ETIMEDOUT; + cal_data += 0x11111) { putreg32(cal_data, MPFS_CFG_DDR_SGMII_PHY_EXPERT_WRCALIB); - for (lane_to_test = 0x00; lane_to_test < lanes; lane_to_test++) + for (lane_to_test = 0x00; + lane_to_test < lanes && result != -ETIMEDOUT; + lane_to_test++) { - /* Read once to flush MTC. During write calibration the first MTC - * read must be discarded as it is unreliable after a series of - * bad writes. - */ - uint8_t mask = (uint8_t)(1 << lane_to_test); - - result = mpfs_mtc_test(mask, start_address, size, - MTC_COUNTING_PATTERN, MTC_ADD_SEQUENTIAL); - - /* Read using different patterns */ - - result |= mpfs_mtc_test(mask, start_address, size, - MTC_COUNTING_PATTERN, - MTC_ADD_SEQUENTIAL); - result |= mpfs_mtc_test(mask, start_address, size, - MTC_WALKING_ONE, MTC_ADD_SEQUENTIAL); - result |= mpfs_mtc_test(mask, start_address, size, - MTC_PSEUDO_RANDOM, MTC_ADD_SEQUENTIAL); - result |= mpfs_mtc_test(mask, start_address, size, - MTC_NO_REPEATING_PSEUDO_RANDOM, - MTC_ADD_SEQUENTIAL); - result |= mpfs_mtc_test(mask, start_address, size, - MTC_ALT_ONES_ZEROS, MTC_ADD_SEQUENTIAL); - result |= mpfs_mtc_test(mask, start_address, size, - MTC_ALT_5_A, MTC_ADD_SEQUENTIAL); - result |= mpfs_mtc_test(mask, start_address, size, - MTC_PSEUDO_RANDOM_16BIT, - MTC_ADD_SEQUENTIAL); - result |= mpfs_mtc_test(mask, start_address, size, - MTC_PSEUDO_RANDOM_8BIT, - MTC_ADD_SEQUENTIAL); + result = mpfs_mtc_test_all(mask, start_address, size, + MTC_ADD_SEQUENTIAL); if (result == 0) /* if passed for this lane */ { @@ -3766,7 +3799,7 @@ static int mpfs_training_write_calibration(struct mpfs_ddr_priv_s *priv) static int mpfs_training_full_mtc_test(void) { - uint32_t error = 0; + int error = 0; uint8_t mask; if (mpfs_get_num_lanes() <= 3) @@ -3778,48 +3811,16 @@ static int mpfs_training_full_mtc_test(void) mask = 0xf; } - /* Read once to flush MTC. During write calibration the first MTC read - * must be discarded as it is unreliable after a series of bad writes. - */ + /* Test sequential additions */ + + error = mpfs_mtc_test_all(mask, 0x00, ONE_MB_MTC, MTC_ADD_SEQUENTIAL); - mpfs_mtc_test(mask, 0x00, ONE_MB_MTC, MTC_COUNTING_PATTERN, - MTC_ADD_SEQUENTIAL); - - /* Read using different patterns */ - - error |= mpfs_mtc_test(mask, 0x00, ONE_MB_MTC, MTC_COUNTING_PATTERN, - MTC_ADD_SEQUENTIAL); - error |= mpfs_mtc_test(mask, 0x00, ONE_MB_MTC, MTC_WALKING_ONE, - MTC_ADD_SEQUENTIAL); - error |= mpfs_mtc_test(mask, 0x00, ONE_MB_MTC, MTC_PSEUDO_RANDOM, - MTC_ADD_SEQUENTIAL); - error |= mpfs_mtc_test(mask, 0x00, ONE_MB_MTC, - MTC_NO_REPEATING_PSEUDO_RANDOM, MTC_ADD_SEQUENTIAL); - error |= mpfs_mtc_test(mask, 0x00, ONE_MB_MTC, MTC_ALT_ONES_ZEROS, - MTC_ADD_SEQUENTIAL); - error |= mpfs_mtc_test(mask, 0x00, ONE_MB_MTC, MTC_ALT_5_A, - MTC_ADD_SEQUENTIAL); - error |= mpfs_mtc_test(mask, 0x00, ONE_MB_MTC, MTC_PSEUDO_RANDOM_16BIT, - MTC_ADD_SEQUENTIAL); - error |= mpfs_mtc_test(mask, 0x00, ONE_MB_MTC, MTC_PSEUDO_RANDOM_8BIT, - MTC_ADD_SEQUENTIAL); - - error |= mpfs_mtc_test(mask, 0x00, ONE_MB_MTC, MTC_COUNTING_PATTERN, - MTC_ADD_RANDOM); - error |= mpfs_mtc_test(mask, 0x00, ONE_MB_MTC, MTC_WALKING_ONE, - MTC_ADD_RANDOM); - error |= mpfs_mtc_test(mask, 0x00, ONE_MB_MTC, MTC_PSEUDO_RANDOM, - MTC_ADD_RANDOM); - error |= mpfs_mtc_test(mask, 0x00, ONE_MB_MTC, - MTC_NO_REPEATING_PSEUDO_RANDOM, MTC_ADD_RANDOM); - error |= mpfs_mtc_test(mask, 0x00, ONE_MB_MTC, MTC_ALT_ONES_ZEROS, - MTC_ADD_RANDOM); - error |= mpfs_mtc_test(mask, 0x00, ONE_MB_MTC, MTC_ALT_5_A, - MTC_ADD_RANDOM); - error |= mpfs_mtc_test(mask, 0x00, ONE_MB_MTC, MTC_PSEUDO_RANDOM_16BIT, - MTC_ADD_RANDOM); - error |= mpfs_mtc_test(mask, 0x00, ONE_MB_MTC, MTC_PSEUDO_RANDOM_8BIT, - MTC_ADD_RANDOM); + if (error == 0) + { + /* Test random additions */ + + error = mpfs_mtc_test_all(mask, 0x00, ONE_MB_MTC, MTC_ADD_RANDOM); + } if (error) { From 2602afd00378286424b81ae849db49f9e0613198 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Thu, 24 Aug 2023 11:07:24 +0300 Subject: [PATCH 71/79] arch/risc-v/src/mpfs/mpfs_ddr.c: Make sure that DDRC is in reset when starting the training Also move the DDRC clock enablement and reset to mpfs_init_ddr. This doesn't change the functionality, but is the cleaner place for it. Signed-off-by: Jukka Laitinen --- arch/risc-v/src/mpfs/mpfs_ddr.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_ddr.c b/arch/risc-v/src/mpfs/mpfs_ddr.c index 8c61e54b4c380..db50ccb9209ab 100644 --- a/arch/risc-v/src/mpfs/mpfs_ddr.c +++ b/arch/risc-v/src/mpfs/mpfs_ddr.c @@ -812,6 +812,19 @@ void mpfs_setup_ddr_segments(enum seg_setup_e option) static void mpfs_init_ddrc(void) { + /* Turn on DDRC clock */ + + modifyreg32(MPFS_SYSREG_SUBBLK_CLOCK_CR, 0, + SYSREG_SUBBLK_CLOCK_CR_DDRC); + + /* Remove soft reset */ + + modifyreg32(MPFS_SYSREG_SOFT_RESET_CR, 0, + SYSREG_SUBBLK_CLOCK_CR_DDRC); + + modifyreg32(MPFS_SYSREG_SOFT_RESET_CR, + SYSREG_SUBBLK_CLOCK_CR_DDRC, 0); + putreg32(LIBERO_SETTING_CFG_MANUAL_ADDRESS_MAP, MPFS_DDR_CSR_APB_CFG_MANUAL_ADDRESS_MAP); putreg32(LIBERO_SETTING_CFG_CHIPADDR_MAP, @@ -3130,16 +3143,6 @@ static int mpfs_set_mode_vs_bits(struct mpfs_ddr_priv_s *priv) mpfs_setup_ddr_segments(DEFAULT_SEG_SETUP); - /* Turn on DDRC clock */ - - modifyreg32(MPFS_SYSREG_SUBBLK_CLOCK_CR, 0, - SYSREG_SUBBLK_CLOCK_CR_DDRC); - - /* Remove soft reset */ - - modifyreg32(MPFS_SYSREG_SOFT_RESET_CR, - SYSREG_SUBBLK_CLOCK_CR_DDRC, 0); - /* Set-up DDRC */ mpfs_init_ddrc(); From ee58b2e451b6d53ec61405a017db184e86b8e785 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Thu, 24 Aug 2023 15:35:50 +0300 Subject: [PATCH 72/79] arch/risc-v/src/mpfs/mpfs_ddr.c: Add a simple prng for memory training code Implement the previously empty mpfs_ddr_rand with adapted "seiran128" code from https://github.com/andanteyk/prng-seiran This implements a non-secure prng, which is minimal in size. The DDR training doesn't need cryptographically secure prng, and linking in the NuttX crypto would increase the code size significantly for bootloaders. Signed-off-by: Jukka Laitinen --- arch/risc-v/src/mpfs/mpfs_ddr.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_ddr.c b/arch/risc-v/src/mpfs/mpfs_ddr.c index db50ccb9209ab..0ed14b4ac3336 100644 --- a/arch/risc-v/src/mpfs/mpfs_ddr.c +++ b/arch/risc-v/src/mpfs/mpfs_ddr.c @@ -306,6 +306,14 @@ static const uint8_t refclk_offsets[][5] = #endif +/* State of the seiran128 PRNG, with initial seed */ + +static uint64_t prng_state[2] = + { + 0x6c64f673ed93b6cc, + 0x97c703d5f6c9d72b + }; + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -2131,19 +2139,29 @@ static int mpfs_write_calibration_using_mtc(struct mpfs_ddr_priv_s *priv) * Name: mpfs_ddr_rand * * Description: - * This should return a random value. + * This is adapted from seiran128 + * (https://github.com/andanteyk/prng-seiran) * * Returned Value: - * Always zero at the moment. - * - * Assumptions/Limitations: - * This doesn't return random values at the moment. + * Non-cryptographically secure pseudo random number * ****************************************************************************/ +static inline uint64_t rotl(uint64_t x, int k) +{ + return (x << k) | (x >> (-k & 0x3f)); +} + static int mpfs_ddr_rand(void) { - return 0; + uint64_t s0 = prng_state[0]; + uint64_t s1 = prng_state[1]; + uint64_t result = rotl((s0 + s1) * 9, 29) + s0; + + prng_state[0] = s0 ^ rotl(s1, 29); + prng_state[1] = s0 ^ (s1 << 9); + + return (int)result; } /**************************************************************************** From 66eec9dc1d04ec757d19589adb9bdfad1b3f6948 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Mon, 28 Aug 2023 14:02:45 +0300 Subject: [PATCH 73/79] Revert "drivers/mmcsd: fix style issues" This reverts commit 8254b374dd363f3fbeff9c6f7af387456fc5b1e4. --- drivers/mmcsd/mmcsd_sdio.c | 60 ++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/drivers/mmcsd/mmcsd_sdio.c b/drivers/mmcsd/mmcsd_sdio.c index 1baee5e782bd0..d683c31b405d7 100644 --- a/drivers/mmcsd/mmcsd_sdio.c +++ b/drivers/mmcsd/mmcsd_sdio.c @@ -149,54 +149,51 @@ static void mmcsd_unlock(FAR struct mmcsd_state_s *priv); /* Command/response helpers *************************************************/ static int mmcsd_sendcmdpoll(FAR struct mmcsd_state_s *priv, - uint32_t cmd, uint32_t arg); + uint32_t cmd, uint32_t arg); static int mmcsd_recv_r1(FAR struct mmcsd_state_s *priv, uint32_t cmd); static int mmcsd_recv_r6(FAR struct mmcsd_state_s *priv, uint32_t cmd); static int mmcsd_get_scr(FAR struct mmcsd_state_s *priv, - uint32_t scr[2]); + uint32_t scr[2]); static void mmcsd_decode_csd(FAR struct mmcsd_state_s *priv, - uint32_t csd[4]); + uint32_t csd[4]); #ifdef CONFIG_DEBUG_FS_INFO static void mmcsd_decode_cid(FAR struct mmcsd_state_s *priv, - uint32_t cid[4]); + uint32_t cid[4]); #else # define mmcsd_decode_cid(priv,cid) #endif static void mmcsd_decode_scr(FAR struct mmcsd_state_s *priv, - uint32_t scr[2]); + uint32_t scr[2]); static int mmcsd_get_r1(FAR struct mmcsd_state_s *priv, - FAR uint32_t *r1); + FAR uint32_t *r1); static int mmcsd_verifystate(FAR struct mmcsd_state_s *priv, - uint32_t status); + uint32_t status); /* Transfer helpers *********************************************************/ static bool mmcsd_wrprotected(FAR struct mmcsd_state_s *priv); static int mmcsd_eventwait(FAR struct mmcsd_state_s *priv, - sdio_eventset_t failevents); + sdio_eventset_t failevents); static int mmcsd_transferready(FAR struct mmcsd_state_s *priv); #if MMCSD_MULTIBLOCK_LIMIT != 1 static int mmcsd_stoptransmission(FAR struct mmcsd_state_s *priv); #endif static int mmcsd_setblocklen(FAR struct mmcsd_state_s *priv, - uint32_t blocklen); + uint32_t blocklen); static ssize_t mmcsd_readsingle(FAR struct mmcsd_state_s *priv, - FAR uint8_t *buffer, off_t startblock); + FAR uint8_t *buffer, off_t startblock); #if MMCSD_MULTIBLOCK_LIMIT != 1 static ssize_t mmcsd_readmultiple(FAR struct mmcsd_state_s *priv, - FAR uint8_t *buffer, off_t startblock, - size_t nblocks); + FAR uint8_t *buffer, off_t startblock, size_t nblocks); #endif static ssize_t mmcsd_writesingle(FAR struct mmcsd_state_s *priv, - FAR const uint8_t *buffer, - off_t startblock); + FAR const uint8_t *buffer, off_t startblock); #if MMCSD_MULTIBLOCK_LIMIT != 1 static ssize_t mmcsd_writemultiple(FAR struct mmcsd_state_s *priv, - FAR const uint8_t *buffer, - off_t startblock, - size_t nblocks); + FAR const uint8_t *buffer, off_t startblock, + size_t nblocks); #endif /* Block driver methods *****************************************************/ @@ -204,15 +201,14 @@ static ssize_t mmcsd_writemultiple(FAR struct mmcsd_state_s *priv, static int mmcsd_open(FAR struct inode *inode); static int mmcsd_close(FAR struct inode *inode); static ssize_t mmcsd_read(FAR struct inode *inode, FAR unsigned char *buffer, - blkcnt_t startsector, unsigned int nsectors); + blkcnt_t startsector, unsigned int nsectors); static ssize_t mmcsd_write(FAR struct inode *inode, - FAR const unsigned char *buffer, - blkcnt_t startsector, - unsigned int nsectors); + FAR const unsigned char *buffer, blkcnt_t startsector, + unsigned int nsectors); static int mmcsd_geometry(FAR struct inode *inode, - FAR struct geometry *geometry); + FAR struct geometry *geometry); static int mmcsd_ioctl(FAR struct inode *inode, int cmd, - unsigned long arg); + unsigned long arg); /* Initialization/uninitialization/reset ************************************/ @@ -1581,8 +1577,8 @@ static ssize_t mmcsd_readmultiple(FAR struct mmcsd_state_s *priv, SDIO_BLOCKSETUP(priv->dev, priv->blocksize, nblocks); SDIO_WAITENABLE(priv->dev, - SDIOWAIT_TRANSFERDONE | SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR, - nblocks * MMCSD_BLOCK_RDATADELAY); + SDIOWAIT_TRANSFERDONE | SDIOWAIT_TIMEOUT | SDIOWAIT_ERROR, + nblocks * MMCSD_BLOCK_RDATADELAY); #ifdef CONFIG_SDIO_DMA if ((priv->caps & SDIO_CAPS_DMASUPPORTED) != 0) @@ -2552,9 +2548,11 @@ static int mmcsd_widebus(FAR struct mmcsd_state_s *priv) * Configuring MMC - Use MMC_SWITCH access modes. */ - mmcsd_sendcmdpoll(priv, MMCSD_CMD6, - MMCSD_CMD6_MODE_WRITE_BYTE | MMCSD_CMD6_BUSWIDTH_RW | - MMCSD_CMD6_BUS_WIDTH_4); + uint32_t arg = MMCSD_CMD6_MODE_WRITE_BYTE | MMCSD_CMD6_BUSWIDTH_RW; + + arg |= MMCSD_CMD6_BUS_WIDTH_4; + + mmcsd_sendcmdpoll(priv, MMCSD_CMD6, arg); ret = mmcsd_recv_r1(priv, MMCSD_CMD6); if (ret != OK) @@ -2695,7 +2693,7 @@ static int mmcsd_mmcinitialize(FAR struct mmcsd_state_s *priv) * extended CSD register. */ - mmcsd_sendcmdpoll(priv, MMCSD_CMD9, (uint32_t)priv->rca << 16); + mmcsd_sendcmdpoll(priv, MMCSD_CMD9, (uint32_t) priv->rca << 16); ret = SDIO_RECVR2(priv->dev, MMCSD_CMD9, csd); if (ret != OK) { @@ -3502,8 +3500,8 @@ static int mmcsd_cardidentify(FAR struct mmcsd_state_s *priv) if (ret != OK) { - fwarn("WARNING: CMD1 RECVR3: %d. " - "NOTE: This is expected for SD cards.\n", ret); + fwarn("WARNING: CMD1 RECVR3: %d. \ + NOTE: This is expected for SD cards.\n", ret); /* CMD1 did not succeed, card is not MMC. Return to idle * to allow the communication to recover before another send. From 9d3b9fa72083054ec92029a3dd722fd6c7ab300d Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Mon, 28 Aug 2023 14:04:34 +0300 Subject: [PATCH 74/79] Revert "Add eMMC driver support" This reverts commit 50a8ec62c45dc12512cbbd5dce7f1e885b003849. --- arch/risc-v/src/litex/litex_sdio.c | 8 +- boards/risc-v/litex/arty_a7/Kconfig | 38 ---- .../litex/arty_a7/configs/sdmmc/defconfig | 74 ------- drivers/mmcsd/mmcsd_sdio.c | 200 +++--------------- drivers/mmcsd/mmcsd_sdio.h | 26 --- 5 files changed, 31 insertions(+), 315 deletions(-) delete mode 100644 boards/risc-v/litex/arty_a7/configs/sdmmc/defconfig diff --git a/arch/risc-v/src/litex/litex_sdio.c b/arch/risc-v/src/litex/litex_sdio.c index eec66ed29589f..13359662a3f13 100644 --- a/arch/risc-v/src/litex/litex_sdio.c +++ b/arch/risc-v/src/litex/litex_sdio.c @@ -860,12 +860,10 @@ static int litex_recvsetup(struct sdio_dev_s *dev, uint8_t *buffer, /* flush CPU d-cache */ -#ifndef CONFIG_LITEX_COHERENT_DMA up_invalidate_dcache_all(); -#endif putreg32(0, LITEX_SDBLOCK2MEM_DMA_ENABLE); - putreg32((uintptr_t)(&buffer[4]), LITEX_SDBLOCK2MEM_DMA_BASE); + putreg32((uintptr_t)buffer >> 32, LITEX_SDBLOCK2MEM_DMA_BASE); putreg32((uintptr_t)buffer, LITEX_SDBLOCK2MEM_DMA_BASE + 0x04); putreg32(nbytes, LITEX_SDBLOCK2MEM_DMA_LENGTH); putreg32(1, LITEX_SDBLOCK2MEM_DMA_ENABLE); @@ -905,12 +903,10 @@ static int litex_sendsetup(struct sdio_dev_s *dev, /* flush CPU d-cache */ -#ifndef CONFIG_LITEX_COHERENT_DMA up_invalidate_dcache_all(); -#endif putreg32(0, LITEX_SDMEM2BLOCK_DMA_ENABLE); - putreg32((uintptr_t)(&buffer[4]), LITEX_SDMEM2BLOCK_DMA_BASE); + putreg32((uintptr_t)buffer >> 32, LITEX_SDMEM2BLOCK_DMA_BASE); putreg32((uintptr_t)buffer, LITEX_SDMEM2BLOCK_DMA_BASE + 0x04); putreg32(nbytes, LITEX_SDMEM2BLOCK_DMA_LENGTH); putreg32(1, LITEX_SDMEM2BLOCK_DMA_ENABLE); diff --git a/boards/risc-v/litex/arty_a7/Kconfig b/boards/risc-v/litex/arty_a7/Kconfig index 7977b985b27c8..92df0ad54c723 100644 --- a/boards/risc-v/litex/arty_a7/Kconfig +++ b/boards/risc-v/litex/arty_a7/Kconfig @@ -5,44 +5,6 @@ if ARCH_BOARD_ARTY_A7 - -config LITEX_SDIO - bool "SDIO" - default n - select SCHED_HPWORK - select MMCSD - select MMCSD_SDIO - select SDIO_BLOCKSETUP - select ARCH_HAVE_SDIO - select SDIO_DMA - -config LITEX_SDIO1 - bool "Enable SDIO1" - default LITEX_SDIO - select LITEX_SDIO_DMA - depends on LITEX_SDIO - -config LITEX_IDMODE_FREQ - int "ID mode frequency" - default 400000 - depends on LITEX_SDIO - ---help--- - Initial, ID mode SD frequency - -config LITEX_MMCXFR_FREQ - int "MMC transfer frequency" - default 25000000 - depends on LITEX_SDIO - ---help--- - Frequency to use for transferring data to/from an MMC card - -config LITEX_SD4BIT_FREQ - int "SD 4-bit transfer frequency" - default 50000000 - depends on LITEX_SDIO - ---help--- - Frequency to use for transferring data to/from an SD card using all four data lines. - config LITEX_SDIO_MOUNT bool "Mount SDIO at startup" default n diff --git a/boards/risc-v/litex/arty_a7/configs/sdmmc/defconfig b/boards/risc-v/litex/arty_a7/configs/sdmmc/defconfig deleted file mode 100644 index 5ee0e4d97c24e..0000000000000 --- a/boards/risc-v/litex/arty_a7/configs/sdmmc/defconfig +++ /dev/null @@ -1,74 +0,0 @@ -# -# This file is autogenerated: PLEASE DO NOT EDIT IT. -# -# You can use "make menuconfig" to make any modifications to the installed .config file. -# You can then do "make savedefconfig" to generate a new defconfig file that includes your -# modifications. -# -# CONFIG_DISABLE_PTHREAD is not set -# CONFIG_FS_PROCFS_EXCLUDE_BLOCKS is not set -# CONFIG_FS_PROCFS_EXCLUDE_ENVIRON is not set -# CONFIG_FS_PROCFS_EXCLUDE_MEMDUMP is not set -# CONFIG_FS_PROCFS_EXCLUDE_MEMINFO is not set -# CONFIG_FS_PROCFS_EXCLUDE_MOUNT is not set -# CONFIG_FS_PROCFS_EXCLUDE_MOUNTS is not set -# CONFIG_FS_PROCFS_EXCLUDE_PROCESS is not set -# CONFIG_FS_PROCFS_EXCLUDE_UPTIME is not set -# CONFIG_FS_PROCFS_EXCLUDE_USAGE is not set -# CONFIG_FS_PROCFS_EXCLUDE_VERSION is not set -# CONFIG_NSH_DISABLEBG is not set -# CONFIG_NSH_DISABLE_LOSMART is not set -# CONFIG_NSH_DISABLE_UNAME is not set -# CONFIG_STANDARD_SERIAL is not set -CONFIG_ARCH="risc-v" -CONFIG_ARCH_BOARD="arty_a7" -CONFIG_ARCH_BOARD_ARTY_A7=y -CONFIG_ARCH_CHIP="litex" -CONFIG_ARCH_CHIP_LITEX=y -CONFIG_ARCH_INTERRUPTSTACK=8192 -CONFIG_ARCH_RISCV=y -CONFIG_ARCH_STACKDUMP=y -CONFIG_BOARD_LOOPSPERMSEC=10000 -CONFIG_BUILTIN=y -CONFIG_DEBUG_FULLOPT=y -CONFIG_DEBUG_SYMBOLS=y -CONFIG_DEFAULT_SMALL=y -CONFIG_DEV_ZERO=y -CONFIG_EXAMPLES_HELLO=y -CONFIG_EXAMPLES_HELLO_STACKSIZE=8192 -CONFIG_FAT_DMAMEMORY=y -CONFIG_FAT_FORCE_INDIRECT=y -CONFIG_FAT_LFN=y -CONFIG_FS_FAT=y -CONFIG_FS_FATTIME=y -CONFIG_FS_PROCFS=y -CONFIG_GRAN=y -CONFIG_IDLETHREAD_STACKSIZE=8192 -CONFIG_INIT_ENTRYPOINT="nsh_main" -CONFIG_INIT_STACKSIZE=8192 -CONFIG_INTELHEX_BINARY=y -CONFIG_LIBC_PERROR_STDOUT=y -CONFIG_LIBC_STRERROR=y -CONFIG_LITEX_SDIO=y -CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6 -CONFIG_NSH_ARCHINIT=y -CONFIG_NSH_BUILTIN_APPS=y -CONFIG_NSH_FILEIOSIZE=64 -CONFIG_NSH_STRERROR=y -CONFIG_POSIX_SPAWN_DEFAULT_STACKSIZE=8192 -CONFIG_PTHREAD_STACK_DEFAULT=8192 -CONFIG_RAM_SIZE=268435456 -CONFIG_RAM_START=0x40000000 -CONFIG_RAW_BINARY=y -CONFIG_RR_INTERVAL=200 -CONFIG_SCHED_WAITPID=y -CONFIG_STACK_COLORATION=y -CONFIG_START_DAY=20 -CONFIG_START_MONTH=3 -CONFIG_START_YEAR=2020 -CONFIG_SYSTEM_NSH=y -CONFIG_TASK_NAME_SIZE=12 -CONFIG_TESTING_GETPRIME=y -CONFIG_UART0_RXBUFSIZE=128 -CONFIG_UART0_SERIAL_CONSOLE=y -CONFIG_UART0_TXBUFSIZE=128 diff --git a/drivers/mmcsd/mmcsd_sdio.c b/drivers/mmcsd/mmcsd_sdio.c index d683c31b405d7..53c8d97598895 100644 --- a/drivers/mmcsd/mmcsd_sdio.c +++ b/drivers/mmcsd/mmcsd_sdio.c @@ -358,7 +358,6 @@ static inline int mmcsd_sendcmd4(FAR struct mmcsd_state_s *priv) if (priv->dsrimp != false) { - finfo("Card supports DSR - send DSR.\n"); /* CMD4 = SET_DSR will set the cards DSR register. The DSR and CMD4 * support are optional. However, since this is a broadcast command * with no response (like CMD0), we will never know if the DSR was @@ -373,10 +372,6 @@ static inline int mmcsd_sendcmd4(FAR struct mmcsd_state_s *priv) mmcsd_sendcmdpoll(priv, MMCSD_CMD4, CONFIG_MMCSD_DSR << 16); nxsig_usleep(MMCSD_DSR_DELAY); } - else - { - finfo("Card does not support DSR.\n"); - } #endif return ret; @@ -2480,14 +2475,9 @@ static int mmcsd_widebus(FAR struct mmcsd_state_s *priv) * SCR or in the SDIO driver capabililities) */ - if (IS_SD(priv->type) && - (priv->buswidth & MMCSD_SCR_BUSWIDTH_4BIT) != 0 && + if ((priv->buswidth & MMCSD_SCR_BUSWIDTH_4BIT) != 0 && (priv->caps & SDIO_CAPS_1BIT_ONLY) == 0) { - /* SD card supports 4-bit BUS and host settings is not 1-bit only. */ - - finfo("Setting SD BUS width to 4-bit. Card type: %d\n", priv->type); - /* Disconnect any CD/DAT3 pull up using ACMD42. ACMD42 is optional and * need not be supported by all SD calls. * @@ -2517,7 +2507,7 @@ static int mmcsd_widebus(FAR struct mmcsd_state_s *priv) return ret; } - /* Now send ACMD6 to select bus width operation, beginning + /* Now send ACMD6 to select wide, 4-bit bus operation, beginning * with CMD55, APP_CMD: */ @@ -2532,82 +2522,27 @@ static int mmcsd_widebus(FAR struct mmcsd_state_s *priv) /* Then send ACMD6 */ mmcsd_sendcmdpoll(priv, SD_ACMD6, MMCSD_ACMD6_BUSWIDTH_4); - ret = mmcsd_recv_r1(priv, SD_ACMD6); if (ret != OK) { return ret; } - } -#ifdef CONFIG_MMCSD_MMCSUPPORT - else if (IS_MMC(priv->type) && - ((priv->buswidth & MMCSD_SCR_BUSWIDTH_4BIT) != 0 && - (priv->caps & SDIO_CAPS_1BIT_ONLY) == 0)) - { - /* SD card supports 4-bit BUS and host settings is not 1-bit only. - * Configuring MMC - Use MMC_SWITCH access modes. - */ - - uint32_t arg = MMCSD_CMD6_MODE_WRITE_BYTE | MMCSD_CMD6_BUSWIDTH_RW; - - arg |= MMCSD_CMD6_BUS_WIDTH_4; - - mmcsd_sendcmdpoll(priv, MMCSD_CMD6, arg); - ret = mmcsd_recv_r1(priv, MMCSD_CMD6); - - if (ret != OK) - { - ferr("ERROR: (MMCSD_CMD6) Setting MMC BUS width: %d\n", ret); - return ret; - } - } -#endif /* #ifdef CONFIG_MMCSD_MMCSUPPORT */ - else - { - fwarn("No card inserted.\n"); - SDIO_WIDEBUS(priv->dev, false); - priv->widebus = false; - SDIO_CLOCK(priv->dev, CLOCK_SDIO_DISABLED); - nxsig_usleep(MMCSD_CLK_DELAY); - - return OK; - } - /* Configure the SDIO peripheral */ + /* Configure the SDIO peripheral */ - if ((priv->buswidth & MMCSD_SCR_BUSWIDTH_4BIT) != 0) - { finfo("Wide bus operation selected\n"); SDIO_WIDEBUS(priv->dev, true); priv->widebus = true; - } - else - { - finfo("Narrow bus operation selected\n"); - SDIO_WIDEBUS(priv->dev, false); - priv->widebus = false; - } - if (IS_SD(priv->type)) - { - if ((priv->buswidth & MMCSD_SCR_BUSWIDTH_4BIT) != 0) - { - SDIO_CLOCK(priv->dev, CLOCK_SD_TRANSFER_4BIT); - } - else - { - SDIO_CLOCK(priv->dev, CLOCK_SD_TRANSFER_1BIT); - } - } -#ifdef CONFIG_MMCSD_MMCSUPPORT - else - { - SDIO_CLOCK(priv->dev, CLOCK_MMC_TRANSFER); + SDIO_CLOCK(priv->dev, CLOCK_SD_TRANSFER_4BIT); + nxsig_usleep(MMCSD_CLK_DELAY); + return OK; } -#endif /* #ifdef CONFIG_MMCSD_MMCSUPPORT */ - nxsig_usleep(MMCSD_CLK_DELAY); - return OK; + /* Wide bus operation not supported */ + + fwarn("WARNING: Card does not support wide-bus operation\n"); + return -ENOSYS; } /**************************************************************************** @@ -2639,8 +2574,6 @@ static int mmcsd_mmcinitialize(FAR struct mmcsd_state_s *priv) * identification state / card-identification mode. */ - finfo("Initialising MMC card.\n"); - mmcsd_sendcmdpoll(priv, MMCSD_CMD2, 0); ret = SDIO_RECVR2(priv->dev, MMCSD_CMD2, cid); if (ret != OK) @@ -2657,7 +2590,7 @@ static int mmcsd_mmcinitialize(FAR struct mmcsd_state_s *priv) */ priv->rca = 1; /* There is only one card */ - mmcsd_sendcmdpoll(priv, MMC_CMD3, (uint32_t)priv->rca << 16); + mmcsd_sendcmdpoll(priv, MMC_CMD3, priv->rca << 16); ret = mmcsd_recv_r1(priv, MMC_CMD3); if (ret != OK) { @@ -2667,8 +2600,8 @@ static int mmcsd_mmcinitialize(FAR struct mmcsd_state_s *priv) /* This should have caused a transition to standby state. However, this * will not be reflected in the present R1/6 status. R1/6 contains the - * state of the card when the command was received, not when it - * completed execution. + * state of the card when the command was received, not when it completed + * execution. * * Verify that we are in standby state/data-transfer mode */ @@ -2682,18 +2615,10 @@ static int mmcsd_mmcinitialize(FAR struct mmcsd_state_s *priv) /* Send CMD9, SEND_CSD in standby state/data-transfer mode to obtain the * Card Specific Data (CSD) register, e.g., block length, card storage - * capacity, etc. (Stays in standby state/data-transfer mode). - * NOTE in v2.0 high capacity cards, the following values are always - * returned: - * - write block length = 9 = 2^9 = 512 - * - read block length = 9 = 512 - * - rw2 factor = 0x2 (010b) - * - size_mult = 0 - * We can't decode the CSD register yet as we also need to read the - * extended CSD register. + * capacity, etc. (Stays in standby state/data-transfer mode) */ - mmcsd_sendcmdpoll(priv, MMCSD_CMD9, (uint32_t) priv->rca << 16); + mmcsd_sendcmdpoll(priv, MMCSD_CMD9, priv->rca << 16); ret = SDIO_RECVR2(priv->dev, MMCSD_CMD9, csd); if (ret != OK) { @@ -2701,13 +2626,6 @@ static int mmcsd_mmcinitialize(FAR struct mmcsd_state_s *priv) return ret; } - /* Decode the CSD register to obtain version. We will need to - * decode further if card is v4.0 or higher as it supports - * ext_csd commands. - */ - - mmcsd_decode_csd(priv, csd); - /* Set the Driver Stage Register (DSR) if (1) a CONFIG_MMCSD_DSR has been * provided and (2) the card supports a DSR register. If no DSR value * the card default value (0x0404) will be used. @@ -2715,8 +2633,7 @@ static int mmcsd_mmcinitialize(FAR struct mmcsd_state_s *priv) mmcsd_sendcmd4(priv); - /* Select the card. - * Send CMD7 with the argument == RCA in order to select the card + /* Send CMD7 with the argument == RCA in order to select the card * and send it in data-trasfer mode. Since we are supporting * only a single card, we just leave the card selected all of the time. */ @@ -2729,33 +2646,14 @@ static int mmcsd_mmcinitialize(FAR struct mmcsd_state_s *priv) return ret; } - /* If the hardware only supports 4-bit transfer mode then we forced to - * attempt to setup the card in this mode before checking the ext CSD - * register. - */ - - if ((priv->caps & SDIO_CAPS_4BIT_ONLY) != 0) - { - /* Select width (4-bit) bus operation */ - - priv->buswidth = MMCSD_SCR_BUSWIDTH_4BIT; - ret = mmcsd_widebus(priv); - - if (ret != OK) - { - ferr("ERROR: Failed to set wide bus operation: %d\n", ret); - } - } - /* CSD Decoding for MMC should be done after entering in data-transfer mode * because if the card has block addressing then extended CSD register * must be read in order to get the right number of blocks and capacity, - * and BUS width but it has to be done in data-transfer mode. + * but it has to be done in data-transfer mode. */ if (IS_BLOCK(priv->type)) { - finfo("Card supports eMMC spec 4.0 (or greater). Reading ext_csd.\n"); ret = mmcsd_read_csd(priv); if (ret != OK) { @@ -2766,17 +2664,10 @@ static int mmcsd_mmcinitialize(FAR struct mmcsd_state_s *priv) mmcsd_decode_csd(priv, csd); - if ((priv->caps & SDIO_CAPS_4BIT_ONLY) != 0) - { - /* Select width (4-bit) bus operation (if the card supports it) */ - - ret = mmcsd_widebus(priv); - if (ret != OK) - { - ferr("ERROR: Failed to set wide bus operation: %d\n", ret); - } - } + /* Select high speed MMC clocking (which may depend on the DSR setting) */ + SDIO_CLOCK(priv->dev, CLOCK_MMC_TRANSFER); + nxsig_usleep(MMCSD_CLK_DELAY); return OK; } @@ -2810,7 +2701,6 @@ static int mmcsd_read_csd(FAR struct mmcsd_state_s *priv) memset(buffer, 0, sizeof(buffer)); #if defined(CONFIG_SDIO_DMA) && defined(CONFIG_ARCH_HAVE_SDIO_PREFLIGHT) - /* If we think we are going to perform a DMA transfer, make sure that we * will be able to before we commit the card to the operation. */ @@ -2839,7 +2729,7 @@ static int mmcsd_read_csd(FAR struct mmcsd_state_s *priv) return ret; } - /* Select the block size for the card (CMD16) */ + /* Select the block size for the card */ ret = mmcsd_setblocklen(priv, 512); if (ret != OK) @@ -2858,7 +2748,6 @@ static int mmcsd_read_csd(FAR struct mmcsd_state_s *priv) #ifdef CONFIG_SDIO_DMA if ((priv->caps & SDIO_CAPS_DMASUPPORTED) != 0) { - finfo("Setting up for DMA transfer.\n"); ret = SDIO_DMARECVSETUP(priv->dev, buffer, 512); if (ret != OK) { @@ -3388,9 +3277,8 @@ static int mmcsd_sdinitialize(FAR struct mmcsd_state_s *priv) { /* Select width (4-bit) bus operation */ - priv->buswidth = MMCSD_SCR_BUSWIDTH_4BIT; + priv->buswidth = 4; ret = mmcsd_widebus(priv); - if (ret != OK) { ferr("ERROR: Failed to set wide bus operation: %d\n", ret); @@ -3411,7 +3299,7 @@ static int mmcsd_sdinitialize(FAR struct mmcsd_state_s *priv) mmcsd_decode_scr(priv, scr); - if ((priv->caps & SDIO_CAPS_4BIT_ONLY) != 0) + if ((priv->caps & SDIO_CAPS_4BIT_ONLY) == 0) { /* Select width (4-bit) bus operation (if the card supports it) */ @@ -3450,8 +3338,6 @@ static int mmcsd_cardidentify(FAR struct mmcsd_state_s *priv) clock_t elapsed; int ret; - finfo("Identifying card...\n"); - /* Assume failure to identify the card */ priv->type = MMCSD_CARDTYPE_UNKNOWN; @@ -3466,13 +3352,6 @@ static int mmcsd_cardidentify(FAR struct mmcsd_state_s *priv) return -ENODEV; } - /* For eMMC, Send CMD0 with argument 0xf0f0f0f0 as per JEDEC v4.41 - * for pre-idle. No effect for SD. - */ - - mmcsd_sendcmdpoll(priv, MMCSD_CMD0, 0xf0f0f0f0); - nxsig_usleep(MMCSD_IDLE_DELAY); - /* Set ID mode clocking (<400KHz) */ SDIO_CLOCK(priv->dev, CLOCK_IDMODE); @@ -3500,14 +3379,12 @@ static int mmcsd_cardidentify(FAR struct mmcsd_state_s *priv) if (ret != OK) { - fwarn("WARNING: CMD1 RECVR3: %d. \ - NOTE: This is expected for SD cards.\n", ret); + ferr("ERROR: CMD1 RECVR3: %d\n", ret); - /* CMD1 did not succeed, card is not MMC. Return to idle - * to allow the communication to recover before another send. + /* CMD1 did not succeed, card is not MMC. This sleep let + * the communication to recover before another send. */ - mmcsd_sendcmdpoll(priv, MMCSD_CMD0, 0); nxsig_usleep(MMCSD_IDLE_DELAY); } else @@ -3597,7 +3474,7 @@ static int mmcsd_cardidentify(FAR struct mmcsd_state_s *priv) } } - /* At this point, type is either UNKNOWN, eMMC or SDV2. Try sending + /* At this point, type is either UNKNOWN or SDV2. Try sending * CMD55 and (maybe) ACMD41 for up to 1 second or until the card * exits the IDLE state. CMD55 is supported by SD V1.x and SD V2.x, * but not MMC @@ -3607,7 +3484,7 @@ static int mmcsd_cardidentify(FAR struct mmcsd_state_s *priv) elapsed = 0; do { - /* We may have already determined that this card is an MMC card from + /* We may have already determined that his card is an MMC card from * an earlier pass through this loop. In that case, we should * skip the SD-specific commands. */ @@ -3728,8 +3605,6 @@ static int mmcsd_cardidentify(FAR struct mmcsd_state_s *priv) { /* CMD1 succeeded... this must be an MMC card */ - finfo("Confirmed MMC card present.\n"); - priv->type = MMCSD_CARDTYPE_MMC; /* Now, check if this is a MMC card/chip that supports block @@ -3761,13 +3636,9 @@ static int mmcsd_cardidentify(FAR struct mmcsd_state_s *priv) * Then break out of the look with an MMC card identified */ - finfo("MMC card/chip is ready!\n"); + finfo("MMC card/chip ready!\n"); break; } - else - { - finfo("MMC card/chip is busy. Waiting for reply...\n"); - } } } #endif @@ -3840,8 +3711,6 @@ static int mmcsd_probe(FAR struct mmcsd_state_s *priv) { /* Yes.. probe it. First, what kind of card was inserted? */ - finfo("Card present. Probing....\n"); - ret = mmcsd_cardidentify(priv); if (ret != OK) { @@ -3856,33 +3725,24 @@ static int mmcsd_probe(FAR struct mmcsd_state_s *priv) /* Bit 1: SD version 1.x */ case MMCSD_CARDTYPE_SDV1: - finfo("SD version 1.x .\n"); - ret = mmcsd_sdinitialize(priv); - break; /* SD version 2.x with byte addressing */ case MMCSD_CARDTYPE_SDV2: - finfo("SD version 2.x with byte addressing.\n"); - ret = mmcsd_sdinitialize(priv); - break; /* SD version 2.x with block addressing */ case MMCSD_CARDTYPE_SDV2 | MMCSD_CARDTYPE_BLOCK: - finfo("SD version 2.x with block addressing.\n"); ret = mmcsd_sdinitialize(priv); break; /* MMC card with byte addressing */ case MMCSD_CARDTYPE_MMC: - finfo("MMC card with byte addressing.\n"); /* MMC card with block addressing */ case MMCSD_CARDTYPE_MMC | MMCSD_CARDTYPE_BLOCK: - finfo("MMC card with block addressing.\n"); #ifdef CONFIG_MMCSD_MMCSUPPORT ret = mmcsd_mmcinitialize(priv); break; @@ -3967,10 +3827,8 @@ static int mmcsd_removed(FAR struct mmcsd_state_s *priv) /* Go back to the default 1-bit data bus. */ - priv->buswidth = MMCSD_SCR_BUSWIDTH_1BIT; SDIO_WIDEBUS(priv->dev, false); priv->widebus = false; - mmcsd_widebus(priv); /* Disable clocking to the card */ diff --git a/drivers/mmcsd/mmcsd_sdio.h b/drivers/mmcsd/mmcsd_sdio.h index 031a81a76d1ea..83e1c445c82be 100644 --- a/drivers/mmcsd/mmcsd_sdio.h +++ b/drivers/mmcsd/mmcsd_sdio.h @@ -32,32 +32,6 @@ * Pre-processor Definitions ****************************************************************************/ -/* CMD6 (MMC_SWITCH) argument - * MMC_SWITCH argument format: - * - * [31:26] Always 0 - * [25:24] Access Mode - * [23:16] Location of target Byte in EXT_CSD - * [15:08] Value Byte - * [07:03] Always 0 - * [02:00] Command Set - */ -#define MMCSD_CMD6_BUSWIDTH_RWSHIFT (16) -# define MMCSD_CMD6_BUSWIDTH_RW ((uint32_t)0xb7 << MMCSD_CMD6_BUSWIDTH_RWSHIFT) /* R/W */ - -#define MMCSD_CMD6_WRITE_BYTE_SHIFT (24) -# define MMCSD_CMD6_MODE_CMD_SET ((uint32_t)0x00 << MMCSD_CMD6_WRITE_BYTE_SHIFT) /* Change the command set */ -# define MMCSD_CMD6_MODE_SET_BITS ((uint32_t)0x01 << MMCSD_CMD6_WRITE_BYTE_SHIFT) /* Set bits which are 1 in value */ -# define MMCSD_CMD6_MODE_CLEAR_BITS ((uint32_t)0x02 << MMCSD_CMD6_WRITE_BYTE_SHIFT) /* Clear bits which are 1 in value */ -# define MMCSD_CMD6_MODE_WRITE_BYTE ((uint32_t)0x03 << MMCSD_CMD6_WRITE_BYTE_SHIFT) /* Set target to value */ - -#define MMCSD_CMD6_BUS_WIDTH_SHIFT (8) -# define MMCSD_CMD6_BUS_WIDTH_1 ((uint32_t)0x00 << MMCSD_CMD6_BUS_WIDTH_SHIFT) /* Card is in 1 bit mode */ -# define MMCSD_CMD6_BUS_WIDTH_4 ((uint32_t)0x01 << MMCSD_CMD6_BUS_WIDTH_SHIFT) /* Card is in 4 bit mode */ -# define MMCSD_CMD6_CSD_BUS_WIDTH_8 ((uint32_t)0x02 << MMCSD_CMD6_BUS_WIDTH_SHIFT) /* Card is in 8 bit mode */ -# define MMCSD_CMD6_DDR_BUS_WIDTH_4 ((uint32_t)0x05 << MMCSD_CMD6_BUS_WIDTH_SHIFT) /* Card is in 4 bit DDR mode */ -# define MMCSD_CMD6_DDR_BUS_WIDTH_8 ((uint32_t)0x06 << MMCSD_CMD6_BUS_WIDTH_SHIFT) /* Card is in 8 bit DDR mode */ - /* CMD8 Argument: * [31:12]: Reserved (shall be set to '0') * [11:8]: Supply Voltage (VHS) 0x1 (Range: 2.7-3.6 V) From c356bfbcd1cb652dfdcb08dd91fd7f513cb655a8 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Tue, 29 Aug 2023 13:52:31 +0300 Subject: [PATCH 75/79] arch/risc-v/src/mpfs: Sync some of the libero config macros with HSS reference code Signed-off-by: Jukka Laitinen Co-authored-by: Eero Nurkkala --- arch/risc-v/src/mpfs/hardware/mpfs_sgmii.h | 6 ++++-- arch/risc-v/src/mpfs/mpfs_ddr.c | 22 ++++++++++++++++------ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/arch/risc-v/src/mpfs/hardware/mpfs_sgmii.h b/arch/risc-v/src/mpfs/hardware/mpfs_sgmii.h index 566e1fe654b3b..126ace313667b 100644 --- a/arch/risc-v/src/mpfs/hardware/mpfs_sgmii.h +++ b/arch/risc-v/src/mpfs/hardware/mpfs_sgmii.h @@ -152,7 +152,7 @@ #define MPFS_CFG_DDR_SGMII_PHY_SOFT_RESET_DDR_PHY_OFFSET 0x000 #define MPFS_CFG_DDR_SGMII_PHY_DDRPHY_MODE_OFFSET 0x004 #define MPFS_CFG_DDR_SGMII_PHY_STARTUP_OFFSET 0x008 -#define MPFS_CFG_DDR_SGMII_PHY_SPARE_0_OFFSET 0x00c +#define MPFS_CFG_DDR_SGMII_PHY_UNUSED_SPACE0_OFFSET 0x00c #define MPFS_CFG_DDR_SGMII_PHY_SOFT_RESET_MAIN_PLL_OFFSET 0x080 #define MPFS_CFG_DDR_SGMII_PHY_PLL_CTRL_MAIN_OFFSET 0x084 #define MPFS_CFG_DDR_SGMII_PHY_PLL_REF_FB_MAIN_OFFSET 0x088 @@ -566,18 +566,19 @@ /* SGMII register definitions */ +#define MPFS_CFG_DDR_SGMII_PHY_SPARE0 (MPFS_CFG_DDR_SGMII_PHY_BASE + MPFS_CFG_DDR_SGMII_PHY_SPARE0_OFFSET) #define MPFS_CFG_DDR_SGMII_PHY_SOFT_RESET_DECODER_DRIVER (MPFS_CFG_DDR_SGMII_PHY_BASE + MPFS_CFG_DDR_SGMII_PHY_SOFT_RESET_DECODER_DRIVER_OFFSET) #define MPFS_CFG_DDR_SGMII_PHY_SOFT_RESET_DECODER_ODT (MPFS_CFG_DDR_SGMII_PHY_BASE + MPFS_CFG_DDR_SGMII_PHY_SOFT_RESET_DECODER_ODT_OFFSET) #define MPFS_CFG_DDR_SGMII_PHY_SOFT_RESET_DECODER_IO (MPFS_CFG_DDR_SGMII_PHY_BASE + MPFS_CFG_DDR_SGMII_PHY_SOFT_RESET_DECODER_IO_OFFSET) #define MPFS_CFG_DDR_SGMII_PHY_TRAINING_START (MPFS_CFG_DDR_SGMII_PHY_BASE + MPFS_CFG_DDR_SGMII_PHY_TRAINING_START_OFFSET) #define MPFS_CFG_DDR_SGMII_PHY_DDRPHY_MODE (MPFS_CFG_DDR_SGMII_PHY_BASE + MPFS_CFG_DDR_SGMII_PHY_DDRPHY_MODE_OFFSET) +#define MPFS_CFG_DDR_SGMII_PHY_UNUSED_SPACE0 (MPFS_CFG_DDR_SGMII_PHY_BASE + MPFS_CFG_DDR_SGMII_PHY_UNUSED_SPACE0_OFFSET) #define MPFS_CFG_DDR_SGMII_PHY_DPC_BITS (MPFS_CFG_DDR_SGMII_PHY_BASE + MPFS_CFG_DDR_SGMII_PHY_DPC_BITS_OFFSET) #define MPFS_CFG_DDR_SGMII_PHY_RPC95 (MPFS_CFG_DDR_SGMII_PHY_BASE + MPFS_CFG_DDR_SGMII_PHY_RPC95_OFFSET) #define MPFS_CFG_DDR_SGMII_PHY_RPC96 (MPFS_CFG_DDR_SGMII_PHY_BASE + MPFS_CFG_DDR_SGMII_PHY_RPC96_OFFSET) #define MPFS_CFG_DDR_SGMII_PHY_RPC97 (MPFS_CFG_DDR_SGMII_PHY_BASE + MPFS_CFG_DDR_SGMII_PHY_RPC97_OFFSET) #define MPFS_CFG_DDR_SGMII_PHY_RPC98 (MPFS_CFG_DDR_SGMII_PHY_BASE + MPFS_CFG_DDR_SGMII_PHY_RPC98_OFFSET) -#define MPFS_CFG_DDR_SGMII_PHY_SPARE_0 (MPFS_CFG_DDR_SGMII_PHY_BASE + MPFS_CFG_DDR_SGMII_PHY_SPARE_0_OFFSET) #define MPFS_CFG_DDR_SGMII_PHY_SPIO253 (MPFS_CFG_DDR_SGMII_PHY_BASE + MPFS_CFG_DDR_SGMII_PHY_SPIO253_OFFSET) #define MPFS_CFG_DDR_SGMII_PHY_RPC10_ODT (MPFS_CFG_DDR_SGMII_PHY_BASE + MPFS_CFG_DDR_SGMII_PHY_RPC10_ODT_OFFSET) #define MPFS_CFG_DDR_SGMII_PHY_RPC11_ODT (MPFS_CFG_DDR_SGMII_PHY_BASE + MPFS_CFG_DDR_SGMII_PHY_RPC11_ODT_OFFSET) @@ -605,6 +606,7 @@ #define MPFS_CFG_DDR_SGMII_PHY_RPC166 (MPFS_CFG_DDR_SGMII_PHY_BASE + MPFS_CFG_DDR_SGMII_PHY_RPC166_OFFSET) #define MPFS_CFG_DDR_SGMII_PHY_RPC168 (MPFS_CFG_DDR_SGMII_PHY_BASE + MPFS_CFG_DDR_SGMII_PHY_RPC168_OFFSET) #define MPFS_CFG_DDR_SGMII_PHY_RPC220 (MPFS_CFG_DDR_SGMII_PHY_BASE + MPFS_CFG_DDR_SGMII_PHY_RPC220_OFFSET) +#define MPFS_CFG_DDR_SGMII_PHY_RPC226 (MPFS_CFG_DDR_SGMII_PHY_BASE + MPFS_CFG_DDR_SGMII_PHY_RPC226_OFFSET) #define MPFS_CFG_DDR_SGMII_PHY_RPC235 (MPFS_CFG_DDR_SGMII_PHY_BASE + MPFS_CFG_DDR_SGMII_PHY_RPC235_OFFSET) #define MPFS_CFG_DDR_SGMII_PHY_RPC236 (MPFS_CFG_DDR_SGMII_PHY_BASE + MPFS_CFG_DDR_SGMII_PHY_RPC236_OFFSET) #define MPFS_CFG_DDR_SGMII_PHY_RPC237 (MPFS_CFG_DDR_SGMII_PHY_BASE + MPFS_CFG_DDR_SGMII_PHY_RPC237_OFFSET) diff --git a/arch/risc-v/src/mpfs/mpfs_ddr.c b/arch/risc-v/src/mpfs/mpfs_ddr.c index 0ed14b4ac3336..31cacb5e696dc 100644 --- a/arch/risc-v/src/mpfs/mpfs_ddr.c +++ b/arch/risc-v/src/mpfs/mpfs_ddr.c @@ -373,12 +373,12 @@ static void mpfs_ddr_off_mode(void) putreg32(0x07, MPFS_CFG_DDR_SGMII_PHY_RPC97); /* dq */ putreg32(0x07, MPFS_CFG_DDR_SGMII_PHY_RPC98); /* dqs */ - /* SPARE_0: + /* UNUSED_SPACE0: * bits 15:14 connect to ibufmx DQ/DQS/DM * bits 13:12 connect to ibufmx CA/CK */ - putreg32(0, MPFS_CFG_DDR_SGMII_PHY_SPARE_0); + putreg32(0, MPFS_CFG_DDR_SGMII_PHY_UNUSED_SPACE0); /* REG_POWERDOWN_B on PLL turn-off, in case was turned on */ @@ -530,21 +530,21 @@ static void mpfs_set_ddr_rpc_regs(struct mpfs_ddr_priv_s *priv) } putreg32(0x04, MPFS_CFG_DDR_SGMII_PHY_RPC98); - putreg32(0, MPFS_CFG_DDR_SGMII_PHY_SPARE_0); + putreg32(0, MPFS_CFG_DDR_SGMII_PHY_UNUSED_SPACE0); #elif defined(CONFIG_MPFS_DDR_TYPE_DDR4) putreg32(2, MPFS_CFG_DDR_SGMII_PHY_RPC10_ODT); putreg32(2, MPFS_CFG_DDR_SGMII_PHY_RPC11_ODT); putreg32(0x04, MPFS_CFG_DDR_SGMII_PHY_RPC98); - putreg32(0, MPFS_CFG_DDR_SGMII_PHY_SPARE_0); + putreg32(0, MPFS_CFG_DDR_SGMII_PHY_UNUSED_SPACE0); #elif defined(CONFIG_MPFS_DDR_TYPE_LPDDR3) putreg32(2, MPFS_CFG_DDR_SGMII_PHY_RPC10_ODT); putreg32(2, MPFS_CFG_DDR_SGMII_PHY_RPC11_ODT); putreg32(0x04, MPFS_CFG_DDR_SGMII_PHY_RPC98); - putreg32(0, MPFS_CFG_DDR_SGMII_PHY_SPARE_0); + putreg32(0, MPFS_CFG_DDR_SGMII_PHY_UNUSED_SPACE0); #elif defined(CONFIG_MPFS_DDR_TYPE_LPDDR4) @@ -578,8 +578,18 @@ static void mpfs_set_ddr_rpc_regs(struct mpfs_ddr_priv_s *priv) putreg32(1, MPFS_CFG_DDR_SGMII_PHY_SPIO253); } + /* Write ibufmd_dqs. Value is a constant coped from HSS refenrece code */ + putreg32(0x04, MPFS_CFG_DDR_SGMII_PHY_RPC98); - putreg32(0xa000, MPFS_CFG_DDR_SGMII_PHY_SPARE_0); + + /* Write TXDLY offset data. 0x14 is a constant copied from HSS reference code, it is + * unknown whether this needs to be adjustable at the moment + */ + + putreg32(0x14, MPFS_CFG_DDR_SGMII_PHY_RPC226); + + putreg32(0xa000, MPFS_CFG_DDR_SGMII_PHY_UNUSED_SPACE0); + putreg32(0xa000, MPFS_CFG_DDR_SGMII_PHY_SPARE0); #endif From 3ce090eb24a610016ca4a3106d3d13ba03e49502 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Sun, 27 Aug 2023 14:41:06 +0300 Subject: [PATCH 76/79] arch/risc-v/src/mpfs/mpfs_ddr.c: Re-write write calibration Clean up the code and remove un-used global variables & structs Signed-off-by: Jukka Laitinen --- arch/risc-v/src/mpfs/mpfs_ddr.c | 196 +++++++++----------------------- 1 file changed, 51 insertions(+), 145 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_ddr.c b/arch/risc-v/src/mpfs/mpfs_ddr.c index 31cacb5e696dc..d4b2f43252ca2 100644 --- a/arch/risc-v/src/mpfs/mpfs_ddr.c +++ b/arch/risc-v/src/mpfs/mpfs_ddr.c @@ -192,37 +192,6 @@ enum ddr_access_size_e DDR_64_BIT }; -typedef struct -{ - uint32_t status_lower; - uint32_t status_upper; - uint32_t lower; - uint32_t upper; - uint32_t vref_result; -} mss_ddr_vref_t; - -typedef struct -{ - uint32_t status_lower; - uint32_t lower[MAX_LANES]; - uint32_t lane_calib_result; -} mss_mpfs_ddr_write_calibration_t; - -typedef struct -{ - uint32_t lower[MAX_LANES]; - uint32_t upper[MAX_LANES]; - uint32_t calibration_found[MAX_LANES]; -} mss_lpddr4_dq_calibration_t; - -typedef struct -{ - mss_mpfs_ddr_write_calibration_t write_cal; - mss_lpddr4_dq_calibration_t dq_cal; - mss_ddr_vref_t fpga_vref; - mss_ddr_vref_t mem_vref; -} mss_ddr_calibration_t; - struct mpfs_ddr_priv_s { uint32_t tip_cfg_params; @@ -238,8 +207,6 @@ struct mpfs_ddr_priv_s * Private Data ****************************************************************************/ -static mss_ddr_calibration_t calib_data; - static struct mpfs_ddr_priv_s g_mpfs_ddr_priv = { .en_addcmd0_ovrt9 = true, @@ -582,8 +549,8 @@ static void mpfs_set_ddr_rpc_regs(struct mpfs_ddr_priv_s *priv) putreg32(0x04, MPFS_CFG_DDR_SGMII_PHY_RPC98); - /* Write TXDLY offset data. 0x14 is a constant copied from HSS reference code, it is - * unknown whether this needs to be adjustable at the moment + /* Write TXDLY offset data. 0x14 is a constant copied from HSS reference + * code, it is unknown whether this needs to be adjustable at the moment */ putreg32(0x14, MPFS_CFG_DDR_SGMII_PHY_RPC226); @@ -1731,8 +1698,6 @@ static void mpfs_load_dq(uint8_t lane) { modifyreg32(MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1, 0x0f, 0); } - - putreg32(0x08, MPFS_CFG_DDR_SGMII_PHY_EXPERT_MODE_EN); } #endif @@ -1900,12 +1865,6 @@ static int mpfs_mtc_test(uint8_t mask, uint64_t start_address, modifyreg32(MPFS_DDR_CSR_APB_MT_ERROR_MASK_4, 0x0000f000, 0); } - /* MT_EN - Enables memory test. If asserted at end of memory test, - * will keep going. - */ - - putreg32(0, MPFS_DDR_CSR_APB_MT_EN); - /* MT_EN_SINGLE - Will not repeat if this is set */ putreg32(0, MPFS_DDR_CSR_APB_MT_EN_SINGLE); @@ -1969,6 +1928,7 @@ static int mpfs_mtc_test_all(uint8_t mask, uint64_t start_address, /* Test all patterns except MTC_USER */ + result = 0; for (test_pattern = MTC_COUNTING_PATTERN; test_pattern <= MTC_PSEUDO_RANDOM_8BIT && result == 0; test_pattern++) @@ -1988,50 +1948,6 @@ static int mpfs_mtc_test_all(uint8_t mask, uint64_t start_address, return result; } -/**************************************************************************** - * Name: mpfs_set_write_calib - * - * Description: - * Sets and stores the calibrated values. - * - * Input Parameters: - * priv - Instance of the ddr private state structure - * - * Returned Value: - * Zero (OK) is returned on success. A nonzero value indicates a fail. - * - ****************************************************************************/ - -static void mpfs_set_write_calib(struct mpfs_ddr_priv_s *priv) -{ - uint32_t temp = 0; - uint8_t lane_to_set; - uint8_t shift = 0; - uint32_t lanes = priv->number_of_lanes_to_calibrate; - - /* Calculate the calibrated value and write back */ - - calib_data.write_cal.lane_calib_result = 0; - for (lane_to_set = 0; lane_to_set < lanes; lane_to_set++) - { - temp = calib_data.write_cal.lower[lane_to_set]; - calib_data.write_cal.lane_calib_result = \ - calib_data.write_cal.lane_calib_result | (temp << (shift)); - shift = (uint8_t)(shift + 0x04); - } - - /* bit 3 must be set if we want to use the expert_wrcalib - * register. - */ - - putreg32(0x08, MPFS_CFG_DDR_SGMII_PHY_EXPERT_MODE_EN); - - /* Set the calibrated value */ - - putreg32(calib_data.write_cal.lane_calib_result, - MPFS_CFG_DDR_SGMII_PHY_EXPERT_WRCALIB); -} - /**************************************************************************** * Name: mpfs_write_calibration_using_mtc * @@ -2054,17 +1970,24 @@ static int mpfs_write_calibration_using_mtc(struct mpfs_ddr_priv_s *priv) uint64_t start_address = 0x00; uint32_t size = ONE_MB_MTC; int result = 0; - uint8_t lane_to_test; + uint8_t done = 0x0; + uint8_t lane; uint32_t cal_data; - uint32_t lanes; + int lanes; + uint8_t offset[MAX_LANES]; + uint8_t done_mask; - calib_data.write_cal.status_lower = 0U; + /* Initialize number of lanes */ + + lanes = priv->number_of_lanes_to_calibrate; /* Bit 3 must be set if we want to use the expert_wrcalib register. */ putreg32(0x08, MPFS_CFG_DDR_SGMII_PHY_EXPERT_MODE_EN); - lanes = priv->number_of_lanes_to_calibrate; + /* mask of as many 1 bits as there are lanes */ + + done_mask = 0xff >> (8 - lanes); /* Training carried out here: sweeping write calibration offset from 0 to F * Explanation: A register, expert_wrcalib, is described in MSS DDR TIP @@ -2073,73 +1996,62 @@ static int mpfs_write_calibration_using_mtc(struct mpfs_ddr_priv_s *priv) * with the respect to the address and command for each lane. */ - for (cal_data = 0x00000; cal_data < 0xfffff && result != -ETIMEDOUT; + for (cal_data = 0x00000; + cal_data < 0xfffff && done != done_mask && result != -ETIMEDOUT; cal_data += 0x11111) { putreg32(cal_data, MPFS_CFG_DDR_SGMII_PHY_EXPERT_WRCALIB); - for (lane_to_test = 0x00; - lane_to_test < lanes && result != -ETIMEDOUT; - lane_to_test++) + for (lane = 0; lane < lanes && result != -ETIMEDOUT; lane++) { - uint8_t mask = (uint8_t)(1 << lane_to_test); - result = mpfs_mtc_test_all(mask, start_address, size, - MTC_ADD_SEQUENTIAL); - - if (result == 0) /* if passed for this lane */ - { - if ((calib_data.write_cal.status_lower & - (0x01 << lane_to_test)) == 0) - { - /* Still looking for good value */ - - calib_data.write_cal.lower[lane_to_test] = - (cal_data & 0xf); - calib_data.write_cal.status_lower |= - (0x01 << lane_to_test); - } + uint8_t cal_value = cal_data & 0xf; + uint8_t mask = (uint8_t)(0x1 << lane); - /* Check the result */ + /* Check if this lane is not yet done and the test passes */ - uint32_t lane_to_check; - - for (lane_to_check = 0; lane_to_check < lanes; - lane_to_check++) - { - if (((calib_data.write_cal.status_lower) & - (0x01 << lane_to_check)) == 0) - { - /* not finished, still looking */ - - result = 1; - break; - } - } + if (!(done & (0x1 << lane))) + { + /* First passing value is the offset point, record it */ + result = mpfs_mtc_test_all(mask, start_address, size, + MTC_ADD_SEQUENTIAL); if (result == 0) { - /* We're good for all lanes, can stop */ - - break; + offset[lane] = cal_value; + done |= 1 << lane; } } } + } - if (result == 0) - { - /* if true, we are good for all lanes, can stop searching */ + /* If calibration was successful, calculate and set the value */ - break; + if (done == done_mask) + { + /* Calibration succeeded, set the result */ + + result = 0; + + /* Create cal_data mask from individua lane offsets */ + + cal_data = 0x0; + for (lane = 0; lane < lanes; lane++) + { + cal_data |= offset[lane] << (lane * 4); } - } - /* If calibration successful, calculate and set the value */ + /* Set the write calibration which has been calculated */ - if (result == 0) + putreg32(cal_data, + MPFS_CFG_DDR_SGMII_PHY_EXPERT_WRCALIB); + } + else if (result == 0) { - /* Set the write calibration which has been calculated */ + /* Just in case calibration is not done but last result from lane test + * was OK + */ - mpfs_set_write_calib(priv); + result = 1; } return result; @@ -3076,8 +2988,6 @@ static void mpfs_ddr_sm_init(struct mpfs_ddr_priv_s *priv) priv->refclk_sweep_index = 0xf; priv->number_of_lanes_to_calibrate = mpfs_get_num_lanes(); - - memset(&calib_data, 0, sizeof(calib_data)); } /**************************************************************************** @@ -3094,8 +3004,6 @@ static void mpfs_ddr_sm_init(struct mpfs_ddr_priv_s *priv) static void mpfs_ddr_fail(struct mpfs_ddr_priv_s *priv) { - memset(&calib_data, 0, sizeof(calib_data)); - putreg32(0, MPFS_DDR_CSR_APB_PHY_DFI_INIT_START); /* Reset controller */ @@ -3774,15 +3682,13 @@ static int mpfs_training_write_calibration(struct mpfs_ddr_priv_s *priv) /* Now start the write calibration as training has been successful */ #ifdef CONFIG_MPFS_DDR_TYPE_LPDDR4 - uint32_t nr_lanes; uint8_t lane; /* Changed default value to centre dq/dqs on window */ putreg32(0x0c, MPFS_CFG_DDR_SGMII_PHY_RPC220); - nr_lanes = mpfs_get_num_lanes(); - for (lane = 0; lane < nr_lanes; lane++) + for (lane = 0; lane < priv->number_of_lanes_to_calibrate; lane++) { mpfs_load_dq(lane); } From 2563e1678820407839ff2fc4808a9b9215ac476c Mon Sep 17 00:00:00 2001 From: Jani Paalijarvi Date: Wed, 30 Aug 2023 15:14:35 +0300 Subject: [PATCH 77/79] arch/risc-v/src/mpfs: Set USB DMA upper addr offset Use a configuration register to set the upper address lines [37:32] for USB DMA engine. Signed-off-by: Jani Paalijarvi --- arch/risc-v/src/mpfs/hardware/mpfs_usb.h | 8 ++++++++ arch/risc-v/src/mpfs/mpfs_usb.c | 8 ++++++++ boards/risc-v/mpfs/icicle/include/board.h | 2 ++ 3 files changed, 18 insertions(+) diff --git a/arch/risc-v/src/mpfs/hardware/mpfs_usb.h b/arch/risc-v/src/mpfs/hardware/mpfs_usb.h index 863044d8ddd9a..bbea409fbdaba 100644 --- a/arch/risc-v/src/mpfs/hardware/mpfs_usb.h +++ b/arch/risc-v/src/mpfs/hardware/mpfs_usb.h @@ -142,6 +142,8 @@ #define MPFS_USB_C_T_HHSRTN_OFFSET 0x346 #define MPFS_USB_C_T_HSBT_OFFSET 0x348 +#define MPFS_USB_DMA_ADDR_UPPER_REG_OFFSET 0x3FC + #define MPFS_USB_POWER (MPFS_USB_BASE + MPFS_USB_POWER_OFFSET) #define MPFS_USB_POWER_ENABLE_SUSPENDM (1 << 0) #define MPFS_USB_POWER_SUSPEND_MODE (1 << 1) @@ -175,6 +177,12 @@ #define MPFS_USB_RX_DPBUF_DIS (MPFS_USB_BASE + MPFS_USB_RX_DPBUF_DIS_OFFSET) #define MPFS_USB_TX_DPBUF_DIS (MPFS_USB_BASE + MPFS_USB_TX_DPBUF_DIS_OFFSET) +/* MPFS_USB_DMA_ADDR_UPPER_REG is used to set the upper 6-bits of + * the Address bus for USB DMA operations. + */ + +#define MPFS_USB_DMA_ADDR_UPPER_REG (MPFS_USB_BASE + MPFS_USB_DMA_ADDR_UPPER_REG_OFFSET) + #define MPFS_USB_DMA_CHANNEL(n) (MPFS_USB_BASE + MPFS_USB_DMA_CHANNEL_OFFSET + MPFS_USB_DMA_CHANNEL_SIZE * n) /**************************************************************************** diff --git a/arch/risc-v/src/mpfs/mpfs_usb.c b/arch/risc-v/src/mpfs/mpfs_usb.c index 8f0e11bc20e1c..c8983b16c1ab3 100644 --- a/arch/risc-v/src/mpfs/mpfs_usb.c +++ b/arch/risc-v/src/mpfs/mpfs_usb.c @@ -129,6 +129,10 @@ # define MSB 1 #endif +#ifndef MPFS_USB_DMA_ADDR_UPPER_OFFSET +# define MPFS_USB_DMA_ADDR_UPPER_OFFSET 0x14u +#endif + #define MPFS_NUM_USB_PKT 1 #define MPFS_MIN_EP_FIFO_SIZE 8 #define MPFS_USB_REG_MAX 0x2000 @@ -3685,6 +3689,10 @@ static void mpfs_hw_setup(struct mpfs_usbdev_s *priv) modifyreg32(MPFS_SYSREG_SOFT_RESET_CR, SYSREG_SOFT_RESET_CR_USB | SYSREG_SOFT_RESET_CR_FPGA, 0); + /* Set USB upper address offset to enable USB DMA support for himen */ + + mpfs_putreg32(MPFS_USB_DMA_ADDR_UPPER_OFFSET, MPFS_USB_DMA_ADDR_UPPER_REG); + /* Reset the controller */ mpfs_putreg8(SOFT_RESET_REG_MASK, MPFS_USB_SOFT_RST); diff --git a/boards/risc-v/mpfs/icicle/include/board.h b/boards/risc-v/mpfs/icicle/include/board.h index ad8da65db8e8f..28adc89988025 100644 --- a/boards/risc-v/mpfs/icicle/include/board.h +++ b/boards/risc-v/mpfs/icicle/include/board.h @@ -45,6 +45,8 @@ # define MPFS_SD_CLOCK_4BIT MPFS_MMC_CLOCK_25MHZ #endif +#define MPFS_USB_DMA_ADDR_UPPER_OFFSET 0x14u + /* Clocking TODO: */ #define MPFS_MSS_EXT_SGMII_REF_CLK (125000000UL) From 25d9216785a299829a759a1bb500c2b5b23a372c Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Tue, 5 Sep 2023 15:58:18 +0300 Subject: [PATCH 78/79] drivers/timers/pcf85263.c: Fix compilation Add the missing semicolons Signed-off-by: Jukka Laitinen --- drivers/timers/pcf85263.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/timers/pcf85263.c b/drivers/timers/pcf85263.c index e28685669a78d..0c7de5899a4f0 100644 --- a/drivers/timers/pcf85263.c +++ b/drivers/timers/pcf85263.c @@ -309,7 +309,7 @@ int up_rtc_getdatetime(FAR struct tm *tp) ret = I2C_TRANSFER(g_pcf85263.i2c, msg, 4); if (ret < 0) { - rtcerr("ERROR: I2C_TRANSFER failed: %d\n", ret) + rtcerr("ERROR: I2C_TRANSFER failed: %d\n", ret); return ret; } } @@ -400,7 +400,7 @@ int up_rtc_settime(FAR const struct timespec *tp) if (localtime_r(&newtime, &newtm) == NULL) { - rtcerr("ERROR: localtime_r failed\n") + rtcerr("ERROR: localtime_r failed\n"); return -EINVAL; } @@ -477,7 +477,7 @@ int up_rtc_settime(FAR const struct timespec *tp) ret = I2C_TRANSFER(g_pcf85263.i2c, msg, 3); if (ret < 0) { - rtcerr("ERROR: I2C_TRANSFER failed: %d\n", ret) + rtcerr("ERROR: I2C_TRANSFER failed: %d\n", ret); return ret; } } From 716413b2017fe5e2e0f24ab2f2eb8421a9b434c4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Sep 2023 03:34:30 +0000 Subject: [PATCH 79/79] build(deps): bump actions/checkout from 3 to 4 Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/build.yml | 4 ++-- .github/workflows/check.yml | 2 +- .github/workflows/doc.yml | 2 +- .github/workflows/docker_linux.yml | 2 +- .github/workflows/lint.yml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 79d9afc3f1bf7..da91fb6c27c0e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -89,7 +89,7 @@ jobs: echo "app_ref=$APPS_REF" >> $GITHUB_OUTPUT - name: Checkout nuttx repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: tiiuae/nuttx ref: ${{ steps.gittargets.outputs.os_ref }} @@ -99,7 +99,7 @@ jobs: run: git -C sources/nuttx fetch --tags - name: Checkout apps repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: tiiuae/incubator-nuttx-apps ref: ${{ steps.gittargets.outputs.apps_ref }} diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 28adffb82a5e3..ca0cd858f63b8 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -30,7 +30,7 @@ jobs: steps: - name: Checkout nuttx repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: tiiuae/nuttx path: nuttx diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index 53c6c51825df2..81a16de70d0a0 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -27,7 +27,7 @@ jobs: build-html: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-python@v4 with: python-version: '3.8' diff --git a/.github/workflows/docker_linux.yml b/.github/workflows/docker_linux.yml index 0494d14e8a1da..75593042f52f3 100644 --- a/.github/workflows/docker_linux.yml +++ b/.github/workflows/docker_linux.yml @@ -46,7 +46,7 @@ jobs: IMAGE_TAG: ghcr.io/${{ github.repository }}/apache-nuttx-ci-linux steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 0b0324560e464..b7c1070be4bb5 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -17,7 +17,7 @@ jobs: name: Lint runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - run: mkdir super-linter.report