From c6ad5be9a5e3dfe643c668a8dd5f9ccee5276264 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Mon, 22 Nov 2021 14:58:29 +0200 Subject: [PATCH 001/138] 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 002/138] 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 003/138] 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 004/138] [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 005/138] [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 006/138] 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 007/138] 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 008/138] 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 009/138] 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 010/138] 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 011/138] 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 012/138] 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 013/138] 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 014/138] 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 015/138] 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 016/138] 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 017/138] 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 018/138] 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 019/138] 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 020/138] 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 021/138] 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 022/138] 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 023/138] 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 024/138] 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 025/138] 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 026/138] 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 027/138] 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 028/138] 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 029/138] 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 030/138] 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 031/138] 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 032/138] 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 033/138] 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 034/138] 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 035/138] 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 036/138] 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 037/138] 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 038/138] 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 039/138] 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 040/138] 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 041/138] 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 042/138] 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 043/138] 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 044/138] 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 045/138] 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 046/138] 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 047/138] 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 048/138] [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 049/138] 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 050/138] 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 051/138] 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 052/138] 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 053/138] 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 054/138] 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 055/138] 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 056/138] 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 057/138] 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 058/138] 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 059/138] 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 060/138] 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 061/138] 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 062/138] 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 063/138] 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 064/138] 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 065/138] 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 066/138] 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 067/138] 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 068/138] 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 069/138] 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 070/138] 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 071/138] 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 072/138] 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 073/138] 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 074/138] 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 075/138] 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 076/138] 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 077/138] 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 078/138] 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 19be1d87c1dfe1d3a8a70ce539d6f8e27a439860 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Thu, 31 Aug 2023 14:28:59 +0300 Subject: [PATCH 079/138] drivers/net: Add a management driver for ksz9477 ethernet switch Signed-off-by: Jukka Laitinen --- drivers/net/Kconfig | 24 ++++ drivers/net/Make.defs | 9 ++ drivers/net/ksz9477.c | 260 ++++++++++++++++++++++++++++++++++++ drivers/net/ksz9477_i2c.c | 111 +++++++++++++++ drivers/net/ksz9477_reg.h | 155 +++++++++++++++++++++ include/nuttx/net/ksz9477.h | 101 ++++++++++++++ 6 files changed, 660 insertions(+) create mode 100644 drivers/net/ksz9477.c create mode 100644 drivers/net/ksz9477_i2c.c create mode 100644 drivers/net/ksz9477_reg.h create mode 100644 include/nuttx/net/ksz9477.h diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index ff289b2fb021c..5028e0db17521 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -392,6 +392,30 @@ menuconfig NET_W5500 References: W5500 Datasheet, Version 1.0.9, 2013 WIZnet Co., Ltd. +config NET_KSZ9477 + bool "Management interface for ksz9477 ethernet switch" + default n + ---help--- + Support for Microchip/Micrel KSZ9477 managed switch. To use this, + one must also select the management interface (I2C / SPI) and + call the driver's init from board initialization code or from the + ethernet driver. + +choice + prompt "Management bus for the kzs9477 switch" + default NET_KSZ9477_I2C + depends on NET_KSZ9477 + ---help--- + Select the used management interface + +config NET_KSZ9477_I2C + bool "Use I2C management interface" + +config NET_KSZ9477_SPI + bool "Use SPI management interface" + +endchoice + if NET_W5500 config NET_W5500_NINTERFACES diff --git a/drivers/net/Make.defs b/drivers/net/Make.defs index 76aa70e6b73d4..070df18e55e66 100644 --- a/drivers/net/Make.defs +++ b/drivers/net/Make.defs @@ -80,6 +80,15 @@ ifeq ($(CONFIG_ARCH_PHY_INTERRUPT),y) CSRCS += phy_notify.c endif +ifeq ($(CONFIG_NET_KSZ9477),y) + CSRCS += ksz9477.c + +ifeq ($(CONFIG_NET_KSZ9477_I2C),y) + CSRCS += ksz9477_i2c.c +endif + +endif + # Include network build support DEPPATH += --dep-path net diff --git a/drivers/net/ksz9477.c b/drivers/net/ksz9477.c new file mode 100644 index 0000000000000..4cb5cb5d2ef3c --- /dev/null +++ b/drivers/net/ksz9477.c @@ -0,0 +1,260 @@ +/**************************************************************************** + * drivers/net/ksz9477.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 "ksz9477_reg.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static uint16_t bswap16(uint16_t data) +{ + return (data << 8) | (data >> 8); +} + +static uint32_t bswap32(uint32_t data) +{ + return (data << 24) | (data >> 24) | ((data << 8) & 0xff0000) | + ((data >> 8) & 0xff00); +} + +#if 0 /* Enable when needed */ +static int ksz9477_reg_read8(uint16_t reg, uint8_t *data) +{ + int ret; + struct ksz9477_transfer_s read_msg; + read_msg.len = 3; + read_msg.reg = bswap16(reg); + ret = ksz9477_read(&read_msg); + *data = read_msg.data; + return ret; +} +#endif + +static int ksz9477_reg_read16(uint16_t reg, uint16_t *data) +{ + int ret; + struct ksz9477_transfer_s read_msg; + read_msg.len = 4; + read_msg.reg = bswap16(reg); + ret = ksz9477_read(&read_msg); + *data = bswap16(read_msg.data); + return ret; +} + +static int ksz9477_reg_read32(uint16_t reg, uint32_t *data) +{ + int ret; + struct ksz9477_transfer_s read_msg; + read_msg.len = 6; + read_msg.reg = bswap16(reg); + ret = ksz9477_read(&read_msg); + *data = bswap32(read_msg.data); + return ret; +} + +#if 0 /* Enable when needed */ +static int ksz9477_reg_write8(uint16_t reg, uint8_t data) +{ + struct ksz9477_transfer_s write_msg; + write_msg.len = 3; + write_msg.reg = bswap16(reg); + write_msg.data = data; + return ksz9477_write(&write_msg); +} +#endif + +static int ksz9477_reg_write32(uint16_t reg, uint32_t data) +{ + struct ksz9477_transfer_s write_msg; + write_msg.len = 6; + write_msg.reg = bswap16(reg); + write_msg.data = bswap32(data); + return ksz9477_write(&write_msg); +} + +#if 0 /* Enable when needed */ +static int ksz9477_reg_write16(uint16_t reg, uint16_t data) +{ + int ret; + struct ksz9477_transfer_s write_msg; + uint16_t addr = reg; + uint32_t data32; + + /* Errata: 16-bit writes to registers 0xN120-0xN13f will corrupt the + * adjacent regsters. Workaround: perform only 32-bit writes to this + * area + */ + + if ((reg & 0xfff) >= 0x120 && (reg & 0xfff) <= 0x13f) + { + /* Align write on lower 16-byte boundary */ + + addr = reg & (~1); + + /* Read the full 32-bit register */ + + ret = ksz9477_reg_read32(addr, &data32); + if (ret != OK) + { + return ret; + } + + /* Inject the data to the 32-bit write data */ + + if (reg & 1) + { + data32 = (data32 & 0xff0000ff) | ((uint32_t)data << 8); + } + else + { + data32 = (data32 & 0xffff0000) | data; + } + + write_msg.len = 6; + write_msg.data = bswap32(data32); + } + else + { + write_msg.len = 4; + write_msg.data = bswap16(data); + } + + write_msg.reg = bswap16(reg); + + return ksz9477_write(&write_msg); +} +#endif + +static int ksz9477_sgmii_read_indirect(uint32_t address, uint16_t *value, + unsigned len) +{ + int ret; + uint32_t data; + + address |= SGMII_PORT_ADDRESS_AUTO_INC_ENB; + ret = ksz9477_reg_write32(KSZ9477_SGMII_PORT_ADDRESS, address); + while (len-- && ret == OK) + { + ret = ksz9477_reg_read32(KSZ9477_SGMII_PORT_DATA, &data); + *value++ = (uint16_t)data; + } + + return ret; +} + +static int ksz9477_sgmii_write_indirect(uint32_t address, uint16_t *value, + unsigned len) +{ + int ret; + uint32_t data; + + address |= SGMII_PORT_ADDRESS_AUTO_INC_ENB; + ret = ksz9477_reg_write32(KSZ9477_SGMII_PORT_ADDRESS, address); + while (len-- && ret == OK) + { + data = *value++; + ret = ksz9477_reg_write32(KSZ9477_SGMII_PORT_DATA, data); + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ksz9477_init + * + * Description: + * Switches the ksz9477's SGMII port into PHY mode and sets the + * default settings to work directly with an external MAC + * + * Input Parameters: + * master_port: Port connected to the host MAC + * + * Returned Value: + * OK or negative error number + * + ****************************************************************************/ + +int ksz9477_init(ksz9477_port_t master_port) +{ + int ret; + uint16_t regval16; + uint32_t regval32; + + /* Read the ID registers */ + + ret = ksz9477_reg_read16(KSZ9477_ID1, ®val16); + if (ret != OK || regval16 != KSZ9477_ID) + { + nerr("Device not found, id %x, ret %d\n", regval16, ret); + return ret ? ret : -EINVAL; + } + + /* Check that the SGMII block is alive and indirect accesses work */ + + ret = ksz9477_sgmii_read_indirect(KSZ9477_SGMII_ID1, + (uint16_t *)®val32, 2); + if (ret != OK || regval32 != SGMII_PHY_ID) + { + nerr("SGMII port access failure, id %x, ret %d\n", regval32, ret); + return ret ? ret : -EINVAL; + } + + if (master_port == KSZ9477_PORT_SGMII) + { + /* Set the switch's SGMII port into "PHY" mode and enable link */ + + regval16 = (SGMII_AUTONEG_CONTROL_PCS_SGMII | + SGMII_AUTONEG_CONTROL_TC_MASTER | + SGMII_AUTONEG_CONTROL_LINK_STATUS); + ret = ksz9477_sgmii_write_indirect(KSZ9477_SGMII_AUTONEG_CONTROL, + ®val16, 1); + + /* Write to autonegotiation advertisement register activates the new + * setting. Advertise only full duplex. + */ + + regval16 = SGMII_AUTONEG_ADVERTISE_FD; + ret = ksz9477_sgmii_write_indirect(KSZ9477_SGMII_AUTONEG_ADVERTISE, + ®val16, 1); + } + + return ret; +} diff --git a/drivers/net/ksz9477_i2c.c b/drivers/net/ksz9477_i2c.c new file mode 100644 index 0000000000000..35618d826cfbc --- /dev/null +++ b/drivers/net/ksz9477_i2c.c @@ -0,0 +1,111 @@ +/**************************************************************************** + * drivers/net/ksz9477_i2c.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 "ksz9477_reg.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct i2c_master_s *g_ksz9477_i2c_bus; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void setup_i2c_transfer(struct i2c_msg_s *msg, uint8_t *data, + size_t len, bool read) +{ + msg[0].frequency = KSZ9477_I2C_SPEED; + msg[0].addr = KSZ9477_I2C_ADDRESS; + msg[0].flags = read ? I2C_M_READ : 0; + msg[0].buffer = data; + msg[0].length = len; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int ksz9477_read(struct ksz9477_transfer_s *read_msg) +{ + struct i2c_msg_s msg[2]; + + /* Set up to write the address */ + + setup_i2c_transfer(&msg[0], (uint8_t *)&read_msg->reg, + sizeof(read_msg->reg), false); + + /* Followed by the read data */ + + setup_i2c_transfer(&msg[1], (uint8_t *)&read_msg->data, + read_msg->len - sizeof(read_msg->reg), true); + + return I2C_TRANSFER(g_ksz9477_i2c_bus, msg, 2); +} + +int ksz9477_write(struct ksz9477_transfer_s *write_msg) +{ + struct i2c_msg_s msg; + + /* Set up to write the address and data */ + + setup_i2c_transfer(&msg, (uint8_t *)&write_msg->reg, + write_msg->len, false); + + return I2C_TRANSFER(g_ksz9477_i2c_bus, &msg, 1); +} + +/**************************************************************************** + * Name: ksz9477_i2c_init + * + * Description: + * Stores the configured i2c_master and calls the main init function + * + * Input Parameters: + * i2c_bus: The i2c master used as a control interface + * master_port: The switch port connected to the host MAC + * Returned Value: + * OK or negative error number + * + ****************************************************************************/ + +int ksz9477_i2c_init(struct i2c_master_s *i2c_bus, + ksz9477_port_t master_port) +{ + if (!i2c_bus) + { + return -EINVAL; + } + + g_ksz9477_i2c_bus = i2c_bus; + + /* Call the main init function */ + + return ksz9477_init(master_port); +} diff --git a/drivers/net/ksz9477_reg.h b/drivers/net/ksz9477_reg.h new file mode 100644 index 0000000000000..3423edb8ef603 --- /dev/null +++ b/drivers/net/ksz9477_reg.h @@ -0,0 +1,155 @@ +/**************************************************************************** + * drivers/net/ksz9477_reg.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 __DRIVERS_NET_KSZ9477_REG_H +#define __DRIVERS_NET_KSZ9477_REG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* These define only a subset of full register map. New registers can added + * as needed + */ + +#define KSZ9477_I2C_ADDRESS 0x5f +#define KSZ9477_I2C_SPEED I2C_SPEED_FAST + +/* Global registers */ + +#define KSZ9477_ID0 0x0 +#define KSZ9477_ID1 0x1 +#define KSZ9477_ID2 0x2 +#define KSZ9477_ID3 0x3 + +/* Port registers */ + +#define KSZ9477_PORT_REG(p,r) ((((uint16_t)(p)) << 12) | (r)) + +#define KSZ9477_PORT_DEFAULT_TAG0(p) KSZ9477_PORT_REG(p, 0x0) +#define KSZ9477_PORT_DEFAULT_TAG1(p) KSZ9477_PORT_REG(p, 0x1) + +#define KSZ9477_PHY_CONTROL(p) KSZ9477_PORT_REG(p, 0x100) +#define KSZ9477_PHY_STATUS(p) KSZ9477_PORT_REG(p, 0x102) + +/* Note! Unlike in data sheet, the indirect data register reads and + * writes must be done with 32-bit accesses and the address is + * 0x204 + */ + +#define KSZ9477_PORT_ADDRESS(p) KSZ9477_PORT_REG(p, 0x200) +#define KSZ9477_PORT_DATA(p) KSZ9477_PORT_REG(p, 0x204) + +#define KSZ9477_SGMII_PORT_ADDRESS KSZ9477_PORT_ADDRESS(7) +#define KSZ9477_SGMII_PORT_DATA KSZ9477_PORT_DATA(7) + +/* SGMII indirect registers */ + +#define KSZ9477_SGMII_CONTROL 0x1F0000 +#define KSZ9477_SGMII_STATUS 0x1F0001 +#define KSZ9477_SGMII_ID1 0x1F0002 +#define KSZ9477_SGMII_ID2 0x1F0003 +#define KSZ9477_SGMII_AUTONEG_ADVERTISE 0x1F0004 +#define KSZ9477_SGMII_LINK_PARTNER_ABILITY 0x1F0005 +#define KSZ9477_SGMII_AUTONEG_EXPANSION 0x1F0006 +#define KSZ9477_SGMII_DIGITAL_CONTROL 0x1F8000 +#define KSZ9477_SGMII_AUTONEG_CONTROL 0x1F8001 +#define KSZ9477_SGMII_AUTONEG_STATUS 0x1F8002 + +/* Register bit definitions */ + +/* KSZ9477_ID2, KSZ9477_ID1 */ + +#define KSZ9477_ID 0x9477 + +/* KSZ9477_SGMII_ID2, KSZ9477_SGMII_ID1 */ + +#define SGMII_PHY_ID 0xced07996 + +/* KSZ9477_SGMII_PORT_ADDRESS */ + +#define SGMII_PORT_ADDRESS_AUTO_INC_ENB (1 << 23) + +/* KSZ9477_SGMII_AUTONEG_ADVERTISE */ + +#define SGMII_AUTONEG_ADVERTISE_FD (1 << 5) +#define SGMII_AUTONEG_ADVERTISE_HD (1 << 5) + +/* KSZ9477_SGMII_AUTONEG_CONTROL */ + +#define SGMII_AUTONEG_CONTROL_IE (1 << 0) +#define SGMII_AUTONEG_CONTROL_PCS_SERDES (0 << 1) +#define SGMII_AUTONEG_CONTROL_PCS_SGMII (2 << 1) +#define SGMII_AUTONEG_CONTROL_TC_MASTER (1 << 3) +#define SGMII_AUTONEG_CONTROL_LINK_STATUS (1 << 4) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +struct ksz9477_transfer_s +{ + uint16_t len; + uint16_t reg; + uint32_t data; +} +__attribute__((packed)); + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +int ksz9477_init(ksz9477_port_t master_port); + +int ksz9477_read(struct ksz9477_transfer_s *read_msg); + +int ksz9477_write(struct ksz9477_transfer_s *write_msg); + +#if defined(__cplusplus) +} +#endif +#undef EXTERN + +#endif /* __ASSEMBLY__ */ +#endif /* __DRIVERS_NET_KSZ9477_REG_H */ diff --git a/include/nuttx/net/ksz9477.h b/include/nuttx/net/ksz9477.h new file mode 100644 index 0000000000000..cc37adb48a40a --- /dev/null +++ b/include/nuttx/net/ksz9477.h @@ -0,0 +1,101 @@ +/**************************************************************************** + * include/nuttx/net/ksz9477.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 __INCLUDE_NUTTX_NET_KSZ9477_H +#define __INCLUDE_NUTTX_NET_KSZ9477_H + +#ifdef CONFIG_NET_KSZ9477 + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +typedef enum +{ + KSZ9477_PORT_NONE = -1, + KSZ9477_PORT_GLOBAL = 0, + KSZ9477_PORT_PHY1 = 1, + KSZ9477_PORT_PHY2 = 2, + KSZ9477_PORT_PHY3 = 3, + KSZ9477_PORT_PHY4 = 4, + KSZ9477_PORT_PHY5 = 5, + KSZ9477_PORT_RMII = 6, + KSZ9477_PORT_SGMII = 7, +} ksz9477_port_t; + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: ksz9477_i2c_init + * + * Description: + * Switches the ksz9477's SGMII port into PHY mode and sets the + * default settings to work directly with an external MAC + * + * Input Parameters: + * i2c_bus: Management i2c bus + * master_port: The port of the switch connected to host MAC + * + * Returned Value: + * OK or ERROR + * + ****************************************************************************/ + +#ifdef CONFIG_NET_KSZ9477_I2C +int ksz9477_i2c_init(struct i2c_master_s *i2c_bus, + ksz9477_port_t master_port); +#else +# error Only I2c interface currently supported +#endif + +#if defined(__cplusplus) +} +#endif +#undef EXTERN + +#endif /* __ASSEMBLY__ */ +#endif /* CONFIG_NET_KSZ9477 */ +#endif /* __INCLUDE_NUTTX_NET_KSZ9477_H */ From 537e3ffa1d1daa6745b31e38b5169158873ed4af Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Thu, 31 Aug 2023 14:38:50 +0300 Subject: [PATCH 080/138] arch/risc-v/src/mpfs: Add ksz9477 initialization This adds initialization of the ksz9477 switch when used instead of a PHY, directly connected to SGMII Signed-off-by: Jukka Laitinen --- arch/risc-v/src/mpfs/Kconfig | 31 +++++++++++ arch/risc-v/src/mpfs/mpfs_ethernet.c | 78 ++++++++++++++++++++++++---- 2 files changed, 100 insertions(+), 9 deletions(-) diff --git a/arch/risc-v/src/mpfs/Kconfig b/arch/risc-v/src/mpfs/Kconfig index a13d98ad3a86d..75b2e5dc3a4d9 100644 --- a/arch/risc-v/src/mpfs/Kconfig +++ b/arch/risc-v/src/mpfs/Kconfig @@ -747,6 +747,8 @@ config MPFS_MAC_NO_BROADCAST config MPFS_MAC_AUTONEG bool "Use autonegotiation" + depends on !MPFS_ETH0_PHY_KSZ9477 + depends on !MPFS_ETH1_PHY_KSZ9477 default y ---help--- Use PHY autonegotiation to determine speed and mode @@ -765,6 +767,34 @@ config MPFS_PHYINIT ---help--- call mpfs_phy_boardinitialize() on init +config MPFS_ETH0_PHY_KSZ9477 + bool "Use ksz9477 switch as an SGMII PHY for ETH0" + default n + select NET_KSZ9477 + ---help--- + Select to use ksz9477 connected to SGMII + +config MPFS_ETH1_PHY_KSZ9477 + bool "Use ksz9477 switch as an SGMII PHY for ETH1" + default n + select NET_KSZ9477 + ---help--- + Select to use ksz9477 connected to SGMII + +config MPFS_ETH0_PHY_KSZ9477_I2C_BUS + int "Management I2C bus number for ksz9477 switch" + depends on MPFS_ETH0_PHY_KSZ9477 + default 5 + ---help--- + The i2c port number for switch management + +config MPFS_ETH1_PHY_KSZ9477_I2C_BUS + int "Management I2C bus number for ksz9477 switch" + depends on MPFS_ETH1_PHY_KSZ9477 + default 5 + ---help--- + The i2c port number for switch management + if !MPFS_MAC_AUTONEG config MPFS_MAC_ETHFD @@ -776,6 +806,7 @@ config MPFS_MAC_ETHFD choice prompt "MAC Speed" + default MPFS_MAC_ETH1000MBPS if MPFS_ETH0_PHY_KSZ9477 || MPFS_ETH1_PHY_KSZ9477 default MPFS_MAC_ETH100MBPS ---help--- If autonegotiation is not used, then you must select the fixed speed diff --git a/arch/risc-v/src/mpfs/mpfs_ethernet.c b/arch/risc-v/src/mpfs/mpfs_ethernet.c index c72764ebb8c59..8fcc8f6129a3d 100644 --- a/arch/risc-v/src/mpfs/mpfs_ethernet.c +++ b/arch/risc-v/src/mpfs/mpfs_ethernet.c @@ -50,10 +50,31 @@ # include #endif +#include + #include "riscv_internal.h" #include "mpfs_memorymap.h" #include "mpfs_ethernet.h" #include "mpfs_dsn.h" +#include "mpfs_i2c.h" + +#if defined(CONFIG_MPFS_ETH0_PHY_KSZ9477) ||\ + defined(CONFIG_MPFS_ETH1_PHY_KSZ9477) +# if !defined(CONFIG_MPFS_MAC_SGMII) +# error Using KSZ9477 as a PHY requires CONFIG_MPFS_MAC_SGMII to be set +# endif + +# define ETH_HAS_KSZ_SWITCH + +# ifdef CONFIG_MPFS_ETH0_PHY_KSZ9477 +# define ETH_PHY_KSZ9477_I2C_BUS CONFIG_MPFS_ETH0_PHY_KSZ9477_I2C_BUS +# else +# define ETH_PHY_KSZ9477_I2C_BUS CONFIG_MPFS_ETH1_PHY_KSZ9477_I2C_BUS +# endif + +#else +# define ETH_HAS_MDIO_PHY +#endif #if defined(CONFIG_NET) && defined(CONFIG_MPFS_ETHMAC) @@ -90,7 +111,7 @@ # endif #endif -#ifndef CONFIG_MPFS_PHYADDR +#if defined(ETH_HAS_MDIO_PHY) && !defined(CONFIG_MPFS_PHYADDR) # error "CONFIG_MPFS_PHYADDR must be defined in the NuttX configuration" #endif @@ -253,7 +274,9 @@ struct mpfs_ethmac_s irq_t mac_q_int[MPFS_MAC_QUEUE_COUNT]; /* irq numbers */ uint8_t ifup : 1; /* true:ifup false:ifdown */ uint8_t intf; /* Ethernet interface number */ +#ifdef ETH_HAS_MDIO_PHY uint8_t phyaddr; /* PHY address */ +#endif 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 */ @@ -338,10 +361,13 @@ static int mpfs_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg); /* PHY Initialization */ +static int mpfs_phyinit(struct mpfs_ethmac_s *priv); + +#ifdef ETH_HAS_MDIO_PHY + static void mpfs_enablemdio(struct mpfs_ethmac_s *priv); static void mpfs_disablemdio(struct mpfs_ethmac_s *priv); static int mpfs_phyreset(struct mpfs_ethmac_s *priv); -static int mpfs_phyinit(struct mpfs_ethmac_s *priv); static int mpfs_phyread(struct mpfs_ethmac_s *priv, uint8_t phyaddr, uint8_t regaddr, uint16_t *phyval); static int mpfs_phywrite(struct mpfs_ethmac_s *priv, uint8_t phyaddr, @@ -350,16 +376,21 @@ static int mpfs_phywait(struct mpfs_ethmac_s *priv); static int mpfs_phyfind(struct mpfs_ethmac_s *priv, uint8_t *phyaddr); #ifdef CONFIG_MPFS_MAC_AUTONEG static int mpfs_autonegotiate(struct mpfs_ethmac_s *priv); -#else -static void mpfs_linkspeed(struct mpfs_ethmac_s *priv); #endif -#if defined(CONFIG_DEBUG_NET) && defined(CONFIG_DEBUG_INFO) +#endif /* ETH_HAS_MDIO_PHY */ + +#if defined(CONFIG_DEBUG_NET) && defined(CONFIG_DEBUG_INFO) && \ + defined(ETH_HAS_MDIO_PHY) static void mpfs_phydump(struct mpfs_ethmac_s *priv); #else # define mpfs_phydump(priv) #endif +#ifndef CONFIG_MPFS_MAC_AUTONEG +static void mpfs_linkspeed(struct mpfs_ethmac_s *priv); +#endif + /* MAC/DMA Initialization */ static void mpfs_txreset(struct mpfs_ethmac_s *priv); @@ -1873,6 +1904,8 @@ static int mpfs_rmmac(struct net_driver_s *dev, const uint8_t *mac) } #endif +#ifdef ETH_HAS_MDIO_PHY + /**************************************************************************** * Function: mpfs_enablemdio * @@ -2503,6 +2536,8 @@ static int mpfs_autonegotiate(struct mpfs_ethmac_s *priv) } #endif +#endif /* ETH_HAS_MDIO_PHY */ + /**************************************************************************** * Function: mpfs_linkspeed * @@ -2518,7 +2553,7 @@ static int mpfs_autonegotiate(struct mpfs_ethmac_s *priv) * ****************************************************************************/ -#ifndef CONFIG_MPFS_MAC_AUTONEG +#if !defined(CONFIG_MPFS_MAC_AUTONEG) || !defined(ETH_HAS_MDIO_PHY) static void mpfs_linkspeed(struct mpfs_ethmac_s *priv) { uint32_t regval; @@ -2594,7 +2629,7 @@ static void mpfs_linkspeed(struct mpfs_ethmac_s *priv) #ifdef CONFIG_NETDEV_IOCTL static int mpfs_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) { -#ifdef CONFIG_NETDEV_PHY_IOCTL +#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(ETH_HAS_MDIO_PHY) struct mpfs_ethmac_s *priv = (struct mpfs_ethmac_s *)dev->d_private; #endif int ret; @@ -2602,6 +2637,7 @@ static int mpfs_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) switch (cmd) { #ifdef CONFIG_NETDEV_PHY_IOCTL +#ifdef ETH_HAS_MDIO_PHY #ifdef CONFIG_ARCH_PHY_INTERRUPT case SIOCMIINOTIFY: /* Set up for PHY event notifications */ { @@ -2665,6 +2701,7 @@ static int mpfs_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg) mpfs_disablemdio(priv); } break; +#endif /* ETH_HAS_MDIO_PHY */ #endif /* CONFIG_NETDEV_PHY_IOCTL */ default: @@ -3239,6 +3276,8 @@ static int mpfs_macenable(struct mpfs_ethmac_s *priv) * ****************************************************************************/ +#ifdef ETH_HAS_MDIO_PHY + static void mpfs_mdcclock(struct mpfs_ethmac_s *priv) { uint32_t ncfgr; @@ -3293,6 +3332,8 @@ static void mpfs_mdcclock(struct mpfs_ethmac_s *priv) mac_putreg(priv, NETWORK_CONTROL, ncr); } +#endif + /**************************************************************************** * Function: mpfs_phyinit * @@ -3309,7 +3350,9 @@ static void mpfs_mdcclock(struct mpfs_ethmac_s *priv) static int mpfs_phyinit(struct mpfs_ethmac_s *priv) { - int ret; + int ret = -EINVAL; + +#ifdef ETH_HAS_MDIO_PHY /* Configure PHY clocking */ @@ -3328,7 +3371,20 @@ static int mpfs_phyinit(struct mpfs_ethmac_s *priv) /* We have a PHY address. Reset the PHY */ mpfs_phyreset(priv); - return OK; + +#elif defined(ETH_HAS_KSZ_SWITCH) + struct i2c_master_s *bus; + + bus = mpfs_i2cbus_initialize(ETH_PHY_KSZ9477_I2C_BUS); + + if (bus) + { + ret = ksz9477_i2c_init(bus, KSZ9477_PORT_SGMII); + } + +#endif + + return ret; } /**************************************************************************** @@ -3347,6 +3403,8 @@ static int mpfs_phyinit(struct mpfs_ethmac_s *priv) * ****************************************************************************/ +#ifdef ETH_HAS_MDIO_PHY + static int mpfs_phyreset(struct mpfs_ethmac_s *priv) { uint16_t mcr; @@ -3416,6 +3474,8 @@ static int mpfs_phyreset(struct mpfs_ethmac_s *priv) return ret; } +#endif + /**************************************************************************** * Function: mpfs_ethconfig * From 3472e29d165e54342c63971e9b4805c61e1653f3 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Mon, 11 Sep 2023 09:21:31 +0300 Subject: [PATCH 081/138] arch/risc-v/src/mpfs/mpfs_i2c.c: Clean up using priv->status and STOP interrupts - There are occasional extra STOPs being sent due to an IP bug when using an FPGA based I2C. Add a flag "inflight" to mask out extra STOP interrupts when using the FPGA based implementation - There are no MPFS_I2C_ST_STOP_SENT irq's "initally". It is just already either success or still in progress Signed-off-by: Jukka Laitinen --- arch/risc-v/src/mpfs/mpfs_i2c.c | 70 +++++++++++++++++---------------- 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_i2c.c b/arch/risc-v/src/mpfs/mpfs_i2c.c index 0f760820c0a3e..2fb7a538117bb 100644 --- a/arch/risc-v/src/mpfs/mpfs_i2c.c +++ b/arch/risc-v/src/mpfs/mpfs_i2c.c @@ -163,6 +163,7 @@ struct mpfs_i2c_priv_s bool initialized; /* Bus initialization status */ bool fpga; /* FPGA i2c */ + bool inflight; /* Transfer ongoing */ }; #ifndef CONFIG_MPFS_COREI2C @@ -447,6 +448,8 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg) { priv->tx_idx = 0u; } + + priv->inflight = true; break; case MPFS_I2C_ST_LOST_ARB: @@ -479,7 +482,7 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg) clear_irq = 0u; modifyreg32(MPFS_I2C_CTRL, 0, MPFS_I2C_CTRL_STA_MASK); - /* Jump to the next message */ + /* Jump to the next message */ priv->msgid++; } @@ -498,7 +501,7 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg) clear_irq = 0u; modifyreg32(MPFS_I2C_CTRL, 0, MPFS_I2C_CTRL_STA_MASK); - /* Jump to the next message */ + /* Jump to the next message */ priv->msgid++; } @@ -566,12 +569,33 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg) break; case MPFS_I2C_ST_IDLE: - case MPFS_I2C_ST_STOP_SENT: /* No activity, bus idle */ break; + case MPFS_I2C_ST_STOP_SENT: + + /* FPGA driver terminates all transactions with STOP sent irq + * if there has been no errors, the transfer succeeded. + * Due to the IP bug that extra data & STOPs can be sent after + * the actual transaction, filter out any extra stops with + * priv->inflight flag + */ + + if (priv->inflight) + { + if (priv->status == MPFS_I2C_IN_PROGRESS) + { + priv->status = MPFS_I2C_SUCCESS; + } + + nxsem_post(&priv->sem_isr); + } + + priv->inflight = false; + break; + case MPFS_I2C_ST_RESET_ACTIVATED: case MPFS_I2C_ST_BUS_ERROR: /* Bus errors */ default: @@ -586,31 +610,12 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg) break; } - if (priv->fpga) - { - /* FPGA driver terminates all transactions with STOP sent irq */ + if (!priv->fpga && priv->status != MPFS_I2C_IN_PROGRESS) + { + /* MSS I2C has no STOP sent irq */ - if (status == MPFS_I2C_ST_STOP_SENT) - { - /* Don't post on a new request, STOPs possible initially */ - - if (!((priv->rx_idx == 0 && priv->rx_size > 0) || - (priv->tx_idx == 0 && priv->tx_size > 0))) - { - nxsem_post(&priv->sem_isr); - } - else if (priv->status == MPFS_I2C_FAILED) - { - nxsem_post(&priv->sem_isr); - } - } - } - else if (priv->status != MPFS_I2C_IN_PROGRESS) - { - /* MSS I2C has no STOP SENT irq */ - - nxsem_post(&priv->sem_isr); - } + nxsem_post(&priv->sem_isr); + } if (clear_irq) { @@ -642,7 +647,7 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg) static void mpfs_i2c_sendstart(struct mpfs_i2c_priv_s *priv) { up_enable_irq(priv->plic_irq); - modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_STA_MASK, MPFS_I2C_CTRL_STA_MASK); + modifyreg32(MPFS_I2C_CTRL, 0, MPFS_I2C_CTRL_STA_MASK); } static int mpfs_i2c_transfer(struct i2c_master_s *dev, @@ -661,11 +666,6 @@ static int mpfs_i2c_transfer(struct i2c_master_s *dev, return ret; } - if (priv->status != MPFS_I2C_SUCCESS) - { - priv->status = MPFS_I2C_SUCCESS; - } - priv->msgv = msgs; for (int i = 0; i < count; i++) @@ -728,6 +728,7 @@ static int mpfs_i2c_transfer(struct i2c_master_s *dev, if (mpfs_i2c_sem_waitdone(priv) < 0) { i2cinfo("Message %" PRIu8 " timed out.\n", priv->msgid); + priv->inflight = false; ret = -ETIMEDOUT; break; } @@ -741,7 +742,6 @@ static int mpfs_i2c_transfer(struct i2c_master_s *dev, } else { - priv->status = MPFS_I2C_SUCCESS; ret = OK; } } @@ -784,6 +784,8 @@ static int mpfs_i2c_reset(struct i2c_master_s *dev) up_disable_irq(priv->plic_irq); + priv->inflight = false; + priv->status = MPFS_I2C_SUCCESS; priv->initialized = false; ret = mpfs_i2c_init(priv); From 393f37e34b374fb0ea5cc7e2735f6841c940ed4e Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Wed, 30 Aug 2023 16:13:40 +0300 Subject: [PATCH 082/138] riscv/riscv_pmp.c: Improve NAPOT area validity checks Check that the base address and region size are properly aligned with relation to each other. With NAPOT encoding the area base and size are not arbitrary, as when the size increases the amount of bits available for encoding the base address decreases. --- arch/risc-v/src/common/riscv_pmp.c | 51 +++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/arch/risc-v/src/common/riscv_pmp.c b/arch/risc-v/src/common/riscv_pmp.c index 9a19c94a39550..bf0b19a210f9c 100644 --- a/arch/risc-v/src/common/riscv_pmp.c +++ b/arch/risc-v/src/common/riscv_pmp.c @@ -100,6 +100,32 @@ typedef struct pmp_entry_s pmp_entry_t; * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: log2ceil + * + * Description: + * Calculate the up-rounded power-of-two for input. + * + * Input Parameters: + * size - The size of the PMP region. + * + * Returned Value: + * Power-of-two for argument, rounded up. + * + ****************************************************************************/ + +static uintptr_t log2ceil(uintptr_t size) +{ + uintptr_t pot = 0; + + for (size = size - 1; size > 1; size >>= 1) + { + pot++; + } + + return pot; +} + /**************************************************************************** * Name: pmp_check_addrmatch_type * @@ -160,7 +186,8 @@ static bool pmp_check_addrmatch_type(uintptr_t type) * ****************************************************************************/ -static bool pmp_check_region_attrs(uintptr_t base, uintptr_t size) +static bool pmp_check_region_attrs(uintptr_t base, uintptr_t size, + uintptr_t type) { /* Check that the size is not too small */ @@ -183,7 +210,23 @@ static bool pmp_check_region_attrs(uintptr_t base, uintptr_t size) return false; } - return OK; + /* Perform additional checks on base and size for NAPOT area */ + + if (type == PMPCFG_A_NAPOT) + { + /* Get the power-of-two for size, rounded up */ + + uintptr_t pot = log2ceil(size); + + if ((base & ((UINT64_C(1) << pot) - 1)) != 0) + { + /* The start address is not properly aligned with size */ + + return false; + } + } + + return true; } /**************************************************************************** @@ -455,7 +498,7 @@ int riscv_config_pmp_region(uintptr_t region, uintptr_t attr, /* Check the region attributes */ - if (pmp_check_region_attrs(base, size)) + if (pmp_check_region_attrs(base, size, type) == false) { return -EINVAL; } @@ -463,7 +506,7 @@ int riscv_config_pmp_region(uintptr_t region, uintptr_t attr, /* Calculate new base address from type */ addr = base >> 2; - if (PMPCFG_A_NAPOT == (attr & PMPCFG_A_MASK)) + if (type == PMPCFG_A_NAPOT) { addr |= (size - 1) >> 3; } From 3b6acfaf102ad309f4eebfe27ec3d13ac42e3b19 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Mon, 28 Aug 2023 12:05:03 +0300 Subject: [PATCH 083/138] mpfs/mpfs_i2c.c: Replace 1 second timeout with Time-on-Air based timeout Calculate how long an I2C transation will take in microseconds, and use this as the timeout for mpfs_i2c_sem_waitdone. The reason for doing this is not to keep an i2c bus reserved for the full 1 second timeout, if e.g. a sensor is not on the bus / is faulty and non-responsive. Reading the other sensors will be blocked for a relatively long time (1 second) in this case. This fixes such behavior. --- arch/risc-v/src/mpfs/mpfs_i2c.c | 42 ++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/arch/risc-v/src/mpfs/mpfs_i2c.c b/arch/risc-v/src/mpfs/mpfs_i2c.c index 2fb7a538117bb..23843a0981312 100644 --- a/arch/risc-v/src/mpfs/mpfs_i2c.c +++ b/arch/risc-v/src/mpfs/mpfs_i2c.c @@ -68,6 +68,11 @@ #define MPFS_I2C_DATA (priv->hw_base + MPFS_I2C_DATA_OFFSET) #define MPFS_I2C_ADDR (priv->hw_base + MPFS_I2C_SLAVE0ADR_OFFSET) +/* Gives TTOA in microseconds, ~4.8% bias, +1 rounds up */ + +#define I2C_TTOA_US(n, f) ((((n) << 20) / (f)) + 1) +#define I2C_TTOA_MARGIN 20 + /**************************************************************************** * Private Types ****************************************************************************/ @@ -143,6 +148,7 @@ struct mpfs_i2c_priv_s uint32_t frequency; /* Current I2C frequency */ uint8_t msgid; /* Current message ID */ + uint8_t msgc; /* Message count */ ssize_t bytes; /* Processed data bytes */ uint8_t ser_address; /* Own i2c address */ @@ -268,6 +274,7 @@ static struct mpfs_i2c_priv_s static int mpfs_i2c_setfrequency(struct mpfs_i2c_priv_s *priv, uint32_t frequency); +static uint32_t mpfs_i2c_timeout(int msgc, struct i2c_msg_s *msgv); /**************************************************************************** * Private Functions @@ -400,7 +407,8 @@ static void mpfs_i2c_deinit(struct mpfs_i2c_priv_s *priv) static int mpfs_i2c_sem_waitdone(struct mpfs_i2c_priv_s *priv) { - return nxsem_tickwait_uninterruptible(&priv->sem_isr, SEC2TICK(1)); + uint32_t timeout = mpfs_i2c_timeout(priv->msgc, priv->msgv); + return nxsem_tickwait_uninterruptible(&priv->sem_isr, USEC2TICK(timeout)); } /**************************************************************************** @@ -667,6 +675,7 @@ static int mpfs_i2c_transfer(struct i2c_master_s *dev, } priv->msgv = msgs; + priv->msgc = count; for (int i = 0; i < count; i++) { @@ -886,6 +895,37 @@ static int mpfs_i2c_setfrequency(struct mpfs_i2c_priv_s *priv, return OK; } +/**************************************************************************** + * Name: mpfs_i2c_timeout + * + * Description: + * Calculate the time a full I2C transaction (message vector) will take + * to transmit, used for bus timeout. + * + * Input Parameters: + * msgc - Message count in message vector + * msgv - Message vector containing the messages to send + * + * Returned Value: + * I2C transaction timeout in microseconds (with some margin) + * + ****************************************************************************/ + +static uint32_t mpfs_i2c_timeout(int msgc, struct i2c_msg_s *msgv) +{ + uint32_t usec = 0; + int i; + + for (i = 0; i < msgc; i++) + { + /* start + stop + address is 12 bits, each byte is 9 bits */ + + usec += I2C_TTOA_US(12 + msgv[i].length * 9, msgv[i].frequency); + } + + return usec + I2C_TTOA_MARGIN; +} + /**************************************************************************** * Public Functions ****************************************************************************/ From cd343a7bad6c1e753df817f93c1f7d4b5e8f58c4 Mon Sep 17 00:00:00 2001 From: SPRESENSE <41312067+SPRESENSE@users.noreply.github.com> Date: Thu, 7 Sep 2023 11:50:14 +0900 Subject: [PATCH 084/138] libs/libc: Fix a fatal bug in fread Fix a bug the destination buffer is not updated. It is caused by the following commit. commit 5d8d5bfd73c97610626dccbe40e74e007b2dcc9f --- libs/libc/stdio/lib_libfread.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/libc/stdio/lib_libfread.c b/libs/libc/stdio/lib_libfread.c index 1633b3ad9c42f..15282f3ea631d 100644 --- a/libs/libc/stdio/lib_libfread.c +++ b/libs/libc/stdio/lib_libfread.c @@ -141,6 +141,7 @@ ssize_t lib_fread(FAR void *ptr, size_t count, FAR FILE *stream) remaining -= gulp_size; stream->fs_bufpos += gulp_size; + dest += gulp_size; } /* The buffer is empty OR we have already supplied the number From 364a80a0acd46ca3117b3d7cd68536f874427e5c Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Wed, 13 Sep 2023 13:12:20 +0300 Subject: [PATCH 085/138] stdio/lib_libfread: Fix buffer overflow issue If the gulp size in the stdio buffer the remaining user buffer size it will: - Corrupt memory in dest (user memory) and - Keep corrupting KERNEL memory via the stdio character buffer until the whole system crashes, as the 'remaining' count underflows This patch fixes this behavior. --- libs/libc/stdio/lib_libfread.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/libc/stdio/lib_libfread.c b/libs/libc/stdio/lib_libfread.c index 15282f3ea631d..a6aa85fc92c48 100644 --- a/libs/libc/stdio/lib_libfread.c +++ b/libs/libc/stdio/lib_libfread.c @@ -130,11 +130,11 @@ ssize_t lib_fread(FAR void *ptr, size_t count, FAR FILE *stream) if (gulp_size > 0) { - if (gulp_size > count) + if (gulp_size > remaining) { /* Clip the gulp size to the requested byte count */ - gulp_size = count; + gulp_size = remaining; } memcpy(dest, stream->fs_bufpos, gulp_size); From 409359897e552c71f037579b1abb8a46e09af3cd Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Thu, 14 Sep 2023 16:49:54 +0300 Subject: [PATCH 086/138] binfmt/binfmt_execmodule: Copy filename if CONFIG_BUILD_KERNEL and argv=NULL The 'filename' parameter comes from user space and cannot be accessed after calling ret = addrenv_select(binp->addrenv, &binp->oldenv); as it changes the address environment and 'filename' points to who knows where. In this case, calling nxtask_init(filename...) will cause a crash. Solve this by making a local copy before changing address environment IF argv = NULL. Why ? Because argv[0] contains the process name in this case and the argument vector is already copied into kernel memory, thus passing argv[0] to nxtask_init(argv[0]...) is safe. --- binfmt/binfmt_execmodule.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/binfmt/binfmt_execmodule.c b/binfmt/binfmt_execmodule.c index b660e3eef26bc..92fe1f6480bdc 100644 --- a/binfmt/binfmt_execmodule.c +++ b/binfmt/binfmt_execmodule.c @@ -122,6 +122,7 @@ int exec_module(FAR struct binary_s *binp, #if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL) FAR struct arch_addrenv_s *addrenv = &binp->addrenv->addrenv; FAR void *vheap; + char name[CONFIG_PATH_MAX]; #endif FAR void *stackaddr = NULL; pid_t pid; @@ -166,6 +167,14 @@ int exec_module(FAR struct binary_s *binp, } #if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL) + /* If there is no argument vector, the process name must be copied here */ + + if (argv == NULL) + { + strlcpy(name, filename, CONFIG_PATH_MAX); + filename = name; + } + /* Instantiate the address environment containing the user heap */ ret = addrenv_select(binp->addrenv, &binp->oldenv); From 65cf286c4e17d20c0e5998dc17316f6ddc17abf5 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Fri, 15 Sep 2023 12:15:54 +0300 Subject: [PATCH 087/138] risc-v/mpfs: Add DMA buffer allocator for eMMC access The MPFS eMMC DMA has some requirements that are only fulfilled by enabling separate DMA access buffers (FAT DMA buffers) and by forcing indirect access to the media via FAT_FORCE_INDIRECT. Why? Direct access to user buffers violates two things: - Buffer alignment is not ensured - Buffers are user memory (problematic in BUILD_KERNEL) --- arch/risc-v/src/mpfs/Kconfig | 3 + arch/risc-v/src/mpfs/Make.defs | 4 ++ arch/risc-v/src/mpfs/mpfs_dma_alloc.c | 94 +++++++++++++++++++++++++++ arch/risc-v/src/mpfs/mpfs_dma_alloc.h | 39 +++++++++++ 4 files changed, 140 insertions(+) create mode 100644 arch/risc-v/src/mpfs/mpfs_dma_alloc.c create mode 100644 arch/risc-v/src/mpfs/mpfs_dma_alloc.h diff --git a/arch/risc-v/src/mpfs/Kconfig b/arch/risc-v/src/mpfs/Kconfig index 75b2e5dc3a4d9..59d28920f5808 100644 --- a/arch/risc-v/src/mpfs/Kconfig +++ b/arch/risc-v/src/mpfs/Kconfig @@ -391,6 +391,9 @@ config MPFS_EMMCSD select ARCH_HAVE_SDIO select SDIO_BLOCKSETUP select SDIO_DMA + select FAT_DMAMEMORY + select FAT_FORCE_INDIRECT + select GRAN default n ---help--- Selects the MPFS eMMCSD driver. diff --git a/arch/risc-v/src/mpfs/Make.defs b/arch/risc-v/src/mpfs/Make.defs index 2692647db7a59..925e4467619a8 100644 --- a/arch/risc-v/src/mpfs/Make.defs +++ b/arch/risc-v/src/mpfs/Make.defs @@ -62,6 +62,10 @@ ifeq ($(CONFIG_MPFS_EMMCSD),y) CHIP_CSRCS += mpfs_emmcsd.c endif +ifeq ($(CONFIG_FAT_DMAMEMORY),y) +CHIP_CSRCS += mpfs_dma_alloc.c +endif + ifeq ($(CONFIG_MPFS_COREMMC),y) CHIP_CSRCS += mpfs_coremmc.c endif diff --git a/arch/risc-v/src/mpfs/mpfs_dma_alloc.c b/arch/risc-v/src/mpfs/mpfs_dma_alloc.c new file mode 100644 index 0000000000000..3dbfcd9863a36 --- /dev/null +++ b/arch/risc-v/src/mpfs/mpfs_dma_alloc.c @@ -0,0 +1,94 @@ +/**************************************************************************** + * arch/risc-v/src/mpfs/mpfs_dma_alloc.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 + +#if defined(CONFIG_FAT_DMAMEMORY) && defined(CONFIG_GRAN) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define MPFS_DMA_ALLOC_POOL_SIZE (8*512) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static GRAN_HANDLE dma_allocator; + +/* The DMA heap size constrains the total number of things that can be + * ready to do DMA at a time. + * + * For example, FAT DMA depends on one sector-sized buffer per filesystem + * plus one sector-sized buffer per file. + * + * We use a fundamental alignment / granule size of 64B; it fulfills the + * requirement for any DMA engine. + */ + +static uint8_t g_dma_heap[MPFS_DMA_ALLOC_POOL_SIZE] aligned_data(64); + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mpfs_dma_alloc + * + * Description: + * All boards may optionally provide this API to instantiate a pool of + * memory for uses with FAST FS DMA operations. + * + ****************************************************************************/ + +int mpfs_dma_alloc_init(void) +{ + /* Allocate 128B granules with 64B alignment */ + + dma_allocator = gran_initialize(g_dma_heap, sizeof(g_dma_heap), 7, 6); + + if (dma_allocator == NULL) + { + return -ENOMEM; + } + + return OK; +} + +void *fat_dma_alloc(size_t size) +{ + return gran_alloc(dma_allocator, size); +} + +void fat_dma_free(void *memory, size_t size) +{ + gran_free(dma_allocator, memory, size); +} + +#endif /* CONFIG_FAT_DMAMEMORY && CONFIG_GRAN */ diff --git a/arch/risc-v/src/mpfs/mpfs_dma_alloc.h b/arch/risc-v/src/mpfs/mpfs_dma_alloc.h new file mode 100644 index 0000000000000..2ed3198b6459c --- /dev/null +++ b/arch/risc-v/src/mpfs/mpfs_dma_alloc.h @@ -0,0 +1,39 @@ +/**************************************************************************** + * arch/risc-v/src/mpfs/mpfs_dma_alloc.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_RISC_V_SRC_MPFS_MPFS_DMA_ALLOC_H +#define __ARCH_RISC_V_SRC_MPFS_MPFS_DMA_ALLOC_H + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: mpfs_dma_alloc + * + * Description: + * All boards may optionally provide this API to instantiate a pool of + * memory for uses with FAST FS DMA operations. + * + ****************************************************************************/ + +int mpfs_dma_alloc_init(void); + +#endif /* __ARCH_RISC_V_SRC_MPFS_MPFS_DMA_ALLOC_H */ From 1fe72b8fe44bac32f525447743ceb75e8e1f47cd Mon Sep 17 00:00:00 2001 From: Petro Karashchenko Date: Tue, 29 Aug 2023 14:52:59 +0300 Subject: [PATCH 088/138] tools/ci: ensure removing python and openssl related commands Signed-off-by: Petro Karashchenko --- tools/ci/cibuild.sh | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/ci/cibuild.sh b/tools/ci/cibuild.sh index e96b9f45b39c0..7210a363f75aa 100755 --- a/tools/ci/cibuild.sh +++ b/tools/ci/cibuild.sh @@ -448,7 +448,6 @@ function u-boot-tools { if ! type mkimage &> /dev/null; then case ${os} in Darwin) - rm -f /usr/local/bin/openssl brew install u-boot-tools ;; Linux) @@ -563,6 +562,14 @@ case ${os} in install="arm-gcc-toolchain arm64-gcc-toolchain avr-gcc-toolchain binutils bloaty elf-toolchain gen-romfs gperf kconfig-frontends mips-gcc-toolchain python-tools riscv-gcc-toolchain rust xtensa-esp32-gcc-toolchain u-boot-tools wasi-sdk c-cache" mkdir -p "${tools}"/homebrew export HOMEBREW_CACHE=${tools}/homebrew + # https://github.com/apache/arrow/issues/15025 + rm -f /usr/local/bin/2to3* || : + rm -f /usr/local/bin/idle3* || : + rm -f /usr/local/bin/pydoc3* || : + rm -f /usr/local/bin/python3* || : + rm -f /usr/local/bin/python3-config || : + # same for openssl + rm -f /usr/local/bin/openssl || : ;; Linux) install="arm-clang-toolchain arm-gcc-toolchain arm64-gcc-toolchain avr-gcc-toolchain binutils bloaty clang-tidy gen-romfs gperf kconfig-frontends mips-gcc-toolchain python-tools riscv-gcc-toolchain rust rx-gcc-toolchain sparc-gcc-toolchain xtensa-esp32-gcc-toolchain u-boot-tools wasi-sdk c-cache" From 67a45e7c7bb9628ff19c11ded2567d5939c2b932 Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Wed, 13 Sep 2023 08:31:27 +0800 Subject: [PATCH 089/138] tools/ci: Unify the version print: command xxx --version Signed-off-by: Xiang Xiao --- tools/ci/cibuild.sh | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tools/ci/cibuild.sh b/tools/ci/cibuild.sh index 7210a363f75aa..5e02fc160e584 100755 --- a/tools/ci/cibuild.sh +++ b/tools/ci/cibuild.sh @@ -57,7 +57,7 @@ function arm-clang-toolchain { rm LLVMEmbeddedToolchainForArm-14.0.0-${flavor}.tar.gz fi - clang --version + command clang --version } function arm-gcc-toolchain { @@ -81,7 +81,7 @@ function arm-gcc-toolchain { rm arm-gnu-toolchain-12.3.rel1${flavor}-x86_64-arm-none-eabi.tar fi - arm-none-eabi-gcc --version + command arm-none-eabi-gcc --version } function arm64-gcc-toolchain { @@ -105,7 +105,7 @@ function arm64-gcc-toolchain { rm gcc-arm-11.2-2022.02-${flavor}-aarch64-none-elf.tar fi - aarch64-none-elf-gcc --version + command aarch64-none-elf-gcc --version } function avr-gcc-toolchain { @@ -121,7 +121,7 @@ function avr-gcc-toolchain { esac fi - avr-gcc --version + command avr-gcc --version } function binutils { @@ -140,7 +140,7 @@ function binutils { esac fi - objcopy --version + command objcopy --version } function bloaty { @@ -180,7 +180,7 @@ function c-cache { esac fi - ccache --version + command ccache --version } function clang-tidy { @@ -204,7 +204,7 @@ function elf-toolchain { esac fi - x86_64-elf-gcc --version + command x86_64-elf-gcc --version } function gen-romfs { @@ -264,11 +264,11 @@ function mips-gcc-toolchain { case ${os} in Darwin) add_path "${tools}"/pinguino-compilers/macosx/p32/bin - mips-elf-gcc --version + command mips-elf-gcc --version ;; Linux) add_path "${tools}"/pinguino-compilers/linux64/p32/bin - p32-gcc --version + command p32-gcc --version ;; esac } @@ -327,7 +327,7 @@ function riscv-gcc-toolchain { rm riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-${flavor}.tar.gz fi - riscv64-unknown-elf-gcc --version + command riscv64-unknown-elf-gcc --version } function rust { @@ -347,7 +347,7 @@ function rust { esac fi - rustc --version + command rustc --version } function rx-gcc-toolchain { @@ -398,7 +398,7 @@ function rx-gcc-toolchain { esac fi - rx-elf-gcc --version + command rx-elf-gcc --version } function sparc-gcc-toolchain { @@ -417,7 +417,7 @@ function sparc-gcc-toolchain { esac fi - sparc-gaisler-elf-gcc --version + command sparc-gaisler-elf-gcc --version } function xtensa-esp32-gcc-toolchain { @@ -441,7 +441,7 @@ function xtensa-esp32-gcc-toolchain { esac fi - xtensa-esp32-elf-gcc --version + command xtensa-esp32-elf-gcc --version } function u-boot-tools { @@ -486,8 +486,8 @@ function wasi-sdk { export WASI_SDK_PATH="${tools}/wasi-sdk" - ${WASI_SDK_PATH}/bin/clang --version - wamrc --version + command ${WASI_SDK_PATH}/bin/clang --version + command wamrc --version } function usage { From feea81bb1a48a7cb156d4b468f8bcf5d3ebbbf00 Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Wed, 13 Sep 2023 08:17:27 +0800 Subject: [PATCH 090/138] tools/ci: Fix "flock: Command not found" on macOS Signed-off-by: Xiang Xiao --- tools/ci/cibuild.sh | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/tools/ci/cibuild.sh b/tools/ci/cibuild.sh index 5e02fc160e584..b4ae9c55d5dfe 100755 --- a/tools/ci/cibuild.sh +++ b/tools/ci/cibuild.sh @@ -207,6 +207,22 @@ function elf-toolchain { command x86_64-elf-gcc --version } +function util-linux { + if ! type flock &> /dev/null; then + case ${os} in + Darwin) + brew tap discoteq/discoteq + brew install flock + ;; + Linux) + apt-get install -y util-linux + ;; + esac + fi + + command flock --version +} + function gen-romfs { if ! type genromfs &> /dev/null; then case ${os} in @@ -559,7 +575,7 @@ function install_tools { case ${os} in Darwin) - install="arm-gcc-toolchain arm64-gcc-toolchain avr-gcc-toolchain binutils bloaty elf-toolchain gen-romfs gperf kconfig-frontends mips-gcc-toolchain python-tools riscv-gcc-toolchain rust xtensa-esp32-gcc-toolchain u-boot-tools wasi-sdk c-cache" + install="arm-gcc-toolchain arm64-gcc-toolchain avr-gcc-toolchain binutils bloaty elf-toolchain gen-romfs gperf kconfig-frontends mips-gcc-toolchain python-tools riscv-gcc-toolchain rust xtensa-esp32-gcc-toolchain u-boot-tools util-linux wasi-sdk c-cache" mkdir -p "${tools}"/homebrew export HOMEBREW_CACHE=${tools}/homebrew # https://github.com/apache/arrow/issues/15025 @@ -572,7 +588,7 @@ case ${os} in rm -f /usr/local/bin/openssl || : ;; Linux) - install="arm-clang-toolchain arm-gcc-toolchain arm64-gcc-toolchain avr-gcc-toolchain binutils bloaty clang-tidy gen-romfs gperf kconfig-frontends mips-gcc-toolchain python-tools riscv-gcc-toolchain rust rx-gcc-toolchain sparc-gcc-toolchain xtensa-esp32-gcc-toolchain u-boot-tools wasi-sdk c-cache" + install="arm-clang-toolchain arm-gcc-toolchain arm64-gcc-toolchain avr-gcc-toolchain binutils bloaty clang-tidy gen-romfs gperf kconfig-frontends mips-gcc-toolchain python-tools riscv-gcc-toolchain rust rx-gcc-toolchain sparc-gcc-toolchain xtensa-esp32-gcc-toolchain u-boot-tools util-linux wasi-sdk c-cache" ;; esac From 0faa8902caf6a43e30479908e8228356c4c882db Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Mon, 18 Sep 2023 18:20:53 +0800 Subject: [PATCH 091/138] tools: Use GCC 13.2 from xPack for risc-v --- arch/risc-v/src/common/Toolchain.defs | 13 +++++++++---- tools/ci/docker/linux/Dockerfile | 16 ++++++++-------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/arch/risc-v/src/common/Toolchain.defs b/arch/risc-v/src/common/Toolchain.defs index 9032d5a89d1c5..d874224947c36 100644 --- a/arch/risc-v/src/common/Toolchain.defs +++ b/arch/risc-v/src/common/Toolchain.defs @@ -133,12 +133,17 @@ endif ifeq ($(CONFIG_RISCV_TOOLCHAIN),GNU_RVG) - # Generic GNU RVG toolchain + # Generic GNU RVG toolchain, prefer to use riscv-none-elf-gcc from xPack + # if CROSSDEV is not defined. - ifeq ($(CONFIG_RISCV_TOOLCHAIN_GNU_RV32),y) - CROSSDEV ?= riscv32-unknown-elf- + ifeq ($(shell riscv-none-elf-gcc --version > /dev/null 2>&1; echo $$?), 0) + CROSSDEV ?= riscv-none-elf- else - CROSSDEV ?= riscv64-unknown-elf- + ifeq ($(CONFIG_RISCV_TOOLCHAIN_GNU_RV32),y) + CROSSDEV ?= riscv32-unknown-elf- + else + CROSSDEV ?= riscv64-unknown-elf- + endif endif # Detect cpu ISA support flags diff --git a/tools/ci/docker/linux/Dockerfile b/tools/ci/docker/linux/Dockerfile index e1e0467d18c5b..dbf5443ea61bd 100644 --- a/tools/ci/docker/linux/Dockerfile +++ b/tools/ci/docker/linux/Dockerfile @@ -168,10 +168,10 @@ RUN cd /tools/renesas-tools/build/gcc && \ # Build image for tool required by RISCV builds ############################################################################### FROM nuttx-toolchain-base AS nuttx-toolchain-riscv -# Download the latest RISCV GCC toolchain prebuilt by SiFive -RUN mkdir riscv64-unknown-elf-gcc && \ - curl -s -L "https://static.dev.sifive.com/dev-tools/freedom-tools/v2020.12/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14.tar.gz" \ - | tar -C riscv64-unknown-elf-gcc --strip-components 1 -xz +# Download the latest RISCV GCC toolchain prebuilt by xPack +RUN mkdir riscv-none-elf-gcc && \ + curl -s -L "https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v13.2.0-1/xpack-riscv-none-elf-gcc-13.2.0-1-linux-x64.tar.gz" \ + | tar -C riscv-none-elf-gcc --strip-components 1 -xz ############################################################################### # Build image for tool required by SPARC builds @@ -350,8 +350,8 @@ COPY --from=nuttx-toolchain-renesas /tools/renesas-toolchain/rx-elf-gcc/ renesas ENV PATH="/tools/renesas-toolchain/rx-elf-gcc/bin:$PATH" # RISCV toolchain -COPY --from=nuttx-toolchain-riscv /tools/riscv64-unknown-elf-gcc/ riscv64-unknown-elf-gcc/ -ENV PATH="/tools/riscv64-unknown-elf-gcc/bin:$PATH" +COPY --from=nuttx-toolchain-riscv /tools/riscv-none-elf-gcc/ riscv-none-elf-gcc/ +ENV PATH="/tools/riscv-none-elf-gcc/bin:$PATH" # SPARC toolchain COPY --from=nuttx-toolchain-sparc /tools/sparc-gaisler-elf-gcc/ sparc-gaisler-elf-gcc/ @@ -393,8 +393,8 @@ RUN mkdir -p /tools/ccache/bin && \ ln -sf `which ccache` /tools/ccache/bin/g++ && \ ln -sf `which ccache` /tools/ccache/bin/p32-gcc && \ ln -sf `which ccache` /tools/ccache/bin/rx-elf-gcc && \ - ln -sf `which ccache` /tools/ccache/bin/riscv64-unknown-elf-gcc && \ - ln -sf `which ccache` /tools/ccache/bin/riscv64-unknown-elf-g++ && \ + ln -sf `which ccache` /tools/ccache/bin/riscv-none-elf-gcc && \ + ln -sf `which ccache` /tools/ccache/bin/riscv-none-elf-g++ && \ ln -sf `which ccache` /tools/ccache/bin/sparc-gaisler-elf-gcc && \ ln -sf `which ccache` /tools/ccache/bin/sparc-gaisler-elf-g++ && \ ln -sf `which ccache` /tools/ccache/bin/xtensa-esp32-elf-gcc && \ From 1ac9fb5ee78580c4700e6c24bed18c675719c9a7 Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Tue, 19 Sep 2023 10:43:24 +0800 Subject: [PATCH 092/138] tools: Switch riscv GCC to 12.3 GCC13 have compatibility issue with libcxx (need libcxx 17+). Please refer to: https://github.com/llvm/llvm-project/issues/62396 Signed-off-by: Huang Qi --- tools/ci/docker/linux/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/ci/docker/linux/Dockerfile b/tools/ci/docker/linux/Dockerfile index dbf5443ea61bd..272d82ad97ee5 100644 --- a/tools/ci/docker/linux/Dockerfile +++ b/tools/ci/docker/linux/Dockerfile @@ -170,7 +170,7 @@ RUN cd /tools/renesas-tools/build/gcc && \ FROM nuttx-toolchain-base AS nuttx-toolchain-riscv # Download the latest RISCV GCC toolchain prebuilt by xPack RUN mkdir riscv-none-elf-gcc && \ - curl -s -L "https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v13.2.0-1/xpack-riscv-none-elf-gcc-13.2.0-1-linux-x64.tar.gz" \ + curl -s -L "https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v12.3.0-1/xpack-riscv-none-elf-gcc-12.3.0-1-linux-x64.tar.gz" \ | tar -C riscv-none-elf-gcc --strip-components 1 -xz ############################################################################### From 8e7ec224e9eb2b2534116842bcdd96f3f07e3370 Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Tue, 19 Sep 2023 14:13:42 +0800 Subject: [PATCH 093/138] cibuild.sh: Using GCC from xPack for riscv Signed-off-by: Huang Qi --- tools/ci/cibuild.sh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tools/ci/cibuild.sh b/tools/ci/cibuild.sh index b4ae9c55d5dfe..a53b45cafa287 100755 --- a/tools/ci/cibuild.sh +++ b/tools/ci/cibuild.sh @@ -324,26 +324,26 @@ function python-tools { } function riscv-gcc-toolchain { - add_path "${tools}"/riscv64-unknown-elf-gcc/bin + add_path "${tools}"/riscv-none-elf-gcc/bin - if [ ! -f "${tools}/riscv64-unknown-elf-gcc/bin/riscv64-unknown-elf-gcc" ]; then + if [ ! -f "${tools}/riscv-none-elf-gcc/bin/riscv-none-elf-gcc" ]; then local flavor case ${os} in Darwin) - flavor=x86_64-apple-darwin + flavor=darwin-x64 ;; Linux) - flavor=x86_64-linux-ubuntu14 + flavor=linux-x64 ;; esac cd "${tools}" - wget --quiet https://static.dev.sifive.com/dev-tools/freedom-tools/v2020.12/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-${flavor}.tar.gz - tar zxf riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-${flavor}.tar.gz - mv riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-${flavor} riscv64-unknown-elf-gcc - rm riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-${flavor}.tar.gz + wget --quiet https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v12.3.0-1/xpack-riscv-none-elf-gcc-12.3.0-1-${flavor}.tar.gz + tar zxf xpack-riscv-none-elf-gcc-12.3.0-1-${flavor}.tar.gz + mv xpack-riscv-none-elf-gcc-12.3.0-1 riscv-none-elf-gcc + rm xpack-riscv-none-elf-gcc-12.3.0-1-${flavor}.tar.gz fi - command riscv64-unknown-elf-gcc --version + command riscv-none-elf-gcc --version } function rust { From 69253835a98732799c1c67144fcdddde0a6e0421 Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Wed, 20 Sep 2023 13:19:09 +0800 Subject: [PATCH 094/138] rv32m1: Fix compile error Follow other risc-v based chips, and fix: ``` chip/rv32m1_irq.c: In function 'up_irqinitialize': Error: chip/rv32m1_irq.c:98:3: error: array subscript -2048 is outside array bounds of 'uint8_t[2147483647]' {aka 'unsigned char[2147483647]'} [-Werror=array-bounds] 98 | riscv_stack_color(g_intstacktop - intstack_size, intstack_size); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In file included from /github/workspace/sources/nuttx/arch/risc-v/src/common/riscv_internal.h:40, from chip/rv32m1_irq.c:36: /github/workspace/sources/nuttx/arch/risc-v/src/common/riscv_common_memorymap.h:72:16: note: at offset -2048 into object 'g_intstacktop' of size [0, 2147483647] 72 | EXTERN uint8_t g_intstacktop[]; /* Initial top of interrupt stack */ | ^~~~~~~~~~~~~ cc1: all warnings being treated as errors ``` Signed-off-by: Huang Qi --- arch/risc-v/src/rv32m1/rv32m1_irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/risc-v/src/rv32m1/rv32m1_irq.c b/arch/risc-v/src/rv32m1/rv32m1_irq.c index 9de192d2f879d..3f21f49721237 100644 --- a/arch/risc-v/src/rv32m1/rv32m1_irq.c +++ b/arch/risc-v/src/rv32m1/rv32m1_irq.c @@ -95,7 +95,7 @@ void up_irqinitialize(void) #if defined(CONFIG_STACK_COLORATION) && CONFIG_ARCH_INTERRUPTSTACK > 15 size_t intstack_size = (CONFIG_ARCH_INTERRUPTSTACK & ~15); - riscv_stack_color(g_intstacktop - intstack_size, intstack_size); + riscv_stack_color(g_intstackalloc, intstack_size); #endif /* Clear all pending flags */ From 5c02633c4f4fd0675ce9534d3b150df85ce179d7 Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Wed, 20 Sep 2023 14:29:54 +0800 Subject: [PATCH 095/138] espressif: Force cast param in libc stubs Fix: ``` chip/esp_libc_stubs.c: In function '__retarget_lock_init': Error: chip/esp_libc_stubs.c:246:14: error: passing argument 1 of '_lock_init' from incompatible pointer type [-Werror=incompatible-pointer-types] 246 | _lock_init(lock); | ^~~~ | | | struct __lock ** chip/esp_libc_stubs.c:181:26: note: expected 'int *' but argument is of type 'struct __lock **' 181 | void _lock_init(_lock_t *lock) | ^ chip/esp_libc_stubs.c: In function '__retarget_lock_init_recursive': Error: chip/esp_libc_stubs.c:251:24: error: passing argument 1 of '_lock_init_recursive' from incompatible pointer type [-Werror=incompatible-pointer-types] 251 | _lock_init_recursive(lock); | ^~~~ | | | struct __lock ** chip/esp_libc_stubs.c:187:36: note: expected 'int *' but argument is of type 'struct __lock **' 187 | void _lock_init_recursive(_lock_t *lock) | ^ chip/esp_libc_stubs.c: In function '__retarget_lock_close': Error: chip/esp_libc_stubs.c:256:15: error: passing argument 1 of '_lock_close' from incompatible pointer type [-Werror=incompatible-pointer-types] 256 | _lock_close(&lock); | ^~~~~ | | | struct __lock ** chip/esp_libc_stubs.c:193:27: note: expected 'int *' but argument is of type 'struct __lock **' 193 | void _lock_close(_lock_t *lock) ``` Signed-off-by: Huang Qi --- arch/risc-v/src/espressif/esp_libc_stubs.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/risc-v/src/espressif/esp_libc_stubs.c b/arch/risc-v/src/espressif/esp_libc_stubs.c index f9b6c2897d960..da6eddf4c76c0 100644 --- a/arch/risc-v/src/espressif/esp_libc_stubs.c +++ b/arch/risc-v/src/espressif/esp_libc_stubs.c @@ -243,52 +243,52 @@ void _lock_release_recursive(_lock_t *lock) #if ESP_ROM_HAS_RETARGETABLE_LOCKING void __retarget_lock_init(_LOCK_T *lock) { - _lock_init(lock); + _lock_init((_lock_t *)lock); } void __retarget_lock_init_recursive(_LOCK_T *lock) { - _lock_init_recursive(lock); + _lock_init_recursive((_lock_t *)lock); } void __retarget_lock_close(_LOCK_T lock) { - _lock_close(&lock); + _lock_close((_lock_t *)&lock); } void __retarget_lock_close_recursive(_LOCK_T lock) { - _lock_close_recursive(&lock); + _lock_close_recursive((_lock_t *)&lock); } void __retarget_lock_acquire(_LOCK_T lock) { - _lock_acquire(&lock); + _lock_acquire((_lock_t *)&lock); } void __retarget_lock_acquire_recursive(_LOCK_T lock) { - _lock_acquire_recursive(&lock); + _lock_acquire_recursive((_lock_t *)&lock); } int __retarget_lock_try_acquire(_LOCK_T lock) { - return _lock_try_acquire(&lock); + return _lock_try_acquire((_lock_t *)&lock); } int __retarget_lock_try_acquire_recursive(_LOCK_T lock) { - return _lock_try_acquire_recursive(&lock); + return _lock_try_acquire_recursive((_lock_t *)&lock); } void __retarget_lock_release(_LOCK_T lock) { - _lock_release(&lock); + _lock_release((_lock_t *)&lock); } void __retarget_lock_release_recursive(_LOCK_T lock) { - _lock_release_recursive(&lock); + _lock_release_recursive((_lock_t *)&lock); } #endif From 3157f9dc53fd5bd0260844adc2ceb453cdfb57b6 Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Wed, 20 Sep 2023 09:38:12 +0800 Subject: [PATCH 096/138] boards/riscv: Fix module linker target Fix: ``` riscv-none-elf-ld: sotest.o: ABI is incompatible with that of the selected emulation: target emulation `elf64-littleriscv' does not match `elf32-littleriscv' riscv-none-elf-ld: failed to merge target specific data of file sotest.o ``` Signed-off-by: Huang Qi --- boards/risc-v/c906/smartl-c906/scripts/Make.defs | 2 +- boards/risc-v/k210/maix-bit/scripts/Make.defs | 2 +- boards/risc-v/mpfs/icicle/scripts/Make.defs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/boards/risc-v/c906/smartl-c906/scripts/Make.defs b/boards/risc-v/c906/smartl-c906/scripts/Make.defs index 13aa6816c17d4..a7b5ee48e8f83 100644 --- a/boards/risc-v/c906/smartl-c906/scripts/Make.defs +++ b/boards/risc-v/c906/smartl-c906/scripts/Make.defs @@ -49,7 +49,7 @@ AFLAGS += $(CFLAGS) -D__ASSEMBLY__ CMODULEFLAGS = $(CFLAGS) -LDMODULEFLAGS = -r -e module_initialize +LDMODULEFLAGS = -melf64lriscv -r -e module_initialize LDMODULEFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)/libs/libc/modlib/gnu-elf.ld) # ELF module definitions diff --git a/boards/risc-v/k210/maix-bit/scripts/Make.defs b/boards/risc-v/k210/maix-bit/scripts/Make.defs index 10c24c8273208..d43da4aeeafa4 100644 --- a/boards/risc-v/k210/maix-bit/scripts/Make.defs +++ b/boards/risc-v/k210/maix-bit/scripts/Make.defs @@ -38,7 +38,7 @@ AFLAGS += $(CFLAGS) -D__ASSEMBLY__ CMODULEFLAGS = $(CFLAGS) -LDMODULEFLAGS = -r -e module_initialize +LDMODULEFLAGS = -melf64lriscv -r -e module_initialize LDMODULEFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)/libs/libc/modlib/gnu-elf.ld) # ELF module definitions diff --git a/boards/risc-v/mpfs/icicle/scripts/Make.defs b/boards/risc-v/mpfs/icicle/scripts/Make.defs index c81ebf1a96b80..cc72427b79224 100644 --- a/boards/risc-v/mpfs/icicle/scripts/Make.defs +++ b/boards/risc-v/mpfs/icicle/scripts/Make.defs @@ -72,7 +72,7 @@ AFLAGS += $(CFLAGS) -D__ASSEMBLY__ CMODULEFLAGS = $(CFLAGS) -LDMODULEFLAGS = -r -e module_initialize +LDMODULEFLAGS = -melf64lriscv -r -e module_initialize LDMODULEFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)/libs/libc/modlib/gnu-elf.ld) # ELF module definitions @@ -80,5 +80,5 @@ LDMODULEFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)/libs/libc/modlib/gnu-elf.ld) CELFFLAGS = $(CFLAGS) CXXELFFLAGS = $(CXXFLAGS) -LDELFFLAGS = -r -e main +LDELFFLAGS = -melf64lriscv -r -e main LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)/binfmt/libelf/gnu-elf.ld) From b12c01c7791392ae849f9b226d2e6bf2b194d77f Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Tue, 22 Aug 2023 19:32:17 +0800 Subject: [PATCH 097/138] boards/riscv: Add -melf64lriscv to 64bit USER_LDFLAGS/LDELFFLAGS Signed-off-by: Xiang Xiao --- boards/risc-v/c906/smartl-c906/kernel/Makefile | 2 +- boards/risc-v/c906/smartl-c906/scripts/Make.defs | 2 +- boards/risc-v/k210/maix-bit/kernel/Makefile | 2 +- boards/risc-v/k210/maix-bit/scripts/Make.defs | 2 +- boards/risc-v/mpfs/common/kernel/Makefile | 2 +- boards/risc-v/mpfs/m100pfsevp/scripts/Make.defs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/boards/risc-v/c906/smartl-c906/kernel/Makefile b/boards/risc-v/c906/smartl-c906/kernel/Makefile index 6b4cb180ba601..9da36f4eee988 100644 --- a/boards/risc-v/c906/smartl-c906/kernel/Makefile +++ b/boards/risc-v/c906/smartl-c906/kernel/Makefile @@ -43,7 +43,7 @@ USER_HEXFILE += $(call CONVERT_PATH,$(TOPDIR)$(DELIM)nuttx_user.hex) USER_SRECFILE += $(call CONVERT_PATH,$(TOPDIR)$(DELIM)nuttx_user.srec) USER_BINFILE += $(call CONVERT_PATH,$(TOPDIR)$(DELIM)nuttx_user.bin) -USER_LDFLAGS = --undefined=$(ENTRYPT) --entry=$(ENTRYPT) $(USER_LDSCRIPT) +USER_LDFLAGS = -melf64lriscv --undefined=$(ENTRYPT) --entry=$(ENTRYPT) $(USER_LDSCRIPT) USER_LDLIBS = $(patsubst lib%,-l%,$(basename $(notdir $(USERLIBS)))) USER_LIBGCC = "${shell "$(CC)" $(ARCHCPUFLAGS) -print-libgcc-file-name}" diff --git a/boards/risc-v/c906/smartl-c906/scripts/Make.defs b/boards/risc-v/c906/smartl-c906/scripts/Make.defs index a7b5ee48e8f83..61dd59b147e37 100644 --- a/boards/risc-v/c906/smartl-c906/scripts/Make.defs +++ b/boards/risc-v/c906/smartl-c906/scripts/Make.defs @@ -57,5 +57,5 @@ LDMODULEFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)/libs/libc/modlib/gnu-elf.ld) CELFFLAGS = $(CFLAGS) CXXELFFLAGS = $(CXXFLAGS) -LDELFFLAGS = -r -e main +LDELFFLAGS = -melf64lriscv -r -e main LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)/binfmt/libelf/gnu-elf.ld) diff --git a/boards/risc-v/k210/maix-bit/kernel/Makefile b/boards/risc-v/k210/maix-bit/kernel/Makefile index a78a4a69ecc7c..7df8fc03d6c3f 100644 --- a/boards/risc-v/k210/maix-bit/kernel/Makefile +++ b/boards/risc-v/k210/maix-bit/kernel/Makefile @@ -35,7 +35,7 @@ USER_HEXFILE += $(call CONVERT_PATH,$(TOPDIR)$(DELIM)nuttx_user.hex) USER_SRECFILE += $(call CONVERT_PATH,$(TOPDIR)$(DELIM)nuttx_user.srec) USER_BINFILE += $(call CONVERT_PATH,$(TOPDIR)$(DELIM)nuttx_user.bin) -USER_LDFLAGS = --undefined=$(ENTRYPT) --entry=$(ENTRYPT) $(USER_LDSCRIPT) +USER_LDFLAGS = -melf64lriscv --undefined=$(ENTRYPT) --entry=$(ENTRYPT) $(USER_LDSCRIPT) USER_LDLIBS = $(patsubst lib%,-l%,$(basename $(notdir $(USERLIBS)))) USER_LIBGCC = "${shell "$(CC)" $(ARCHCPUFLAGS) -print-libgcc-file-name}" diff --git a/boards/risc-v/k210/maix-bit/scripts/Make.defs b/boards/risc-v/k210/maix-bit/scripts/Make.defs index d43da4aeeafa4..670e43d2b1052 100644 --- a/boards/risc-v/k210/maix-bit/scripts/Make.defs +++ b/boards/risc-v/k210/maix-bit/scripts/Make.defs @@ -46,5 +46,5 @@ LDMODULEFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)/libs/libc/modlib/gnu-elf.ld) CELFFLAGS = $(CFLAGS) CXXELFFLAGS = $(CXXFLAGS) -LDELFFLAGS = -r -e main +LDELFFLAGS = -melf64lriscv -r -e main LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)/binfmt/libelf/gnu-elf.ld) diff --git a/boards/risc-v/mpfs/common/kernel/Makefile b/boards/risc-v/mpfs/common/kernel/Makefile index 3447d2f7d18c2..0566d6873f90c 100644 --- a/boards/risc-v/mpfs/common/kernel/Makefile +++ b/boards/risc-v/mpfs/common/kernel/Makefile @@ -39,7 +39,7 @@ USER_HEXFILE += $(call CONVERT_PATH,$(TOPDIR)$(DELIM)nuttx_user.hex) USER_SRECFILE += $(call CONVERT_PATH,$(TOPDIR)$(DELIM)nuttx_user.srec) USER_BINFILE += $(call CONVERT_PATH,$(TOPDIR)$(DELIM)nuttx_user.bin) -USER_LDFLAGS = --undefined=$(ENTRYPT) --entry=$(ENTRYPT) $(USER_LDSCRIPT) +USER_LDFLAGS = -melf64lriscv --undefined=$(ENTRYPT) --entry=$(ENTRYPT) $(USER_LDSCRIPT) USER_LDLIBS = $(patsubst lib%,-l%,$(basename $(notdir $(USERLIBS)))) USER_LIBGCC = "${shell "$(CC)" $(ARCHCPUFLAGS) -print-libgcc-file-name}" diff --git a/boards/risc-v/mpfs/m100pfsevp/scripts/Make.defs b/boards/risc-v/mpfs/m100pfsevp/scripts/Make.defs index b74eb4721a581..cd4f64c07200c 100644 --- a/boards/risc-v/mpfs/m100pfsevp/scripts/Make.defs +++ b/boards/risc-v/mpfs/m100pfsevp/scripts/Make.defs @@ -57,5 +57,5 @@ LDMODULEFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)/libs/libc/modlib/gnu-elf.ld) CELFFLAGS = $(CFLAGS) CXXELFFLAGS = $(CXXFLAGS) -LDELFFLAGS = -r -e main +LDELFFLAGS = -melf64lriscv -r -e main LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)/binfmt/libelf/gnu-elf.ld) From a4ee2da34488913bddea1d5c50f7480892b27228 Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Tue, 22 Aug 2023 22:52:44 +0800 Subject: [PATCH 098/138] arch/riscv: Move -mcmodel=medany from Make.defs to Toolchain.defs to avoid the code duplication Signed-off-by: Xiang Xiao --- arch/risc-v/src/common/Toolchain.defs | 4 +++- boards/risc-v/c906/smartl-c906/scripts/Make.defs | 9 --------- boards/risc-v/jh7110/star64/scripts/Make.defs | 2 -- boards/risc-v/k210/maix-bit/scripts/Make.defs | 2 -- boards/risc-v/mpfs/icicle/scripts/Make.defs | 8 -------- boards/risc-v/mpfs/m100pfsevp/scripts/Make.defs | 9 --------- boards/risc-v/qemu-rv/rv-virt/scripts/Make.defs | 2 -- 7 files changed, 3 insertions(+), 33 deletions(-) diff --git a/arch/risc-v/src/common/Toolchain.defs b/arch/risc-v/src/common/Toolchain.defs index d874224947c36..47fd54fca979e 100644 --- a/arch/risc-v/src/common/Toolchain.defs +++ b/arch/risc-v/src/common/Toolchain.defs @@ -183,12 +183,14 @@ ifeq ($(CONFIG_RISCV_TOOLCHAIN),GNU_RVG) ARCHTYPE = rv64 ARCHABITYPE = lp64 LLVM_ARCHTYPE := riscv64 + # https://www.sifive.com/blog/all-aboard-part-4-risc-v-code-models + ARCHCPUFLAGS = -mcmodel=medany endif # Construct arch flags ARCHCPUEXTFLAGS = i$(ARCHRVISAM)$(ARCHRVISAA)$(ARCHRVISAF)$(ARCHRVISAD)$(ARCHRVISAC)$(ARCHRVISAZ) - ARCHCPUFLAGS = -march=$(ARCHTYPE)$(ARCHCPUEXTFLAGS) + ARCHCPUFLAGS += -march=$(ARCHTYPE)$(ARCHCPUEXTFLAGS) # Construct arch abi flags diff --git a/boards/risc-v/c906/smartl-c906/scripts/Make.defs b/boards/risc-v/c906/smartl-c906/scripts/Make.defs index 61dd59b147e37..ee56bdbdb0cea 100644 --- a/boards/risc-v/c906/smartl-c906/scripts/Make.defs +++ b/boards/risc-v/c906/smartl-c906/scripts/Make.defs @@ -27,17 +27,8 @@ ifeq ($(CONFIG_C906_WITH_QEMU),y) else LDSCRIPT = ld.script endif - ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDSCRIPT) -# The following options are for the toolchain from T-HEAD. -# For more info ahout the T-HEAD ISA extensions, please refer to the C906 user guide. -# ARCHCPUFLAGS = -march=rv64gcxthead -mabi=lp64d -mtune=c906 -mcmodel=medany -# TODO: We are not going to enable this at this time for the CI compatibility. - -ARCHCPUFLAGS += -mcmodel=medany - - CFLAGS = $(ARCHCFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe CPICFLAGS = $(ARCHPICFLAGS) $(CFLAGS) CXXFLAGS = $(ARCHCXXFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe diff --git a/boards/risc-v/jh7110/star64/scripts/Make.defs b/boards/risc-v/jh7110/star64/scripts/Make.defs index 0048a3c6e0b70..4cdac79de7e8f 100644 --- a/boards/risc-v/jh7110/star64/scripts/Make.defs +++ b/boards/risc-v/jh7110/star64/scripts/Make.defs @@ -24,8 +24,6 @@ include $(TOPDIR)/arch/risc-v/src/common/Toolchain.defs LDSCRIPT = ld.script ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDSCRIPT) - -ARCHCPUFLAGS += -mcmodel=medany ARCHPICFLAGS = -fpic -msingle-pic-base CFLAGS := $(ARCHCFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe diff --git a/boards/risc-v/k210/maix-bit/scripts/Make.defs b/boards/risc-v/k210/maix-bit/scripts/Make.defs index 670e43d2b1052..f40ceb860b7fe 100644 --- a/boards/risc-v/k210/maix-bit/scripts/Make.defs +++ b/boards/risc-v/k210/maix-bit/scripts/Make.defs @@ -25,8 +25,6 @@ include $(TOPDIR)/arch/risc-v/src/common/Toolchain.defs LDSCRIPT = ld.script ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDSCRIPT) -ARCHCPUFLAGS += -mcmodel=medany -mstrict-align - CFLAGS := $(ARCHCFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe CPICFLAGS = $(ARCHPICFLAGS) $(CFLAGS) CXXFLAGS := $(ARCHCXXFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe diff --git a/boards/risc-v/mpfs/icicle/scripts/Make.defs b/boards/risc-v/mpfs/icicle/scripts/Make.defs index cc72427b79224..f5a36739866af 100644 --- a/boards/risc-v/mpfs/icicle/scripts/Make.defs +++ b/boards/risc-v/mpfs/icicle/scripts/Make.defs @@ -53,14 +53,6 @@ ifneq ($(LDMEMORY),) endif ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDSCRIPT) -# The following options are for the toolchain from T-HEAD. -# For more info ahout the T-HEAD ISA extensions, please refer to the MPFS user guide. -# ARCHCPUFLAGS = -march=rv64gcxthead -mabi=lp64d -mcmodel=medany -# TODO: We are not going to enable this at this time for the CI compatibility. - -ARCHCPUFLAGS += -mcmodel=medany - - CFLAGS = $(ARCHCFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe CPICFLAGS = $(ARCHPICFLAGS) $(CFLAGS) CXXFLAGS = $(ARCHCXXFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe diff --git a/boards/risc-v/mpfs/m100pfsevp/scripts/Make.defs b/boards/risc-v/mpfs/m100pfsevp/scripts/Make.defs index cd4f64c07200c..e39fda5107ce6 100644 --- a/boards/risc-v/mpfs/m100pfsevp/scripts/Make.defs +++ b/boards/risc-v/mpfs/m100pfsevp/scripts/Make.defs @@ -27,17 +27,8 @@ ifeq ($(CONFIG_MPFS_BOOTLOADER),y) else LDSCRIPT = ld.script endif - ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDSCRIPT) -# The following options are for the toolchain from T-HEAD. -# For more info ahout the T-HEAD ISA extensions, please refer to the MPFS user guide. -# ARCHCPUFLAGS = -march=rv64gcxthead -mabi=lp64d -mcmodel=medany -# TODO: We are not going to enable this at this time for the CI compatibility. - -ARCHCPUFLAGS += -mcmodel=medany - - CFLAGS = $(ARCHCFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe CPICFLAGS = $(ARCHPICFLAGS) $(CFLAGS) CXXFLAGS = $(ARCHCXXFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe diff --git a/boards/risc-v/qemu-rv/rv-virt/scripts/Make.defs b/boards/risc-v/qemu-rv/rv-virt/scripts/Make.defs index ab13f19b9c6b9..453bad37bc62c 100644 --- a/boards/risc-v/qemu-rv/rv-virt/scripts/Make.defs +++ b/boards/risc-v/qemu-rv/rv-virt/scripts/Make.defs @@ -35,8 +35,6 @@ endif endif ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDSCRIPT) - -ARCHCPUFLAGS += -mcmodel=medany ARCHPICFLAGS = -fpic -msingle-pic-base CFLAGS := $(ARCHCFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) -pipe From 1e8a8f3adf4e62419581097da2ff4cc9962f9140 Mon Sep 17 00:00:00 2001 From: Eero Nurkkala Date: Mon, 18 Sep 2023 08:55:49 +0300 Subject: [PATCH 099/138] risc-v/mpfs: ihc: don't wait for master if it's already up After rebooting this ihc client hart only, ihc will hang as it's waiting for the initial handshake that just won't be there. Detect this situation and let the rptun / ihc know the master is already up. This makes the RPMSG bus usable even after NuttX reboot, in case there's not much traffic. However, Linux is likely to mark the virtio queue broken if there's descent amount of traffic. This makes the bus no longer function. Also deny uninitialized early access for particular structs. Signed-off-by: Eero Nurkkala --- arch/risc-v/src/mpfs/mpfs_ihc.c | 49 +++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_ihc.c b/arch/risc-v/src/mpfs/mpfs_ihc.c index 037cb2de5cc80..3310f6070153e 100644 --- a/arch/risc-v/src/mpfs/mpfs_ihc.c +++ b/arch/risc-v/src/mpfs/mpfs_ihc.c @@ -454,10 +454,20 @@ static uint32_t mpfs_ihc_context_to_local_hart_id(ihc_channel_t channel) static void mpfs_ihc_rx_handler(uint32_t *message) { - g_vq_idx = message[0]; + uint32_t msg = message[0]; - DEBUGASSERT((g_vq_idx == VRING0_NOTIFYID) || - (g_vq_idx == VRING1_NOTIFYID)); + /* After a warm reboot, the message may be initially corrupt as the renote + * doesn't know we restarted and reinitialized the registers. + */ + + if ((msg == VRING0_NOTIFYID) || (msg == VRING1_NOTIFYID)) + { + g_vq_idx = msg; + } + else + { + return; + } #ifdef MPFS_RPTUN_USE_THREAD nxsem_post(&g_mpfs_rx_sig); @@ -905,9 +915,12 @@ mpfs_rptun_get_resource(struct rptun_dev_s *dev) rsc->rpmsg_vdev.gfeatures = 1 << VIRTIO_RPMSG_F_NS | 1 << VIRTIO_RPMSG_F_ACK; - /* Set to VIRTIO_CONFIG_STATUS_DRIVER_OK when master is up */ + /* If the master is up already, don't clear the status here */ - rsc->rpmsg_vdev.status = 0; + if (!g_shmem.master_up) + { + rsc->rpmsg_vdev.status = 0; + } rsc->rpmsg_vdev.config_len = sizeof(struct fw_rsc_config); rsc->rpmsg_vdev.num_of_vrings = VRINGS; @@ -1236,6 +1249,13 @@ static void mpfs_rptun_worker(void *arg) { struct mpfs_queue_table_s *info; + /* Check whether the struct is initialized yet */ + + if (*(uintptr_t *)&g_mpfs_virtqueue_table[0] == 0) + { + return; + } + DEBUGASSERT((g_vq_idx - VRING0_NOTIFYID) < VRINGS); info = &g_mpfs_virtqueue_table[g_vq_idx - VRING0_NOTIFYID]; virtqueue_notification((struct virtqueue *)info->data); @@ -1266,6 +1286,13 @@ static int mpfs_rptun_thread(int argc, char *argv[]) while (1) { + /* Check whether the struct is initialized yet */ + + if (*(uintptr_t *)&g_mpfs_virtqueue_table[0] == 0) + { + return 0; + } + DEBUGASSERT((g_vq_idx - VRING0_NOTIFYID) < VRINGS); info = &g_mpfs_virtqueue_table[g_vq_idx - VRING0_NOTIFYID]; virtqueue_notification((struct virtqueue *)info->data); @@ -1349,6 +1376,18 @@ int mpfs_ihc_init(void) /* Initialize and wait for the master. This will block until. */ ihcinfo("Waiting for the master online...\n"); + + /* Check if the remote is already up. This is the case after reboot of + * this particular hart only. + */ + + if ((getreg32(MPFS_IHC_CTRL(CONTEXTA_HARTID, CONTEXTB_HARTID)) & (MPIE_EN + | ACKIE_EN)) != 0) + { + g_shmem.master_up = true; + g_shmem.rsc.rpmsg_vdev.status |= VIRTIO_CONFIG_STATUS_DRIVER_OK; + } + ret = mpfs_rptun_init(MPFS_RPTUN_SHMEM_NAME, MPFS_RPTUN_CPU_NAME); if (ret < 0) { From 23a616376e83e0d660eaca3a74a8d601f79b1cdf Mon Sep 17 00:00:00 2001 From: Eero Nurkkala Date: Tue, 26 Sep 2023 11:59:00 +0300 Subject: [PATCH 100/138] risc-v/mpfs: emmcsd: deny unaligned access Don't allow unaligned access with the DMA requests. Return -EFAULT in case the provided address is unaligned. Signed-off-by: Eero Nurkkala --- arch/risc-v/src/mpfs/mpfs_emmcsd.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_emmcsd.c b/arch/risc-v/src/mpfs/mpfs_emmcsd.c index ca4ec4c5ef4c7..ef6cbbd337dbf 100644 --- a/arch/risc-v/src/mpfs/mpfs_emmcsd.c +++ b/arch/risc-v/src/mpfs/mpfs_emmcsd.c @@ -2280,7 +2280,11 @@ static int mpfs_dmarecvsetup(struct sdio_dev_s *dev, mcinfo("Receive: %zu bytes\n", buflen); DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0); - DEBUGASSERT(((uintptr_t)buffer & 3) == 0); + if (((uintptr_t)buffer & 3) != 0) + { + mcerr("Unaligned buffer: %p\n", buffer); + return -EFAULT; + } priv->buffer = (uint32_t *)buffer; priv->remaining = buflen; @@ -2340,7 +2344,11 @@ static int mpfs_dmasendsetup(struct sdio_dev_s *dev, mcinfo("Send: %zu bytes\n", buflen); DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0); - DEBUGASSERT(((uintptr_t)buffer & 3) == 0); + if (((uintptr_t)buffer & 3) != 0) + { + mcerr("Unaligned buffer: %p\n", buffer); + return -EFAULT; + } /* DMA send doesn't work in 0x08xxxxxxx address range. Default to IRQ mode * in this special case. From 1f40a926c4b7f1160df9b61a40ecd98fb2d30385 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Fri, 22 Sep 2023 14:34:22 +0300 Subject: [PATCH 101/138] mpfs/mpfs_corespi: Several speed optimizations to the FPGA driver This is a collection of tweaks / optimizations to the driver to limit CPU usage as well as interrupt processing times. The changes are as follows: - setfrequency is now no-op if the frequency does not change. Accessing MPFS_SPI_CONTROL requires synchronization to the FIC domain, which takes unnecessary time if nothing changes - load/unload FIFO loops optimized so !buffer, priv->nbits and i==last are only tested once (instead of for every word written in loop). - Disable the RX interrupt only once (again, FIC domain access is slow) - In case a spurious MPFS_SPI_DATA_RX interrupt arrives, just wipe the whole RX FIFO, instead of trying to read it byte-by-byte --- arch/risc-v/src/mpfs/mpfs_corespi.c | 139 ++++++++++++---------------- 1 file changed, 57 insertions(+), 82 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_corespi.c b/arch/risc-v/src/mpfs/mpfs_corespi.c index 43b1cacf3abe5..3e23479a5dc64 100644 --- a/arch/risc-v/src/mpfs/mpfs_corespi.c +++ b/arch/risc-v/src/mpfs/mpfs_corespi.c @@ -528,6 +528,13 @@ static uint32_t mpfs_spi_setfrequency(struct spi_dev_s *dev, DEBUGASSERT(frequency > 0); + if (priv->frequency == frequency) + { + /* Nothing changes */ + + return priv->actual; + } + if (priv->enabled) { modifyreg32(MPFS_SPI_CONTROL, MPFS_SPI_ENABLE, 0); @@ -738,54 +745,38 @@ static void mpfs_spi_load_tx_fifo(struct mpfs_spi_priv_s *priv, { uint16_t *data16; uint8_t *data8; - int last; int i; DEBUGASSERT(nwords > 0); data16 = (uint16_t *)txbuffer; data8 = (uint8_t *)txbuffer; - last = nwords - 1; - for (i = 0; i < nwords; i++) + if (!txbuffer) { - if (txbuffer) + for (i = 0; i < nwords - 1; i++) { - if (priv->nbits == 8) - { - if (i == last) - { - putreg32((uint32_t)data8[priv->tx_pos], MPFS_SPI_TX_LAST); - } - else - { - putreg32((uint32_t)data8[priv->tx_pos], MPFS_SPI_TX_DATA); - } - } - else - { - if (i == last) - { - putreg32((uint32_t)data16[priv->tx_pos], MPFS_SPI_TX_LAST); - } - else - { - putreg32((uint32_t)data16[priv->tx_pos], MPFS_SPI_TX_DATA); - } - } + putreg32(0, MPFS_SPI_TX_DATA); } - else + + putreg32(0, MPFS_SPI_TX_LAST); + } + else if (priv->nbits == 8) + { + for (i = 0; i < nwords - 1; i++) { - if (i == last) - { - putreg32(0, MPFS_SPI_TX_LAST); - } - else - { - putreg32(0, MPFS_SPI_TX_DATA); - } + putreg32((uint32_t)data8[priv->tx_pos++], MPFS_SPI_TX_DATA); + } + + putreg32((uint32_t)data8[priv->tx_pos++], MPFS_SPI_TX_LAST); + } + else + { + for (i = 0; i < nwords - 1; i++) + { + putreg32((uint32_t)data16[priv->tx_pos++], MPFS_SPI_TX_DATA); } - priv->tx_pos++; + putreg32((uint32_t)data16[priv->tx_pos++], MPFS_SPI_TX_LAST); } } @@ -812,48 +803,40 @@ static void mpfs_spi_unload_rx_fifo(struct mpfs_spi_priv_s *priv, { uint16_t *data16; uint8_t *data8; - int last; int i; DEBUGASSERT(nwords > 0); data16 = (uint16_t *)rxbuffer; data8 = (uint8_t *)rxbuffer; - last = nwords - 1; - for (i = 0; i < nwords; i++) + if (!rxbuffer) { - /* The last character might not be available yet due to bus delays */ - - if (i == last) + modifyreg32(MPFS_SPI_COMMAND, 0, MPFS_SPI_RXFIFORST); + } + else if (priv->nbits == 8) + { + for (i = 0; i < nwords - 1; i++) { - if (mpfs_rx_wait_last_frame(priv) < 0) - { - /* Nothing came, get out */ - - return; - } + data8[priv->rx_pos++] = getreg32(MPFS_SPI_RX_DATA); } - if (rxbuffer) + if (mpfs_rx_wait_last_frame(priv) == 0) { - if (priv->nbits == 8) - { - data8[priv->rx_pos] = getreg32(MPFS_SPI_RX_DATA); - } - else - { - data16[priv->rx_pos] = getreg32(MPFS_SPI_RX_DATA); - } + data8[priv->rx_pos++] = getreg32(MPFS_SPI_RX_DATA); } - else + } + else if (priv->nbits == 16) + { + for (i = 0; i < nwords - 1; i++) { - getreg32(MPFS_SPI_RX_DATA); + data16[priv->rx_pos++] = getreg32(MPFS_SPI_RX_DATA); } - priv->rx_pos++; - - DEBUGASSERT(priv->rx_pos <= priv->rxwords); + if (mpfs_rx_wait_last_frame(priv) == 0) + { + data16[priv->rx_pos++] = getreg32(MPFS_SPI_RX_DATA); + } } } @@ -934,10 +917,6 @@ static void mpfs_spi_irq_exchange(struct mpfs_spi_priv_s *priv, MPFS_SPI_INTRXOVRFLOW | MPFS_SPI_INTTXDONE); - /* Make sure the RX interrupt is disabled */ - - modifyreg32(MPFS_SPI_CONTROL2, MPFS_SPI_INTEN_DATA_RX, 0); - if (mpfs_spi_sem_waitdone(priv) < 0) { spiinfo("Message timed out\n"); @@ -1303,22 +1282,6 @@ static int mpfs_spi_irq(int cpuint, void *context, void *arg) spiinfo("irq status=%x\n", status); - if (status & MPFS_SPI_DATA_RX) - { - remaining = priv->rxwords - priv->rx_pos; - - if (remaining <= priv->fifosize) - { - mpfs_spi_unload_rx_fifo(priv, priv->rxbuf, remaining); - } - else - { - mpfs_spi_unload_rx_fifo(priv, priv->rxbuf, priv->fifolevel); - } - - putreg32(MPFS_SPI_DATA_RX, MPFS_SPI_INT_CLEAR); - } - if (status & MPFS_SPI_TXDONE) { /* TX is done, we know RX is done too -> offload the RX FIFO */ @@ -1356,6 +1319,14 @@ static int mpfs_spi_irq(int cpuint, void *context, void *arg) } } + if (status & MPFS_SPI_DATA_RX) + { + /* We don't expect data RX interrupts, just reset RX FIFO */ + + modifyreg32(MPFS_SPI_COMMAND, 0, MPFS_SPI_RXFIFORST); + putreg32(MPFS_SPI_DATA_RX, MPFS_SPI_INT_CLEAR); + } + if (status & MPFS_SPI_RXCHOVRFLW) { /* Handle receive overflow */ @@ -1448,6 +1419,10 @@ static void mpfs_spi_init(struct spi_dev_s *dev) 0); modifyreg32(MPFS_SYSREG_SUBBLK_CLOCK_CR, 0, MPFS_SYSREG_SUBBLK_CORESPI); + /* Make sure the RX interrupt is disabled (we don't use it) */ + + modifyreg32(MPFS_SPI_CONTROL2, MPFS_SPI_INTEN_DATA_RX, 0); + /* Install some default values, mode and nbits for read back */ mpfs_spi_setfrequency(dev, config->clk_freq); From 16e2f09f1e4e2b471f2184293bfb595907e5aa16 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Wed, 27 Sep 2023 15:04:00 +0300 Subject: [PATCH 102/138] risc-v/pgalloc.h: Add SHM area to riscv_uservaddr query If the vaddr resides within the user's SHM, it is a user memory mapping. --- arch/risc-v/src/common/pgalloc.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/risc-v/src/common/pgalloc.h b/arch/risc-v/src/common/pgalloc.h index 8619038ac7eb7..40da29805660b 100644 --- a/arch/risc-v/src/common/pgalloc.h +++ b/arch/risc-v/src/common/pgalloc.h @@ -95,7 +95,11 @@ static inline bool riscv_uservaddr(uintptr_t vaddr) * heap, or stack regions. */ - return vaddr >= ARCH_ADDRENV_VBASE && vaddr < ARCH_ADDRENV_VEND; + return ((vaddr >= ARCH_ADDRENV_VBASE && vaddr < ARCH_ADDRENV_VEND) +#ifdef CONFIG_ARCH_VMA_MAPPING + || (vaddr >= CONFIG_ARCH_SHM_VBASE && vaddr < ARCH_SHM_VEND) +#endif + ); } /**************************************************************************** From 46ec2ab52233b1a3dabd657b186666e7864f87c3 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Wed, 27 Sep 2023 15:04:59 +0300 Subject: [PATCH 103/138] risc-v/riscv_addrenv.c: Fix bug where SHM area page tables are not freed The SHM physically backed memory does not belong to the user process, but the page table containing the mapping does -> delete the page table memory regardless. --- arch/risc-v/src/common/riscv_addrenv.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/arch/risc-v/src/common/riscv_addrenv.c b/arch/risc-v/src/common/riscv_addrenv.c index 685dea744e6d0..cb49c1a51daf0 100644 --- a/arch/risc-v/src/common/riscv_addrenv.c +++ b/arch/risc-v/src/common/riscv_addrenv.c @@ -535,28 +535,24 @@ int up_addrenv_destroy(arch_addrenv_t *addrenv) { for (i = 0; i < ENTRIES_PER_PGT; i++, vaddr += pgsize) { - if (vaddr_is_shm(vaddr)) - { - /* Do not free memory from SHM area */ - - continue; - } - ptlast = (uintptr_t *)riscv_pgvaddr(mmu_pte_to_paddr(ptprev[i])); if (ptlast) { - /* Page table allocated, free any allocated memory */ - - for (j = 0; j < ENTRIES_PER_PGT; j++) + if (!vaddr_is_shm(vaddr)) { - paddr = mmu_pte_to_paddr(ptlast[j]); - if (paddr) + /* Free the allocated pages, but not from SHM area */ + + for (j = 0; j < ENTRIES_PER_PGT; j++) { - mm_pgfree(paddr, 1); + paddr = mmu_pte_to_paddr(ptlast[j]); + if (paddr) + { + mm_pgfree(paddr, 1); + } } } - /* Then free the page table itself */ + /* Regardless, free the page table itself */ mm_pgfree((uintptr_t)ptlast, 1); } From ccbcb7902a35135c3394d94cf4aba50a06d6cf48 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Fri, 29 Sep 2023 12:30:46 +0300 Subject: [PATCH 104/138] mm/kmap: Change kmm_user_map to kmm_map_user Naming consistency wrt kmm_map_user_page --- include/nuttx/mm/kmap.h | 4 ++-- mm/kmap/kmm_map.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/nuttx/mm/kmap.h b/include/nuttx/mm/kmap.h index f81536352a9fb..baa5630dca1e4 100644 --- a/include/nuttx/mm/kmap.h +++ b/include/nuttx/mm/kmap.h @@ -72,7 +72,7 @@ FAR void *kmm_map(FAR void **pages, size_t npages, int prot); void kmm_unmap(FAR void *kaddr); /**************************************************************************** - * Name: kmm_user_map + * Name: kmm_map_user * * Description: * Map a region of user memory (physical pages) for kernel use through @@ -87,7 +87,7 @@ void kmm_unmap(FAR void *kaddr); * ****************************************************************************/ -FAR void *kmm_user_map(FAR void *uaddr, size_t size); +FAR void *kmm_map_user(FAR void *uaddr, size_t size); /**************************************************************************** * Name: kmm_map_user_page diff --git a/mm/kmap/kmm_map.c b/mm/kmap/kmm_map.c index 883b019c44a78..85d435d485dca 100644 --- a/mm/kmap/kmm_map.c +++ b/mm/kmap/kmm_map.c @@ -331,7 +331,7 @@ void kmm_unmap(FAR void *kaddr) } /**************************************************************************** - * Name: kmm_user_map + * Name: kmm_map_user * * Description: * Map a region of user memory (physical pages) for kernel use through @@ -346,7 +346,7 @@ void kmm_unmap(FAR void *kaddr) * ****************************************************************************/ -FAR void *kmm_user_map(FAR void *uaddr, size_t size) +FAR void *kmm_map_user(FAR void *uaddr, size_t size) { FAR void *pages; uintptr_t vaddr; From 5844fae819524cace7bd1c841cb17255a1d00621 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Fri, 29 Sep 2023 12:31:33 +0300 Subject: [PATCH 105/138] mm/kmap: Fix bug in kmm_unmap Searching the current process mappings for kmappings is quite futile, do the search in the kernel's mappings instead. --- mm/kmap/kmm_map.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/kmap/kmm_map.c b/mm/kmap/kmm_map.c index 85d435d485dca..1312e6af0e31c 100644 --- a/mm/kmap/kmm_map.c +++ b/mm/kmap/kmm_map.c @@ -308,7 +308,7 @@ void kmm_unmap(FAR void *kaddr) { /* Find the entry, it is OK if none found */ - entry = mm_map_find(get_current_mm(), kaddr, 1); + entry = mm_map_find(&g_kmm_map, kaddr, 1); if (entry) { npages = MM_NPAGES(entry->length); From 62897c422bf3e9fdd1fef02ed2e6b454e26c649c Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Fri, 29 Sep 2023 14:37:25 +0300 Subject: [PATCH 106/138] riscv/addrenv: Fix the user VMA end address The end address was off by 1, making it overflow to 0 (u32 value). --- arch/risc-v/src/common/addrenv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/risc-v/src/common/addrenv.h b/arch/risc-v/src/common/addrenv.h index 8cb949af314e1..7be666e84ebf0 100644 --- a/arch/risc-v/src/common/addrenv.h +++ b/arch/risc-v/src/common/addrenv.h @@ -58,7 +58,7 @@ /* User address environment end */ -#define ARCH_ADDRENV_VEND (ARCH_ADDRENV_VBASE + ARCH_ADDRENV_MAX_SIZE) +#define ARCH_ADDRENV_VEND (ARCH_ADDRENV_VBASE + ARCH_ADDRENV_MAX_SIZE - 1) /**************************************************************************** * Public Function Prototypes From 5c4512346b35756d4d10ec88d84bc995688dd570 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Wed, 4 Oct 2023 12:19:16 +0300 Subject: [PATCH 107/138] [REVERTME] riscv_addrenc.c: Add more heap, if TLS_ALIGNED is set The TLS alignment requires more room in the stack, which means more _initial_ heap is required to accomodate the stack. Why 2x TLS_MAXSTACK ? No idea. This is a temporary fix, like the +1 page extra above. --- arch/risc-v/src/common/riscv_addrenv.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/risc-v/src/common/riscv_addrenv.c b/arch/risc-v/src/common/riscv_addrenv.c index cb49c1a51daf0..dfdcfb6aea2fb 100644 --- a/arch/risc-v/src/common/riscv_addrenv.c +++ b/arch/risc-v/src/common/riscv_addrenv.c @@ -65,6 +65,7 @@ #include #include #include +#include #include @@ -421,6 +422,12 @@ int up_addrenv_create(size_t textsize, size_t datasize, size_t heapsize, heapsize = heapsize + MM_PGALIGNUP(CONFIG_DEFAULT_TASK_STACKSIZE); +#ifdef CONFIG_TLS_ALIGNED + /* Need more stack for TLS alignment */ + + heapsize += MM_PGALIGNUP(2 * TLS_MAXSTACK); +#endif + /* Map the reserved area */ ret = create_region(addrenv, resvbase, resvsize, MMU_UDATA_FLAGS); From 8c04b718c79b8e9ed287eda6a4fa0bbe6806f776 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Wed, 4 Oct 2023 15:54:49 +0300 Subject: [PATCH 108/138] riscv_addrenv_utils.c: Determine page table flags by type of vaddr Use kernel page table flags if the mapped virtual address is in kernel space. --- arch/risc-v/src/common/riscv_addrenv_utils.c | 24 ++++++++++++++++++-- arch/risc-v/src/common/riscv_mmu.h | 4 ++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/arch/risc-v/src/common/riscv_addrenv_utils.c b/arch/risc-v/src/common/riscv_addrenv_utils.c index 810563aedd47a..e13fb89ff9e64 100644 --- a/arch/risc-v/src/common/riscv_addrenv_utils.c +++ b/arch/risc-v/src/common/riscv_addrenv_utils.c @@ -63,13 +63,22 @@ uintptr_t riscv_get_pgtable(arch_addrenv_t *addrenv, uintptr_t vaddr) uintptr_t paddr; uintptr_t ptprev; uint32_t ptlevel; + uint32_t flags; /* Get the current level MAX_LEVELS-1 entry corresponding to this vaddr */ ptlevel = ARCH_SPGTS; ptprev = riscv_pgvaddr(addrenv->spgtables[ARCH_SPGTS - 1]); - paddr = mmu_pte_to_paddr(mmu_ln_getentry(ptlevel, ptprev, vaddr)); + if (!ptprev) + { + /* Something is very wrong */ + + return 0; + } + + /* Find the physical address of the final level page table */ + paddr = mmu_pte_to_paddr(mmu_ln_getentry(ptlevel, ptprev, vaddr)); if (!paddr) { /* No page table has been allocated... allocate one now */ @@ -77,10 +86,21 @@ uintptr_t riscv_get_pgtable(arch_addrenv_t *addrenv, uintptr_t vaddr) paddr = mm_pgalloc(1); if (paddr) { + /* Determine page table flags */ + + if (riscv_uservaddr(vaddr)) + { + flags = MMU_UPGT_FLAGS; + } + else + { + flags = MMU_KPGT_FLAGS; + } + /* Wipe the page and assign it */ riscv_pgwipe(paddr); - mmu_ln_setentry(ptlevel, ptprev, paddr, vaddr, MMU_UPGT_FLAGS); + mmu_ln_setentry(ptlevel, ptprev, paddr, vaddr, flags); } } diff --git a/arch/risc-v/src/common/riscv_mmu.h b/arch/risc-v/src/common/riscv_mmu.h index 0c0c6b5373749..6c9d1baebb997 100644 --- a/arch/risc-v/src/common/riscv_mmu.h +++ b/arch/risc-v/src/common/riscv_mmu.h @@ -59,6 +59,10 @@ #define MMU_IO_FLAGS (PTE_R | PTE_W | PTE_G) +/* Flags for kernel page tables */ + +#define MMU_KPGT_FLAGS (PTE_G) + /* Kernel FLASH and RAM are mapped globally */ #define MMU_KTEXT_FLAGS (PTE_R | PTE_X | PTE_G) From 7d4fbfb4d59d3d7a857ab7ba3ee26565df15b0d2 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Wed, 4 Oct 2023 15:57:29 +0300 Subject: [PATCH 109/138] riscv-v/pgalloc.h: Return kernel vaddr for kernel RAM paddr All kernel memory is mapped paddr=vaddr, so it is trivial to give mapping for kernel memory. Only interesting region should be kernel RAM, so omit kernel ROM and don't allow re-mapping it. --- arch/risc-v/src/common/pgalloc.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/risc-v/src/common/pgalloc.h b/arch/risc-v/src/common/pgalloc.h index 40da29805660b..be39da0d3a0d5 100644 --- a/arch/risc-v/src/common/pgalloc.h +++ b/arch/risc-v/src/common/pgalloc.h @@ -75,6 +75,10 @@ static inline uintptr_t riscv_pgvaddr(uintptr_t paddr) { return paddr - CONFIG_ARCH_PGPOOL_PBASE + CONFIG_ARCH_PGPOOL_VBASE; } + else if (paddr >= CONFIG_RAM_START && paddr < CONFIG_RAM_END) + { + return paddr - CONFIG_RAM_START + CONFIG_RAM_VSTART; + } return 0; } From 2a966a4702291903e61da2f1c65b467f295c20b2 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Mon, 2 Oct 2023 17:36:18 +0300 Subject: [PATCH 110/138] sched/assert.c: Print process name in assert dump In addition to printing out the thread name (task name in flat mode), print the parent process's name as well. It is quite useful to know which process is the parent of a faulting thread, although this information can be read from the assert dump, in some cases the dump might be incomplete (due to e.g. stack corruption, which causes another exception and PANIC().) --- sched/misc/assert.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sched/misc/assert.c b/sched/misc/assert.c index 1cbe45aef76b5..95ec7ce5a428a 100644 --- a/sched/misc/assert.c +++ b/sched/misc/assert.c @@ -553,11 +553,21 @@ void _assert(FAR const char *filename, int linenum, FAR const char *msg, FAR void *regs) { FAR struct tcb_s *rtcb = running_task(); +#if CONFIG_TASK_NAME_SIZE > 0 + FAR struct tcb_s *ptcb = NULL; +#endif struct panic_notifier_s notifier_data; struct utsname name; bool fatal = true; int flags; +#if CONFIG_TASK_NAME_SIZE > 0 + if (rtcb->group && !(rtcb->flags & TCB_FLAG_TTYPE_KERNEL)) + { + ptcb = nxsched_get_tcb(rtcb->group->tg_pid); + } +#endif + flags = enter_critical_section(); sched_lock(); @@ -602,6 +612,7 @@ void _assert(FAR const char *filename, int linenum, ": " #if CONFIG_TASK_NAME_SIZE > 0 "%s " + "process: %s " #endif "%p\n", msg ? msg : "", @@ -611,6 +622,7 @@ void _assert(FAR const char *filename, int linenum, #endif #if CONFIG_TASK_NAME_SIZE > 0 rtcb->name, + ptcb ? ptcb->name : "Kernel", #endif rtcb->entry.main); From 040d109a250532679b1dd6aeeaa83c552fe2423a Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Tue, 3 Oct 2023 12:51:36 +0300 Subject: [PATCH 111/138] kmm_map.c: Fix call to gran_alloc Provide the handle to gran_alloc, not pointer to handle. --- mm/kmap/kmm_map.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/kmap/kmm_map.c b/mm/kmap/kmm_map.c index 1312e6af0e31c..d6d1c6c9fa656 100644 --- a/mm/kmap/kmm_map.c +++ b/mm/kmap/kmm_map.c @@ -125,7 +125,7 @@ static FAR void *map_pages(FAR void **pages, size_t npages, int prot) /* Find a virtual memory area that fits */ - vaddr = gran_alloc(&g_kmm_map_vpages, size); + vaddr = gran_alloc(g_kmm_map_vpages, size); if (!vaddr) { return NULL; From 759228c5b3d3376c8e2d03ac5750e09a27f15c9d Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Tue, 3 Oct 2023 12:53:32 +0300 Subject: [PATCH 112/138] kmm_map.c: Fix user page mapping User pages are mapped from the currently active address environment. If the process is running on a borrowed address environment, then the mapping should be created from there. This happens during (new) process creation only. --- mm/kmap/kmm_map.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mm/kmap/kmm_map.c b/mm/kmap/kmm_map.c index d6d1c6c9fa656..4358ae57a6296 100644 --- a/mm/kmap/kmm_map.c +++ b/mm/kmap/kmm_map.c @@ -82,7 +82,7 @@ static int get_user_pages(FAR void **pages, size_t npages, uintptr_t vaddr) for (i = 0; i < npages; i++, vaddr += MM_PGSIZE) { - page = up_addrenv_find_page(&tcb->addrenv_own->addrenv, vaddr); + page = up_addrenv_find_page(&tcb->addrenv_curr->addrenv, vaddr); if (!page) { /* Something went wrong, get out */ @@ -182,7 +182,7 @@ static FAR void *map_single_user_page(uintptr_t vaddr) /* Find the page associated with this virtual address */ - page = up_addrenv_find_page(&tcb->addrenv_own->addrenv, vaddr); + page = up_addrenv_find_page(&tcb->addrenv_curr->addrenv, vaddr); if (!page) { return NULL; From 28b00d336ffdc283df2a3261b80f52b651273530 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Tue, 3 Oct 2023 12:55:24 +0300 Subject: [PATCH 113/138] kmm_map: Fix incorrect function name field --- arch/risc-v/src/common/riscv_addrenv_pgmap.c | 2 +- include/nuttx/arch.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/risc-v/src/common/riscv_addrenv_pgmap.c b/arch/risc-v/src/common/riscv_addrenv_pgmap.c index 9dbac8592fecc..edf9687649105 100644 --- a/arch/risc-v/src/common/riscv_addrenv_pgmap.c +++ b/arch/risc-v/src/common/riscv_addrenv_pgmap.c @@ -202,7 +202,7 @@ int up_addrenv_kmap_pages(void **pages, unsigned int npages, uintptr_t vaddr, } /**************************************************************************** - * Name: riscv_unmap_pages + * Name: up_addrenv_kunmap_pages * * Description: * Unmap a previously mapped virtual memory region. diff --git a/include/nuttx/arch.h b/include/nuttx/arch.h index 4a647afedb2af..9f4bdf78221ad 100644 --- a/include/nuttx/arch.h +++ b/include/nuttx/arch.h @@ -1352,7 +1352,7 @@ int up_addrenv_kmap_pages(FAR void **pages, unsigned int npages, #endif /**************************************************************************** - * Name: riscv_unmap_pages + * Name: up_addrenv_kunmap_pages * * Description: * Unmap a previously mapped virtual memory region. From 163398d9845167b386686e72ac86b907c8542c39 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Tue, 3 Oct 2023 13:33:41 +0300 Subject: [PATCH 114/138] kmm_map.c: Add way to test if addr is within kmap area or not is_kmap_vaddr is added and used to test that a given (v)addr is actually inside the kernel map area. This gives a speed optimization for kmm_unmap, as it is no longer necessary to take the mm_map_lock to check if such a mapping exists; obviously if the address is not within the kmap area, it won't be in the list either. --- mm/kmap/kmm_map.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/mm/kmap/kmm_map.c b/mm/kmap/kmm_map.c index 4358ae57a6296..1deb0f25cef1b 100644 --- a/mm/kmap/kmm_map.c +++ b/mm/kmap/kmm_map.c @@ -192,6 +192,26 @@ static FAR void *map_single_user_page(uintptr_t vaddr) return (FAR void *)vaddr; } +/**************************************************************************** + * Name: is_kmap_vaddr + * + * Description: + * Return true if the virtual address, vaddr, lies in the kmap address + * space. + * + * Input Parameters: + * vaddr - The kernel virtual address where the mapping begins. + * + * Returned Value: + * True if vaddr is in the kmap address space; false otherwise. + * + ****************************************************************************/ + +static bool is_kmap_vaddr(uintptr_t vaddr) +{ + return (vaddr >= CONFIG_ARCH_KMAP_VBASE && vaddr < ARCH_KMAP_VEND); +} + /**************************************************************************** * Name: kmm_map_lock * @@ -301,6 +321,15 @@ void kmm_unmap(FAR void *kaddr) unsigned int npages; int ret; + /* Speed optimization: check that addr is within kmap area */ + + if (!is_kmap_vaddr((uintptr_t)kaddr)) + { + /* Nope: get out */ + + return; + } + /* Lock the mapping list when we fiddle around with it */ ret = kmm_map_lock(); From 054ebd12bd031e98e9891e93c9308d119c68cd08 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Wed, 4 Oct 2023 15:58:15 +0300 Subject: [PATCH 115/138] kmm_map.c: Remember to free the temporary 'pages' variable The temp variable was freed only in error cases, but it needs to be freed in the happy case as well. --- mm/kmap/kmm_map.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/mm/kmap/kmm_map.c b/mm/kmap/kmm_map.c index 1deb0f25cef1b..ca94fe3bf05d2 100644 --- a/mm/kmap/kmm_map.c +++ b/mm/kmap/kmm_map.c @@ -377,7 +377,7 @@ void kmm_unmap(FAR void *kaddr) FAR void *kmm_map_user(FAR void *uaddr, size_t size) { - FAR void *pages; + FAR void **pages; uintptr_t vaddr; uintptr_t offset; size_t npages; @@ -414,7 +414,7 @@ FAR void *kmm_map_user(FAR void *uaddr, size_t size) /* No, the area must be mapped into kernel virtual address space */ - pages = kmm_zalloc(npages * sizeof(FAR void *)); + pages = (FAR void **)kmm_zalloc(npages * sizeof(FAR void *)); if (!pages) { return NULL; @@ -422,7 +422,7 @@ FAR void *kmm_map_user(FAR void *uaddr, size_t size) /* Fetch the physical pages for the user virtual address range */ - ret = get_user_pages(&pages, npages, vaddr); + ret = get_user_pages(pages, npages, vaddr); if (ret < 0) { goto errout_with_pages; @@ -430,7 +430,7 @@ FAR void *kmm_map_user(FAR void *uaddr, size_t size) /* Map the physical pages to kernel memory */ - vaddr = (uintptr_t)map_pages(&pages, npages, PROT_READ | PROT_WRITE); + vaddr = (uintptr_t)map_pages(pages, npages, PROT_READ | PROT_WRITE); if (!vaddr) { goto errout_with_pages; @@ -438,6 +438,7 @@ FAR void *kmm_map_user(FAR void *uaddr, size_t size) /* Ok, we have a virtual memory area, add the offset back */ + kmm_free(pages); return (FAR void *)(vaddr + offset); errout_with_pages: From 24b31ccee569bae288add548135d82809504b179 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Thu, 5 Oct 2023 15:33:03 +0300 Subject: [PATCH 116/138] kmm_map: Add function to map a single page of kernel memory Mapping a physical page to a kernel virtual page is very simple and does not need the kernel vma list, just get the kernel addressable virtual address for the page. --- mm/kmap/kmm_map.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/mm/kmap/kmm_map.c b/mm/kmap/kmm_map.c index ca94fe3bf05d2..cb270706f137b 100644 --- a/mm/kmap/kmm_map.c +++ b/mm/kmap/kmm_map.c @@ -192,6 +192,27 @@ static FAR void *map_single_user_page(uintptr_t vaddr) return (FAR void *)vaddr; } +/**************************************************************************** + * Name: map_single_page + * + * Description: + * Map (find) a single page from the kernel addressable virtual memory + * pool. + * + * Input Parameters: + * page - The physical page. + * + * Returned Value: + * The kernel virtual address for the page, or NULL if page is not kernel + * addressable. + * + ****************************************************************************/ + +static FAR void *map_single_page(uintptr_t page) +{ + return (FAR void *)up_addrenv_page_vaddr(page); +} + /**************************************************************************** * Name: is_kmap_vaddr * @@ -290,6 +311,13 @@ FAR void *kmm_map(FAR void **pages, size_t npages, int prot) return NULL; } + /* A single page can be addressed directly, if it is a kernel page */ + + if (npages == 1) + { + return map_single_page((uintptr_t)pages[0]); + } + /* Attempt to map the pages */ vaddr = (uintptr_t)map_pages(pages, npages, prot); From a3ceafc8ae10d2a58f3309d5543a016e423ce718 Mon Sep 17 00:00:00 2001 From: Eero Nurkkala Date: Thu, 12 Oct 2023 09:23:57 +0300 Subject: [PATCH 117/138] risc-v/mpfs/opensbi: update opensbi to version 1.3.1 Version 1.3.1 is the latest tagged version. This patch prepares the required changes to make v1.3.1 work. Signed-off-by: Eero Nurkkala --- arch/risc-v/src/mpfs/mpfs_opensbi.c | 51 ++++++++++++++++++++++------- arch/risc-v/src/opensbi/Make.defs | 11 +++++-- 2 files changed, 48 insertions(+), 14 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_opensbi.c b/arch/risc-v/src/mpfs/mpfs_opensbi.c index 7544ec493b503..aa1d069371463 100644 --- a/arch/risc-v/src/mpfs/mpfs_opensbi.c +++ b/arch/risc-v/src/mpfs/mpfs_opensbi.c @@ -106,6 +106,8 @@ typedef struct sbi_scratch_holder_s sbi_scratch_holder_t; extern const uint8_t __mpfs_nuttx_start[]; extern const uint8_t __mpfs_nuttx_end[]; +extern const uint8_t _ssbi_zerodev[]; +extern const uint8_t _esbi_zerodev[]; /**************************************************************************** * Private Function Prototypes @@ -118,8 +120,8 @@ static int mpfs_irqchip_init(bool cold_boot); static int mpfs_ipi_init(bool cold_boot); static int mpfs_timer_init(bool cold_boot); #ifdef CONFIG_MPFS_IHC_SBI -static int mpfs_opensbi_vendor_ext_check(long extid); -static int mpfs_opensbi_ecall_handler(long extid, long funcid, +static bool mpfs_opensbi_vendor_ext_check(void); +static int mpfs_opensbi_ecall_handler(long funcid, const struct sbi_trap_regs *regs, unsigned long *out_val, struct sbi_trap_info *out_trap); @@ -170,7 +172,7 @@ static struct aclint_mtimer_data mpfs_mtimer = .mtimecmp_size = ACLINT_DEFAULT_MTIMECMP_SIZE, .first_hartid = 0, .hart_count = MPFS_HART_COUNT, - .has_64bit_mmio = TRUE, + .has_64bit_mmio = true, }; static const struct sbi_platform_operations platform_ops = @@ -476,9 +478,35 @@ static void mpfs_opensbi_scratch_setup(uint32_t hartid) * them so that OpenSBI has no chance override then. */ - g_scratches[hartid].scratch.fw_start = (unsigned long)__mpfs_nuttx_start; - g_scratches[hartid].scratch.fw_size = (unsigned long)__mpfs_nuttx_end - - (unsigned long)__mpfs_nuttx_start; + g_scratches[hartid].scratch.fw_start = (unsigned long)_ssbi_zerodev; + g_scratches[hartid].scratch.fw_size = (unsigned long)_esbi_zerodev - + (unsigned long)_ssbi_zerodev; + + g_scratches[hartid].scratch.fw_rw_offset = + (unsigned long)g_scratches[hartid].scratch.fw_size; + + /* fw_rw_offset needs to be an aligned address */ + + g_scratches[hartid].scratch.fw_rw_offset += 1024 * 2; + g_scratches[hartid].scratch.fw_rw_offset &= 0xffffff800; + g_scratches[hartid].scratch.fw_size = + g_scratches[hartid].scratch.fw_rw_offset; + + g_scratches[hartid].scratch.fw_heap_offset = + (unsigned long)g_scratches[hartid].scratch.fw_size; + + /* Heap minimum is 16k. Otherwise sbi_heap.c fails: + * hpctrl.hksize = hpctrl.size / HEAP_HOUSEKEEPING_FACTOR; + * hpctrl.hksize &= ~((unsigned long)HEAP_BASE_ALIGN - 1); + * eg. 8k: (0x2000 / 16) & ~(1024 - 1) = 0 (Fail!) + * 16k: (0x4000 / 16) & ~(1024 - 1) = 0x400 (Ok) + * hpctrl.hksize gets to be zero making the OpenSBI crash. + */ + + g_scratches[hartid].scratch.fw_heap_size = 1024 * 16; + g_scratches[hartid].scratch.fw_size = + g_scratches[hartid].scratch.fw_heap_offset + + g_scratches[hartid].scratch.fw_heap_size; } /**************************************************************************** @@ -509,10 +537,10 @@ static void mpfs_opensbi_pmp_setup(void) * Name: mpfs_opensbi_vendor_ext_check * * Description: - * Used by the OpenSBI in vendor probe to check the vendor ID. + * Used by the OpenSBI to check if vendor extension is enabled. * * Input Parameters: - * extid - Vendor ID to be checked + * None * * Returned Value: * 1 on match, zero in case of no match @@ -520,9 +548,9 @@ static void mpfs_opensbi_pmp_setup(void) ****************************************************************************/ #ifdef CONFIG_MPFS_IHC_SBI -static int mpfs_opensbi_vendor_ext_check(long extid) +static bool mpfs_opensbi_vendor_ext_check(void) { - return (SBI_EXT_MICROCHIP_TECHNOLOGY == extid); + return true; } /**************************************************************************** @@ -533,7 +561,6 @@ static int mpfs_opensbi_vendor_ext_check(long extid) * related to Inter-Hart Communication (IHC). * * Input Parameters: - * extid - Vendor ID * funcid - One of the valid functions * sbi_trap_regs - SBI trap registers * out_val - Error code location @@ -544,7 +571,7 @@ static int mpfs_opensbi_vendor_ext_check(long extid) * ****************************************************************************/ -static int mpfs_opensbi_ecall_handler(long extid, long funcid, +static int mpfs_opensbi_ecall_handler(long funcid, const struct sbi_trap_regs *regs, unsigned long *out_val, struct sbi_trap_info *out_trap) diff --git a/arch/risc-v/src/opensbi/Make.defs b/arch/risc-v/src/opensbi/Make.defs index b7d0ca61e232d..c893e17a0a28f 100644 --- a/arch/risc-v/src/opensbi/Make.defs +++ b/arch/risc-v/src/opensbi/Make.defs @@ -28,6 +28,12 @@ SBI_CSRCS += opensbi/opensbi-3rdparty/lib/utils/ipi/aclint_mswi.c SBI_CSRCS += opensbi/opensbi-3rdparty/lib/utils/irqchip/plic.c SBI_CSRCS += opensbi/opensbi-3rdparty/lib/utils/timer/aclint_mtimer.c +EXCLUDED_FILES = opensbi/opensbi-3rdparty/lib/sbi/sbi_pmu.c +EXCLUDED_FILES += opensbi/opensbi-3rdparty/lib/sbi/sbi_ecall_dbcn.c + +TMPVAR := $(SBI_CSRCS) +SBI_CSRCS = $(filter-out $(EXCLUDED_FILES), $(TMPVAR)) + SBI_ASRCS += opensbi/opensbi-3rdparty/lib/sbi/sbi_expected_trap.S SBI_ASRCS += opensbi/opensbi-3rdparty/lib/sbi/sbi_hfence.S SBI_ASRCS += opensbi/opensbi-3rdparty/lib/sbi/riscv_hardfp.S @@ -37,10 +43,10 @@ INCLUDES += ${INCDIR_PREFIX}$(ARCH_SRCDIR)$(DELIM)opensbi$(DELIM)opensbi-3rdpar SBI_DIR := opensbi OPENSBI_UNPACK = opensbi-3rdparty -OPENSBI_COMMIT = a082fb83f218a647d2009b565e573dac8f179cb9 +OPENSBI_COMMIT = fbaaafe808f3da7745760d757c436ef1b293d3ed OPENSBI_URL = https://github.com/tiiuae/opensbi/tarball OPENSBI_TARBALL = opensbi.tar.gz -OPENSBI_DIR = tiiuae-opensbi-a082fb8 +OPENSBI_DIR = tiiuae-opensbi-fbaaafe $(OPENSBI_TARBALL): $(call DOWNLOAD,$(OPENSBI_URL),$(OPENSBI_COMMIT),opensbi/$(OPENSBI_TARBALL)) @@ -50,6 +56,7 @@ $(OPENSBI_TARBALL): $(Q) tar xzf opensbi/$(OPENSBI_TARBALL) -C opensbi $(Q) mv opensbi/$(OPENSBI_DIR) opensbi/$(OPENSBI_UNPACK) $(Q) touch opensbi/.opensbi_unpack + $(Q) opensbi/$(OPENSBI_UNPACK)/scripts/carray.sh -i opensbi/$(OPENSBI_UNPACK)/lib/sbi/sbi_ecall_exts.carray -l "ecall_base ecall_hsm ecall_ipi ecall_rfence ecall_time ecall_vendor" > opensbi/$(OPENSBI_UNPACK)/lib/sbi/sbi_ecall_exts.c ifeq ($(wildcard opensbi/$(OPENSBI_UNPACK)/.git),) context:: .opensbi_unpack From df1d24c9bab7abbce05cf0fec0655bf07bed2f52 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Wed, 11 Oct 2023 14:11:40 +0300 Subject: [PATCH 118/138] mpfs/mpfs_entrypoints.c: Fix potential R_RISCV_JAL linker error Change bgtz t0, mpfs_opensbi_prepare_hart to tail-call to ensure there will be no link time error due to the jump offset being too large. --- arch/risc-v/src/mpfs/mpfs_entrypoints.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/risc-v/src/mpfs/mpfs_entrypoints.c b/arch/risc-v/src/mpfs/mpfs_entrypoints.c index 7847a62aefc09..b6ee0a72115ea 100644 --- a/arch/risc-v/src/mpfs/mpfs_entrypoints.c +++ b/arch/risc-v/src/mpfs/mpfs_entrypoints.c @@ -92,7 +92,9 @@ void mpfs_jump_to_app(void) "ld t0, g_hart_use_sbi\n" /* Load sbi usage bitmask */ "srl t0, t0, a0\n" /* Shift right by this hart */ "andi t0, t0, 1\n" /* Check the 0 bit */ - "bgtz t0, mpfs_opensbi_prepare_hart\n" /* If bit was 1, jump to sbi */ + "beqz t0, 1f\n" /* If bit was 1, jump to sbi */ + "tail mpfs_opensbi_prepare_hart\n" + "1:\n" #endif "slli t1, a0, 3\n" /* To entrypoint offset */ "la t0, g_app_entrypoints\n" /* Entrypoint table base */ From b53ad83fc924cfe80799ba664b101c363abf0a9e Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Mon, 16 Oct 2023 13:18:03 +0300 Subject: [PATCH 119/138] mpfs_ethernet.c: Fix possible NULL de-reference Fix case where NULL is de-referenced via tx/rx buffer or descriptor. Only 1 queue is currently set up for each, so the indices 1,2,3 are not valid and should not be handled. --- arch/risc-v/src/mpfs/mpfs_ethernet.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/risc-v/src/mpfs/mpfs_ethernet.c b/arch/risc-v/src/mpfs/mpfs_ethernet.c index 8fcc8f6129a3d..7f5b7368cd80c 100644 --- a/arch/risc-v/src/mpfs/mpfs_ethernet.c +++ b/arch/risc-v/src/mpfs/mpfs_ethernet.c @@ -1194,6 +1194,13 @@ static void mpfs_txreset(struct mpfs_ethmac_s *priv) priv->queue[qi].txhead = 0; priv->queue[qi].txtail = 0; + if (!txdesc || !txbuffer) + { + /* The queue index is not set up */ + + continue; + } + for (ndx = 0; ndx < CONFIG_MPFS_ETHMAC_NTXBUFFERS; ndx++) { bufaddr = (uintptr_t)&txbuffer[ndx * GMAC_TX_UNITSIZE]; @@ -1269,6 +1276,13 @@ static void mpfs_rxreset(struct mpfs_ethmac_s *priv) rxdesc = priv->queue[qi].rx_desc_tab; priv->queue[qi].rxndx = 0; + if (!rxdesc || !rxbuffer) + { + /* The queue index is not set up */ + + continue; + } + for (ndx = 0; ndx < CONFIG_MPFS_ETHMAC_NRXBUFFERS; ndx++) { bufaddr = (uintptr_t)&rxbuffer[ndx * GMAC_RX_UNITSIZE]; From 7e809980f7fffea2b8393170fd4fa49970576176 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Mon, 16 Oct 2023 13:19:13 +0300 Subject: [PATCH 120/138] mpfs_ethernet.c: Release tx descriptor and rx buffer properly Instead of releasing rx descriptor twice and tx buffer twice. --- arch/risc-v/src/mpfs/mpfs_ethernet.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_ethernet.c b/arch/risc-v/src/mpfs/mpfs_ethernet.c index 7f5b7368cd80c..c15d83c4cec87 100644 --- a/arch/risc-v/src/mpfs/mpfs_ethernet.c +++ b/arch/risc-v/src/mpfs/mpfs_ethernet.c @@ -2830,10 +2830,10 @@ static void mpfs_buffer_free(struct mpfs_ethmac_s *priv, unsigned int queue) #ifndef CONFIG_MPFS_GMAC_PREALLOCATE /* Free allocated buffers */ - if (priv->queue[queue].rx_desc_tab != NULL) + if (priv->queue[queue].tx_desc_tab != NULL) { - kmm_free(priv->queue[queue].rx_desc_tab); - priv->queue[queue].rx_desc_tab = NULL; + kmm_free(priv->queue[queue].tx_desc_tab); + priv->queue[queue].tx_desc_tab = NULL; } if (priv->queue[queue].rx_desc_tab != NULL) @@ -2848,10 +2848,10 @@ static void mpfs_buffer_free(struct mpfs_ethmac_s *priv, unsigned int queue) priv->queue[queue].txbuffer = NULL; } - if (priv->queue[queue].txbuffer != NULL) + if (priv->queue[queue].rxbuffer != NULL) { - kmm_free(priv->queue[queue].txbuffer); - priv->queue[queue].txbuffer = NULL; + kmm_free(priv->queue[queue].rxbuffer); + priv->queue[queue].rxbuffer = NULL; } #endif } From 38666348f01f954c45615298053be9c5680f4f6b Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Wed, 11 Oct 2023 16:37:29 +0300 Subject: [PATCH 121/138] mpfs_head.S: Simplify clearing PMP Initially clear PMP for all harts, this fixes random warm reset issues. Signed-off-by: Ville Juven --- arch/risc-v/src/mpfs/mpfs_head.S | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_head.S b/arch/risc-v/src/mpfs/mpfs_head.S index 465cf1f0f60a5..50dd2709226d4 100644 --- a/arch/risc-v/src/mpfs/mpfs_head.S +++ b/arch/risc-v/src/mpfs/mpfs_head.S @@ -129,6 +129,10 @@ __start: .option pop #ifdef CONFIG_MPFS_BOOTLOADER + /* Clear PMP */ + + csrw pmpcfg0, zero + csrw pmpcfg2, zero /* Set all but the boot hart into wfi */ @@ -175,11 +179,6 @@ __start: sd x0, 0(a4) add a4, a4, 8 blt a4, a5, .clear_l2lim - - /* Clear PMP */ - - csrw pmpcfg0, zero - csrw pmpcfg2, zero #endif /* Set stack pointer to the idle thread stack */ From a96473f3350e041c53d954d72cae04d33194d9c7 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Tue, 10 Oct 2023 13:29:41 +0300 Subject: [PATCH 122/138] arch/risc-v/src/mpfs/mpfs_ddr.c: Add read dq/dqs eye centering test After read training, check also that the eye is centered properly. Sometimes after the training the width is long enough, but it is not centered. Signed-off-by: Jukka Laitinen --- arch/risc-v/src/mpfs/mpfs_ddr.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_ddr.c b/arch/risc-v/src/mpfs/mpfs_ddr.c index d4b2f43252ca2..12015c57bae25 100644 --- a/arch/risc-v/src/mpfs/mpfs_ddr.c +++ b/arch/risc-v/src/mpfs/mpfs_ddr.c @@ -3415,6 +3415,8 @@ static int mpfs_training_verify(void) uint32_t lane_sel; uint32_t last; uint32_t i; + uint32_t off_taps; + uint32_t width_taps; while (!(getreg32(MPFS_DDR_CSR_APB_STAT_DFI_TRAINING_COMPLETE) & 0x01) && --retries); @@ -3502,9 +3504,15 @@ static int mpfs_training_verify(void) t_status |= 0x01; } - /* Check that DQ/DQS calculated window is above 5 taps. */ + /* Check that DQ/DQS calculated window is above 5 taps + * and centered with margin + */ + + off_taps = getreg32(MPFS_CFG_DDR_SGMII_PHY_DQDQS_STATUS1); + width_taps = getreg32(MPFS_CFG_DDR_SGMII_PHY_DQDQS_STATUS2); - if (getreg32(MPFS_CFG_DDR_SGMII_PHY_DQDQS_STATUS2) < DQ_DQS_NUM_TAPS) + if (width_taps < DQ_DQS_NUM_TAPS || + width_taps + off_taps <= 16 + DQ_DQS_NUM_TAPS / 2) { t_status |= 0x01; } From 38a04e3e2ecc4ba561466ffeb33cb1470abd3b11 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Wed, 11 Oct 2023 12:59:44 +0300 Subject: [PATCH 123/138] arch/risc-v/src/mpfs/mpfs_ddr.c: Clean up the TXDLY verify step Just verify that the delay for the selected clock != 0 Signed-off-by: Jukka Laitinen --- arch/risc-v/src/mpfs/mpfs_ddr.c | 44 ++++----------------------------- 1 file changed, 5 insertions(+), 39 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_ddr.c b/arch/risc-v/src/mpfs/mpfs_ddr.c index 12015c57bae25..0d0fb6710045a 100644 --- a/arch/risc-v/src/mpfs/mpfs_ddr.c +++ b/arch/risc-v/src/mpfs/mpfs_ddr.c @@ -3417,6 +3417,7 @@ static int mpfs_training_verify(void) uint32_t i; uint32_t off_taps; uint32_t width_taps; + uint32_t gt_clk_sel; while (!(getreg32(MPFS_DDR_CSR_APB_STAT_DFI_TRAINING_COMPLETE) & 0x01) && --retries); @@ -3519,47 +3520,12 @@ static int mpfs_training_verify(void) /* Extra checks */ - uint32_t temp = 0; - uint32_t gt_clk_sel = getreg32(MPFS_CFG_DDR_SGMII_PHY_GT_CLK_SEL) & - 0x03; + /* Check the GT_TXDLY result for the selected clock */ - if ((getreg32(MPFS_CFG_DDR_SGMII_PHY_GT_TXDLY) & 0xff) == 0) - { - temp++; - if (gt_clk_sel == 0) - { - t_status |= 0x01; - } - } - - if (((getreg32(MPFS_CFG_DDR_SGMII_PHY_GT_TXDLY) >> 8) & 0xff) == 0) - { - temp++; - if (gt_clk_sel == 1) - { - t_status |= 0x01; - } - } - - if (((getreg32(MPFS_CFG_DDR_SGMII_PHY_GT_TXDLY) >> 16) & 0xff) == 0) - { - temp++; - if (gt_clk_sel == 2) - { - t_status |= 0x01; - } - } - - if (((getreg32(MPFS_CFG_DDR_SGMII_PHY_GT_TXDLY) >> 24) & 0xff) == 0) - { - temp++; - if (gt_clk_sel == 3) - { - t_status |= 0x01; - } - } + gt_clk_sel = getreg32(MPFS_CFG_DDR_SGMII_PHY_GT_CLK_SEL) & 0x03; - if (temp > 1) + if (((getreg32(MPFS_CFG_DDR_SGMII_PHY_GT_TXDLY) >> (gt_clk_sel * 8)) & + 0xff) == 0) { t_status |= 0x01; } From c266572045f3a5c2e6cc614f02a7eab4fb398a19 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Wed, 11 Oct 2023 12:38:12 +0300 Subject: [PATCH 124/138] arch/risc-v/src/mpfs/mpfs_ddr.c: Fix CA training verify step Corrections to CA training verify step. The original copied from HSS didn't make sense in all aspects: - The check is not per lane, so it should be out of the "for (lane_sel" loop. - The check wasn't proper. The expected outcome is just a vector of increasing numbers separated enough Signed-off-by: Jukka Laitinen --- arch/risc-v/src/mpfs/mpfs_ddr.c | 69 +++++++++++++-------------------- 1 file changed, 27 insertions(+), 42 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_ddr.c b/arch/risc-v/src/mpfs/mpfs_ddr.c index 0d0fb6710045a..6f211e47cacf3 100644 --- a/arch/risc-v/src/mpfs/mpfs_ddr.c +++ b/arch/risc-v/src/mpfs/mpfs_ddr.c @@ -99,8 +99,6 @@ /* Retraining limits */ -#define ABNORMAL_RETRAIN_CA_DECREASE_COUNT 2 -#define ABNORMAL_RETRAIN_CA_DLY_DECREASE_COUNT 2 #define DQ_DQS_NUM_TAPS 5 /* PLL convenience bits */ @@ -3406,14 +3404,11 @@ static int mpfs_training_addcmd(void) static int mpfs_training_verify(void) { - uint32_t low_ca_dly_count; - uint32_t decrease_count; uint32_t addcmd_status0; uint32_t addcmd_status1; uint32_t retries = MPFS_DEFAULT_RETRIES; uint32_t t_status = 0; uint32_t lane_sel; - uint32_t last; uint32_t i; uint32_t off_taps; uint32_t width_taps; @@ -3428,19 +3423,15 @@ static int mpfs_training_verify(void) return -ETIMEDOUT; } - for (lane_sel = 0; lane_sel < LIBERO_SETTING_DATA_LANES_USED; lane_sel++) - { - mpfs_wait_cycles(10); - - putreg32(lane_sel, MPFS_CFG_DDR_SGMII_PHY_LANE_SELECT); - mpfs_wait_cycles(10); + /* Verify cmd address results, rejects if not acceptable */ - /* Verify cmd address results, rejects if not acceptable */ + addcmd_status0 = getreg32(MPFS_CFG_DDR_SGMII_PHY_ADDCMD_STATUS0); + addcmd_status1 = getreg32(MPFS_CFG_DDR_SGMII_PHY_ADDCMD_STATUS1); - addcmd_status0 = getreg32(MPFS_CFG_DDR_SGMII_PHY_ADDCMD_STATUS0); - addcmd_status1 = getreg32(MPFS_CFG_DDR_SGMII_PHY_ADDCMD_STATUS1); - - uint32_t ca_status[8] = + if ((LIBERO_SETTING_TRAINING_SKIP_SETTING & ADDCMD_BIT) != ADDCMD_BIT) + { + unsigned low_ca_dly_count = 0; + uint8_t ca_status[8] = { ((addcmd_status0) & 0xff), ((addcmd_status0 >> 8) & 0xff), @@ -3452,46 +3443,40 @@ static int mpfs_training_verify(void) ((addcmd_status1 >> 24) & 0xff) }; - low_ca_dly_count = 0; - last = 0; - decrease_count = 0; + uint8_t last = ca_status[7]; + + /* Retrain if abnormal CA training result detected + * Expected result is increasing numbers, starting at index n and + * wrapping around. For example: + * [0x35, 0x3b, 0x4, 0x14, 0x1b, 0x21, 0x28, 0x2f]. + * + * Also they need to be separated by at least 5 + */ for (i = 0; i < 8; i++) { - if (ca_status[i] < 5) + if (ca_status[i] < last + 5) { low_ca_dly_count++; } - if (ca_status[i] <= last) - { - decrease_count++; - } - last = ca_status[i]; } - if (ca_status[0] <= ca_status[7]) + if (low_ca_dly_count > 1) { - decrease_count++; - } + /* Retrain via reset */ - if ((LIBERO_SETTING_TRAINING_SKIP_SETTING & ADDCMD_BIT) != ADDCMD_BIT) - { - /* Retrain if abnormal CA training result detected */ - - if (low_ca_dly_count > ABNORMAL_RETRAIN_CA_DLY_DECREASE_COUNT) - { - t_status |= 0x01; - } + return -EIO; + } + } - /* Retrain if abnormal CA training result detected */ + for (lane_sel = 0; lane_sel < LIBERO_SETTING_DATA_LANES_USED; lane_sel++) + { + mpfs_wait_cycles(10); - if (decrease_count > ABNORMAL_RETRAIN_CA_DECREASE_COUNT) - { - t_status |= 0x01; - } - } + putreg32(lane_sel, MPFS_CFG_DDR_SGMII_PHY_LANE_SELECT); + mpfs_wait_cycles(10); /* Check that gate training passed without error */ From 4e4a88e7010e669c6cbc65265989435c15b54395 Mon Sep 17 00:00:00 2001 From: Eero Nurkkala Date: Wed, 20 Sep 2023 15:18:20 +0300 Subject: [PATCH 125/138] riscv/riscv_pmp.c: fix broken TOR checks PMPCFG_A_TOR region may have zero size. The pmp configuration currently fails for zero-sized TOR. This patch bypasses such a restriction. Also replace log2ceil with LOG2_CEIL from lib/math32.h. Signed-off-by: Eero Nurkkala --- arch/risc-v/src/common/riscv_pmp.c | 31 +++--------------------------- 1 file changed, 3 insertions(+), 28 deletions(-) diff --git a/arch/risc-v/src/common/riscv_pmp.c b/arch/risc-v/src/common/riscv_pmp.c index bf0b19a210f9c..652a6d56142df 100644 --- a/arch/risc-v/src/common/riscv_pmp.c +++ b/arch/risc-v/src/common/riscv_pmp.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "riscv_internal.h" @@ -100,32 +101,6 @@ typedef struct pmp_entry_s pmp_entry_t; * Private Functions ****************************************************************************/ -/**************************************************************************** - * Name: log2ceil - * - * Description: - * Calculate the up-rounded power-of-two for input. - * - * Input Parameters: - * size - The size of the PMP region. - * - * Returned Value: - * Power-of-two for argument, rounded up. - * - ****************************************************************************/ - -static uintptr_t log2ceil(uintptr_t size) -{ - uintptr_t pot = 0; - - for (size = size - 1; size > 1; size >>= 1) - { - pot++; - } - - return pot; -} - /**************************************************************************** * Name: pmp_check_addrmatch_type * @@ -191,7 +166,7 @@ static bool pmp_check_region_attrs(uintptr_t base, uintptr_t size, { /* Check that the size is not too small */ - if (size < MIN_BLOCK_SIZE) + if ((type != PMPCFG_A_TOR) && (size < MIN_BLOCK_SIZE)) { return false; } @@ -216,7 +191,7 @@ static bool pmp_check_region_attrs(uintptr_t base, uintptr_t size, { /* Get the power-of-two for size, rounded up */ - uintptr_t pot = log2ceil(size); + uintptr_t pot = LOG2_CEIL(size); if ((base & ((UINT64_C(1) << pot) - 1)) != 0) { From 76d2bd6d771639b7120b4ec8db159ec3f749d899 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Mon, 23 Oct 2023 15:47:06 +0300 Subject: [PATCH 126/138] arch/risc-v: Remove unnecessary PMP kconfig options These options are just wrong and a result of misunderstanding of the Polarfire SoC spec. There are no feature limitations in the CPU PMP implementation -> remove any configuration options added. --- arch/risc-v/Kconfig | 24 ------------- arch/risc-v/src/common/riscv_pmp.c | 56 ------------------------------ arch/risc-v/src/mpfs/Kconfig | 14 -------- 3 files changed, 94 deletions(-) diff --git a/arch/risc-v/Kconfig b/arch/risc-v/Kconfig index a0ded26b0bda8..8467895753889 100644 --- a/arch/risc-v/Kconfig +++ b/arch/risc-v/Kconfig @@ -149,7 +149,6 @@ config ARCH_CHIP_MPFS select ARCH_HAVE_SPI_CS_CONTROL select ARCH_HAVE_PWM_MULTICHAN select ARCH_HAVE_S_MODE - select PMP_HAS_LIMITED_FEATURES select ONESHOT select ALARM_ARCH ---help--- @@ -321,29 +320,6 @@ config ARCH_USE_S_MODE and/or U-mode (in case of separate kernel-/userspaces). This provides an option to run the kernel in S-mode, if the target supports it. -# MPU has certain architecture dependent configurations, which are presented -# here. Default is that the full RISC-V PMP specification is supported. - -config PMP_HAS_LIMITED_FEATURES - bool - default n - -config ARCH_MPU_MIN_BLOCK_SIZE - int "Minimum MPU (PMP) block size" - default 4 if !PMP_HAS_LIMITED_FEATURES - -config ARCH_MPU_HAS_TOR - bool "PMP supports TOR" - default y if !PMP_HAS_LIMITED_FEATURES - -config ARCH_MPU_HAS_NO4 - bool "PMP supports NO4" - default y if !PMP_HAS_LIMITED_FEATURES - -config ARCH_MPU_HAS_NAPOT - bool "PMP supports NAPOT" - default y if !PMP_HAS_LIMITED_FEATURES - choice prompt "Toolchain Selection" default RISCV_TOOLCHAIN_GNU_RV64 diff --git a/arch/risc-v/src/common/riscv_pmp.c b/arch/risc-v/src/common/riscv_pmp.c index 652a6d56142df..302c60338cd0b 100644 --- a/arch/risc-v/src/common/riscv_pmp.c +++ b/arch/risc-v/src/common/riscv_pmp.c @@ -50,11 +50,7 @@ /* Minimum supported block size */ -#if !defined CONFIG_ARCH_MPU_MIN_BLOCK_SIZE #define MIN_BLOCK_SIZE (PMP_XLEN / 8) -#else -#define MIN_BLOCK_SIZE CONFIG_ARCH_MPU_MIN_BLOCK_SIZE -#endif /* Address and block size alignment mask */ @@ -101,51 +97,6 @@ typedef struct pmp_entry_s pmp_entry_t; * Private Functions ****************************************************************************/ -/**************************************************************************** - * Name: pmp_check_addrmatch_type - * - * Description: - * Test if an address matching type is supported by the architecture. - * - * Input Parameters: - * type - The type to test. - * - * Returned Value: - * true if it is, false otherwise. - * - ****************************************************************************/ - -static bool pmp_check_addrmatch_type(uintptr_t type) -{ - /* Parameter is potentially unused */ - - UNUSED(type); -#ifdef CONFIG_ARCH_MPU_HAS_TOR - if (type == PMPCFG_A_TOR) - { - return true; - } - -#endif -#ifdef CONFIG_ARCH_MPU_HAS_NO4 - if (type == PMPCFG_A_NA4) - { - return true; - } - -#endif -#ifdef CONFIG_ARCH_MPU_HAS_NAPOT - if (type == PMPCFG_A_NAPOT) - { - return true; - } -#endif - - /* None of the supported types match */ - - return false; -} - /**************************************************************************** * Name: pmp_check_region_attrs * @@ -464,13 +415,6 @@ int riscv_config_pmp_region(uintptr_t region, uintptr_t attr, uintptr_t cfg = 0; uintptr_t type = (attr & PMPCFG_A_MASK); - /* Check that the architecture supports address matching type */ - - if (pmp_check_addrmatch_type(type) == false) - { - return -EINVAL; - } - /* Check the region attributes */ if (pmp_check_region_attrs(base, size, type) == false) diff --git a/arch/risc-v/src/mpfs/Kconfig b/arch/risc-v/src/mpfs/Kconfig index 59d28920f5808..64ff2bff28329 100644 --- a/arch/risc-v/src/mpfs/Kconfig +++ b/arch/risc-v/src/mpfs/Kconfig @@ -893,20 +893,6 @@ config MPFS_CORERMII_ADDRESS default 1 depends on MPFS_HAVE_CORERMII -# Override the default values for MPU / PMP parameters here - -config ARCH_MPU_MIN_BLOCK_SIZE - default 4096 - -config ARCH_MPU_HAS_TOR - default n - -config ARCH_MPU_HAS_NO4 - default n - -config ARCH_MPU_HAS_NAPOT - default y - config MPFS_CRYPTO bool "Enable MPFS HW crypto" default n From 076f358c2e8be8ea6dc7d61b094eae52a157cc64 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Mon, 23 Oct 2023 15:50:00 +0300 Subject: [PATCH 127/138] arch/risc-v: Simplify pmp_check_region_attrs sanity-checks For TOR: Any size and 4-byte aligned address is required For NA4: Only size 4 and 4-byte aligned address is good For NAPOT: Minimum size is 8 bytes, minimum base alignment is 8 bytes, and size must be power-of-two aligned with base This commit simplifies these checks and removes all the nonsense added by a misunderstanding of how the MPFS / Polarfire SoC's PMP works. --- arch/risc-v/src/common/riscv_pmp.c | 73 ++++++++++++++++-------------- 1 file changed, 39 insertions(+), 34 deletions(-) diff --git a/arch/risc-v/src/common/riscv_pmp.c b/arch/risc-v/src/common/riscv_pmp.c index 302c60338cd0b..2f63c2596db6d 100644 --- a/arch/risc-v/src/common/riscv_pmp.c +++ b/arch/risc-v/src/common/riscv_pmp.c @@ -48,14 +48,6 @@ #define PMP_XLEN (64) #endif -/* Minimum supported block size */ - -#define MIN_BLOCK_SIZE (PMP_XLEN / 8) - -/* Address and block size alignment mask */ - -#define BLOCK_ALIGN_MASK (MIN_BLOCK_SIZE - 1) - #define PMP_CFG_BITS_CNT (8) #define PMP_CFG_FLAG_MASK ((uintptr_t)0xFF) @@ -106,6 +98,7 @@ typedef struct pmp_entry_s pmp_entry_t; * Input Parameters: * base - The base address of the region. * size - The memory length of the region. + * type - Address matching type. * * Returned Value: * true if it is, false otherwise. @@ -115,42 +108,54 @@ typedef struct pmp_entry_s pmp_entry_t; static bool pmp_check_region_attrs(uintptr_t base, uintptr_t size, uintptr_t type) { - /* Check that the size is not too small */ + switch (type) + { + case PMPCFG_A_TOR: - if ((type != PMPCFG_A_TOR) && (size < MIN_BLOCK_SIZE)) - { - return false; - } + /* For TOR any size is good, but alignment requirement stands */ - /* Check that the base address is aligned properly */ + if ((base & 0x03) != 0) + { + return false; + } - if ((base & BLOCK_ALIGN_MASK) != 0) - { - return false; - } + break; - /* Check that the size is aligned properly */ + case PMPCFG_A_NA4: - if ((size & BLOCK_ALIGN_MASK) != 0) - { - return false; - } + /* For NA4 only size 4 is good, and base must be aligned */ + + if ((base & 0x03) != 0 || size != 4) + { + return false; + } - /* Perform additional checks on base and size for NAPOT area */ + break; - if (type == PMPCFG_A_NAPOT) - { - /* Get the power-of-two for size, rounded up */ + case PMPCFG_A_NAPOT: + { + /* For NAPOT, both base and size must be properly aligned */ - uintptr_t pot = LOG2_CEIL(size); + if ((base & 0x07) != 0 || size < 8) + { + return false; + } - if ((base & ((UINT64_C(1) << pot) - 1)) != 0) - { - /* The start address is not properly aligned with size */ + /* Get the power-of-two for size, rounded up */ - return false; - } - } + if ((base & ((UINT64_C(1) << LOG2_CEIL(size)) - 1)) != 0) + { + /* The start address is not properly aligned with size */ + + return false; + } + } + + break; + + default: + break; + } return true; } From cb8392fe5111747a6e69f822ba84035585162a5b Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Tue, 10 Oct 2023 10:36:39 +0300 Subject: [PATCH 128/138] mpfs_opensbi: Remove mpfs_opensbi_pmp_setup The PMP setup should be done in the board specific code, at a much earlier stage. Granting all access is a security risk anyway. --- arch/risc-v/src/mpfs/mpfs_opensbi.c | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_opensbi.c b/arch/risc-v/src/mpfs/mpfs_opensbi.c index aa1d069371463..cb6a66837bbc0 100644 --- a/arch/risc-v/src/mpfs/mpfs_opensbi.c +++ b/arch/risc-v/src/mpfs/mpfs_opensbi.c @@ -75,9 +75,6 @@ #define MPFS_ACLINT_MSWI_ADDR MPFS_CLINT_MSIP0 #define MPFS_ACLINT_MTIMER_ADDR MPFS_CLINT_MTIMECMP0 -#define MPFS_PMP_DEFAULT_ADDR 0xfffffffff -#define MPFS_PMP_DEFAULT_PERM 0x000000009f - #define MPFS_SYSREG_SOFT_RESET_CR (MPFS_SYSREG_BASE + \ MPFS_SYSREG_SOFT_RESET_CR_OFFSET) #define MPFS_SYSREG_SUBBLK_CLOCK_CR (MPFS_SYSREG_BASE + \ @@ -509,30 +506,6 @@ static void mpfs_opensbi_scratch_setup(uint32_t hartid) g_scratches[hartid].scratch.fw_heap_size; } -/**************************************************************************** - * Name: mpfs_opensbi_pmp_setup - * - * Description: - * Initializes the PMP registers in a known default state. All harts need - * to set these registers. - * - * Input Parameters: - * None - * - * Returned Value: - * None - * - ****************************************************************************/ - -static void mpfs_opensbi_pmp_setup(void) -{ - /* All access granted */ - - csr_write(pmpaddr0, MPFS_PMP_DEFAULT_ADDR); - csr_write(pmpcfg0, MPFS_PMP_DEFAULT_PERM); - csr_write(pmpcfg2, 0); -} - /**************************************************************************** * Name: mpfs_opensbi_vendor_ext_check * @@ -633,8 +606,6 @@ void __attribute__((noreturn)) mpfs_opensbi_setup(void) mpfs_hart_index2id[i] = mpfs_get_use_sbi(i) ? i : -1; } - mpfs_opensbi_pmp_setup(); - sbi_console_set_device(&mpfs_console); mpfs_opensbi_scratch_setup(hartid); From d2c09b260480d3c8a0f6c9a53243a0fbe4029ccf Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Tue, 17 Oct 2023 15:33:51 +0300 Subject: [PATCH 129/138] mpfs_entrypoints.c: Open all memory from PMP for hart before booting Open PMP before the hart payload starts to execute --- arch/risc-v/src/mpfs/mpfs_entrypoints.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/arch/risc-v/src/mpfs/mpfs_entrypoints.c b/arch/risc-v/src/mpfs/mpfs_entrypoints.c index b6ee0a72115ea..21d77e5aef048 100644 --- a/arch/risc-v/src/mpfs/mpfs_entrypoints.c +++ b/arch/risc-v/src/mpfs/mpfs_entrypoints.c @@ -33,6 +33,8 @@ #include +#include "riscv_internal.h" + /**************************************************************************** * Extern Function Declarations ****************************************************************************/ @@ -45,6 +47,10 @@ extern void mpfs_opensbi_prepare_hart(void); #define ENTRYPT_CNT sizeof(g_app_entrypoints) / sizeof(g_app_entrypoints[0]) +/* Default PMP permissions */ + +#define PMP_DEFAULT_PERM (PMPCFG_A_NAPOT | PMPCFG_R | PMPCFG_W | PMPCFG_X) + /**************************************************************************** * Private Data ****************************************************************************/ @@ -88,6 +94,11 @@ void mpfs_jump_to_app(void) __asm__ __volatile__ ( "csrr a0, mhartid\n" /* Hart ID */ + "li t0, -1\n" /* Open the whole SoC */ + "csrw pmpaddr0, t0\n" + "li t0, %0\n" /* Grant RWX permissions */ + "csrw pmpcfg0, t0\n" + "csrw pmpcfg2, zero\n" #ifdef CONFIG_MPFS_OPENSBI "ld t0, g_hart_use_sbi\n" /* Load sbi usage bitmask */ "srl t0, t0, a0\n" /* Shift right by this hart */ @@ -101,6 +112,9 @@ void mpfs_jump_to_app(void) "add t0, t0, t1\n" /* Index in table */ "ld t0, 0(t0)\n" /* Load the address from table */ "jr t0\n" /* Jump to entrypoint */ + : + : "i" (PMP_DEFAULT_PERM) + : ); } From 5722d68c457df368d1451b286c308a686c36f5ff Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Tue, 17 Oct 2023 16:04:19 +0300 Subject: [PATCH 130/138] arch/mpfs: Add CONFIG_MPFS_BOARD_PMP option for PMP configuration This adds option to do PMP configuration via mpfs_board_pmp_setup instead of just opening up everything. In this case, it is up to the specific board to implement the PMP configuration in whichever way it sees fit. --- arch/risc-v/src/mpfs/Kconfig | 9 +++++++++ arch/risc-v/src/mpfs/mpfs_entrypoints.c | 20 ++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/arch/risc-v/src/mpfs/Kconfig b/arch/risc-v/src/mpfs/Kconfig index 64ff2bff28329..9f9c18bcbba56 100644 --- a/arch/risc-v/src/mpfs/Kconfig +++ b/arch/risc-v/src/mpfs/Kconfig @@ -46,6 +46,15 @@ config MPFS_BOOTLOADER ---help--- This NuttX image is used as a bootloader, which will boot only on one hart, putting the others in WFI +config MPFS_BOARD_PMP + bool "Enable board specific PMP configuration" + depends on ARCH_USE_MPU && MPFS_BOOTLOADER + default n + ---help--- + If true, the board must provide "mpfs_board_pmp_setup" for PMP + configuration. If false, set ALL memory accessible for every + configured HART. Only the bootloader should do this. + config MPFS_OPENSBI bool "Use OpenSBI" depends on MPFS_BOOTLOADER && OPENSBI diff --git a/arch/risc-v/src/mpfs/mpfs_entrypoints.c b/arch/risc-v/src/mpfs/mpfs_entrypoints.c index 21d77e5aef048..fdcbc1a3b4d56 100644 --- a/arch/risc-v/src/mpfs/mpfs_entrypoints.c +++ b/arch/risc-v/src/mpfs/mpfs_entrypoints.c @@ -45,6 +45,7 @@ extern void mpfs_opensbi_prepare_hart(void); * Pre-processor Definitions ****************************************************************************/ +#define ENTRY_STACK 512 #define ENTRYPT_CNT sizeof(g_app_entrypoints) / sizeof(g_app_entrypoints[0]) /* Default PMP permissions */ @@ -84,6 +85,11 @@ static uint64_t g_hart_use_sbi = #endif 0; +#ifdef CONFIG_MPFS_BOARD_PMP +uint8_t g_mpfs_boot_stacks[ENTRY_STACK * ENTRYPT_CNT] + aligned_data(STACK_ALIGNMENT); +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -94,11 +100,21 @@ void mpfs_jump_to_app(void) __asm__ __volatile__ ( "csrr a0, mhartid\n" /* Hart ID */ +#ifdef CONFIG_MPFS_BOARD_PMP + "li t1, %0\n" /* Size of hart's stack */ + "mul t0, a0, t1\n" /* Hart stack base */ + "add t0, t0, t1\n" /* Hart stack top */ + "la sp, g_mpfs_boot_stacks\n" /* Stack area base */ + "add sp, sp, t0\n" /* Set stack pointer */ + "call mpfs_board_pmp_setup\n" /* Run PMP configuration */ + "csrr a0, mhartid\n" /* Restore hartid */ +#else "li t0, -1\n" /* Open the whole SoC */ "csrw pmpaddr0, t0\n" "li t0, %0\n" /* Grant RWX permissions */ "csrw pmpcfg0, t0\n" "csrw pmpcfg2, zero\n" +#endif #ifdef CONFIG_MPFS_OPENSBI "ld t0, g_hart_use_sbi\n" /* Load sbi usage bitmask */ "srl t0, t0, a0\n" /* Shift right by this hart */ @@ -113,7 +129,11 @@ void mpfs_jump_to_app(void) "ld t0, 0(t0)\n" /* Load the address from table */ "jr t0\n" /* Jump to entrypoint */ : +#ifdef CONFIG_MPFS_BOARD_PMP + : "i" (ENTRY_STACK) +#else : "i" (PMP_DEFAULT_PERM) +#endif : ); } From 9b3a69a23aa0cb8bc89026d8a4502c0601cb62d3 Mon Sep 17 00:00:00 2001 From: yangyalei Date: Tue, 19 Sep 2023 09:51:50 +0800 Subject: [PATCH 131/138] Exec: Support run exec in current task There is a problem when vfork() calls execv() (or execl()) to start a new application: When the parent thread calls vfork() it receives and gets the pid of the vforked task, and not the pid of the desired execv'ed application. see issue #3334 Signed-off-by: yangyalei --- binfmt/CMakeLists.txt | 1 + binfmt/Makefile | 2 + binfmt/binfmt_exec.c | 63 ++++++++++++++++++--- binfmt/binfmt_execmodule.c | 102 ++++++++++++++++++++++++++++++++-- include/nuttx/binfmt/binfmt.h | 3 +- 5 files changed, 157 insertions(+), 14 deletions(-) diff --git a/binfmt/CMakeLists.txt b/binfmt/CMakeLists.txt index f0e0abe3713ec..9af12e1a3bc86 100644 --- a/binfmt/CMakeLists.txt +++ b/binfmt/CMakeLists.txt @@ -63,3 +63,4 @@ endif() target_sources(binfmt PRIVATE ${SRCS}) target_include_directories(binfmt PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +target_include_directories(binfmt PRIVATE ${CMAKE_SOURCE_DIR}/sched) diff --git a/binfmt/Makefile b/binfmt/Makefile index 9f8dbf8f058f0..004ef03a8a2a3 100644 --- a/binfmt/Makefile +++ b/binfmt/Makefile @@ -58,6 +58,8 @@ endif include libnxflat/Make.defs include libelf/Make.defs +CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)sched + AOBJS = $(ASRCS:.S=$(OBJEXT)) COBJS = $(CSRCS:.c=$(OBJEXT)) diff --git a/binfmt/binfmt_exec.c b/binfmt/binfmt_exec.c index ba1d2f3cb7b8f..ea62aff92408c 100644 --- a/binfmt/binfmt_exec.c +++ b/binfmt/binfmt_exec.c @@ -37,11 +37,11 @@ #ifndef CONFIG_BINFMT_DISABLE /**************************************************************************** - * Public Functions + * Private Functions ****************************************************************************/ /**************************************************************************** - * Name: exec_spawn + * Name: exec_internal * * Description: * exec() configurable version, delivery the spawn attribute if this @@ -64,6 +64,7 @@ * nexports - The number of symbols in the exports table. * actions - The spawn file actions * attr - The spawn attributes. + * spawn - Is spawn in new task. * * Returned Value: * It returns the PID of the exec'ed module. On failure, it returns @@ -71,10 +72,11 @@ * ****************************************************************************/ -int exec_spawn(FAR const char *filename, FAR char * const *argv, - FAR char * const *envp, FAR const struct symtab_s *exports, - int nexports, FAR const posix_spawn_file_actions_t *actions, - FAR const posix_spawnattr_t *attr) +static int exec_internal(FAR const char *filename, + FAR char * const *argv, FAR char * const *envp, + FAR const struct symtab_s *exports, int nexports, + FAR const posix_spawn_file_actions_t *actions, + FAR const posix_spawnattr_t *attr, bool spawn) { FAR struct binary_s *bin; irqstate_t flags; @@ -132,7 +134,7 @@ int exec_spawn(FAR const char *filename, FAR char * const *argv, /* Then start the module */ - pid = exec_module(bin, filename, argv, envp, actions); + pid = exec_module(bin, filename, argv, envp, actions, spawn); if (pid < 0) { ret = pid; @@ -175,6 +177,50 @@ int exec_spawn(FAR const char *filename, FAR char * const *argv, return ret; } +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: exec_spawn + * + * Description: + * exec() configurable version, delivery the spawn attribute if this + * process has special customization. + * + * Input Parameters: + * filename - The path to the program to be executed. If + * CONFIG_LIBC_ENVPATH is defined in the configuration, then + * this may be a relative path from the current working + * directory. Otherwise, path must be the absolute path to the + * program. + * argv - A pointer to an array of string arguments. The end of the + * array is indicated with a NULL entry. + * envp - A pointer to an array of environment strings. Terminated with + * a NULL entry. + * exports - The address of the start of the caller-provided symbol + * table. This symbol table contains the addresses of symbols + * exported by the caller and made available for linking the + * module into the system. + * nexports - The number of symbols in the exports table. + * actions - The spawn file actions + * attr - The spawn attributes. + * + * Returned Value: + * It returns the PID of the exec'ed module. On failure, it returns + * the negative errno value appropriately. + * + ****************************************************************************/ + +int exec_spawn(FAR const char *filename, FAR char * const *argv, + FAR char * const *envp, FAR const struct symtab_s *exports, + int nexports, FAR const posix_spawn_file_actions_t *actions, + FAR const posix_spawnattr_t *attr) +{ + return exec_internal(filename, argv, envp, + exports, nexports, actions, attr, true); +} + /**************************************************************************** * Name: exec * @@ -245,7 +291,8 @@ int exec(FAR const char *filename, FAR char * const *argv, { int ret; - ret = exec_spawn(filename, argv, envp, exports, nexports, NULL, NULL); + ret = exec_internal(filename, argv, envp, + exports, nexports, NULL, NULL, false); if (ret < 0) { set_errno(-ret); diff --git a/binfmt/binfmt_execmodule.c b/binfmt/binfmt_execmodule.c index 92fe1f6480bdc..6aab71a92ca90 100644 --- a/binfmt/binfmt_execmodule.c +++ b/binfmt/binfmt_execmodule.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -96,6 +97,91 @@ static void exec_ctors(FAR void *arg) } #endif +/**************************************************************************** + * Name: exec_swap + * + * Description: + * swap the pid of tasks, and reverse parent-child relationship. + * + * Input Parameters: + * ptcb - parent task tcb. + * chtcb - child task tcb. + * + * Returned Value: + * none + * + ****************************************************************************/ + +static void exec_swap(FAR struct tcb_s *ptcb, FAR struct tcb_s *chtcb) +{ + int pndx; + int chndx; + pid_t pid; + irqstate_t flags; +#ifdef HAVE_GROUP_MEMBERS + FAR pid_t *tg_members; +#endif +#ifdef CONFIG_SCHED_HAVE_PARENT +# ifdef CONFIG_SCHED_CHILD_STATUS + FAR struct child_status_s *tg_children; +# else + uint16_t tg_nchildren; +# endif +#endif + + DEBUGASSERT(ptcb); + DEBUGASSERT(chtcb); + + flags = enter_critical_section(); + + pndx = PIDHASH(ptcb->pid); + chndx = PIDHASH(chtcb->pid); + + DEBUGASSERT(g_pidhash[pndx]); + DEBUGASSERT(g_pidhash[chndx]); + + /* Exchange g_pidhash index */ + + g_pidhash[pndx] = chtcb; + g_pidhash[chndx] = ptcb; + + /* Exchange pid */ + + pid = chtcb->pid; + chtcb->pid = ptcb->pid; + ptcb->pid = pid; + + /* Exchange group info. This will reverse parent-child relationship */ + + pid = chtcb->group->tg_pid; + chtcb->group->tg_pid = ptcb->group->tg_pid; + ptcb->group->tg_pid = pid; + + pid = chtcb->group->tg_ppid; + chtcb->group->tg_ppid = ptcb->group->tg_ppid; + ptcb->group->tg_ppid = pid; + +#ifdef HAVE_GROUP_MEMBERS + tg_members = chtcb->group->tg_members; + chtcb->group->tg_members = ptcb->group->tg_members; + ptcb->group->tg_members = tg_members; +#endif + +#ifdef CONFIG_SCHED_HAVE_PARENT +# ifdef CONFIG_SCHED_CHILD_STATUS + tg_children = chtcb->group->tg_children; + chtcb->group->tg_children = ptcb->group->tg_children; + ptcb->group->tg_children = tg_children; +# else + tg_nchildren = chtcb->group->tg_nchildren; + chtcb->group->tg_nchildren = ptcb->group->tg_nchildren; + ptcb->group->tg_nchildren = tg_nchildren; +# endif +#endif + + leave_critical_section(flags); +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -116,7 +202,8 @@ static void exec_ctors(FAR void *arg) int exec_module(FAR struct binary_s *binp, FAR const char *filename, FAR char * const *argv, FAR char * const *envp, - FAR const posix_spawn_file_actions_t *actions) + FAR const posix_spawn_file_actions_t *actions, + bool spawn) { FAR struct task_tcb_s *tcb; #if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL) @@ -285,10 +372,6 @@ int exec_module(FAR struct binary_s *binp, } #endif - /* Get the assigned pid before we start the task */ - - pid = tcb->cmn.pid; - #ifdef CONFIG_SCHED_USER_IDENTITY if (binp->mode & S_ISUID) { @@ -301,6 +384,15 @@ int exec_module(FAR struct binary_s *binp, } #endif + if (!spawn) + { + exec_swap(this_task(), (FAR struct tcb_s *)tcb); + } + + /* Get the assigned pid before we start the task */ + + pid = tcb->cmn.pid; + /* Then activate the task at the provided priority */ nxtask_activate((FAR struct tcb_s *)tcb); diff --git a/include/nuttx/binfmt/binfmt.h b/include/nuttx/binfmt/binfmt.h index 1c90c60fe15d5..772d5ad9e3368 100644 --- a/include/nuttx/binfmt/binfmt.h +++ b/include/nuttx/binfmt/binfmt.h @@ -272,7 +272,8 @@ int unload_module(FAR struct binary_s *bin); int exec_module(FAR struct binary_s *binp, FAR const char *filename, FAR char * const *argv, FAR char * const *envp, - FAR const posix_spawn_file_actions_t *actions); + FAR const posix_spawn_file_actions_t *actions, + bool spawn); /**************************************************************************** * Name: exec From da552cae6328338c990342edccb99acdf2f57842 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Wed, 25 Oct 2023 10:39:17 +0300 Subject: [PATCH 132/138] sched/task_[posix]spawn: Simplify how spawn attributes are handled Handle task spawn attributes as task spawn file actions are handled. Why? This removes the need for sched_lock() when the task is being spawned. When loading the new task from a file the scheduler can be locked for a VERY LONG time, in the order of hundreds of milliseconds! This is unacceptable for real time operation. Also fixes a latent bug in exec_module, spawn_file_actions is executed at a bad location; when CONFIG_ARCH_ADDRENV=y actions will point to the new process's address environment (as it is temporarily instantiated at that point). Fix this by moving it to after addrenv_restore. --- binfmt/binfmt_exec.c | 2 +- binfmt/binfmt_execmodule.c | 43 +++++++++++++++++++---------- include/nuttx/binfmt/binfmt.h | 1 + sched/task/task_posixspawn.c | 23 +--------------- sched/task/task_spawn.c | 52 ++++++++++++++++------------------- 5 files changed, 54 insertions(+), 67 deletions(-) diff --git a/binfmt/binfmt_exec.c b/binfmt/binfmt_exec.c index ea62aff92408c..9c9396636bbf0 100644 --- a/binfmt/binfmt_exec.c +++ b/binfmt/binfmt_exec.c @@ -134,7 +134,7 @@ static int exec_internal(FAR const char *filename, /* Then start the module */ - pid = exec_module(bin, filename, argv, envp, actions, spawn); + pid = exec_module(bin, filename, argv, envp, actions, attr, spawn); if (pid < 0) { ret = pid; diff --git a/binfmt/binfmt_execmodule.c b/binfmt/binfmt_execmodule.c index 6aab71a92ca90..ccfe5a81a21c4 100644 --- a/binfmt/binfmt_execmodule.c +++ b/binfmt/binfmt_execmodule.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -203,6 +204,7 @@ int exec_module(FAR struct binary_s *binp, FAR const char *filename, FAR char * const *argv, FAR char * const *envp, FAR const posix_spawn_file_actions_t *actions, + FAR const posix_spawnattr_t *attr, bool spawn) { FAR struct task_tcb_s *tcb; @@ -326,17 +328,6 @@ int exec_module(FAR struct binary_s *binp, binfmt_freeargv(argv); binfmt_freeenv(envp); - /* Perform file actions */ - - if (actions != NULL) - { - ret = spawn_file_actions(&tcb->cmn, actions); - if (ret < 0) - { - goto errout_with_tcbinit; - } - } - #ifdef CONFIG_PIC /* Add the D-Space address as the PIC base address. By convention, this * must be the first allocated address space. @@ -393,10 +384,6 @@ int exec_module(FAR struct binary_s *binp, pid = tcb->cmn.pid; - /* Then activate the task at the provided priority */ - - nxtask_activate((FAR struct tcb_s *)tcb); - #if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_BUILD_KERNEL) /* Restore the address environment of the caller */ @@ -408,6 +395,32 @@ int exec_module(FAR struct binary_s *binp, } #endif + /* Perform file actions */ + + if (actions != NULL) + { + ret = spawn_file_actions(&tcb->cmn, actions); + if (ret < 0) + { + goto errout_with_tcbinit; + } + } + + /* Set the attributes */ + + if (attr) + { + ret = spawn_execattrs(pid, attr); + if (ret < 0) + { + goto errout_with_tcbinit; + } + } + + /* Then activate the task at the provided priority */ + + nxtask_activate((FAR struct tcb_s *)tcb); + return pid; errout_with_tcbinit: diff --git a/include/nuttx/binfmt/binfmt.h b/include/nuttx/binfmt/binfmt.h index 772d5ad9e3368..3037dfb2f9a6d 100644 --- a/include/nuttx/binfmt/binfmt.h +++ b/include/nuttx/binfmt/binfmt.h @@ -273,6 +273,7 @@ int exec_module(FAR struct binary_s *binp, FAR const char *filename, FAR char * const *argv, FAR char * const *envp, FAR const posix_spawn_file_actions_t *actions, + FAR const posix_spawnattr_t *attr, bool spawn); /**************************************************************************** diff --git a/sched/task/task_posixspawn.c b/sched/task/task_posixspawn.c index 0fb56c97b9549..a0ff0c0d5d365 100644 --- a/sched/task/task_posixspawn.c +++ b/sched/task/task_posixspawn.c @@ -102,13 +102,6 @@ static int nxposix_spawn_exec(FAR pid_t *pidp, FAR const char *path, exec_getsymtab(&symtab, &nsymbols); - /* Disable pre-emption so that we can modify the task parameters after - * we start the new task; the new task will not actually begin execution - * until we re-enable pre-emption. - */ - - sched_lock(); - /* Start the task */ pid = exec_spawn(path, argv, envp, symtab, nsymbols, actions, attr); @@ -116,7 +109,7 @@ static int nxposix_spawn_exec(FAR pid_t *pidp, FAR const char *path, { ret = -pid; serr("ERROR: exec failed: %d\n", ret); - goto errout; + return ret; } /* Return the task ID to the caller */ @@ -126,20 +119,6 @@ static int nxposix_spawn_exec(FAR pid_t *pidp, FAR const char *path, *pidp = pid; } - /* Now set the attributes. Note that we ignore all of the return values - * here because we have already successfully started the task. If we - * return an error value, then we would also have to stop the task. - */ - - if (attr) - { - spawn_execattrs(pid, attr); - } - - /* Re-enable pre-emption and return */ - -errout: - sched_unlock(); return ret; } diff --git a/sched/task/task_spawn.c b/sched/task/task_spawn.c index 7c261286a0059..aa753abd93830 100644 --- a/sched/task/task_spawn.c +++ b/sched/task/task_spawn.c @@ -80,7 +80,8 @@ static int nxtask_spawn_create(FAR const char *name, int priority, FAR void *stack_addr, int stack_size, main_t entry, FAR char * const argv[], FAR char * const envp[], - FAR const posix_spawn_file_actions_t *actions) + FAR const posix_spawn_file_actions_t *actions, + FAR const posix_spawnattr_t *attr) { FAR struct task_tcb_s *tcb; pid_t pid; @@ -109,6 +110,10 @@ static int nxtask_spawn_create(FAR const char *name, int priority, return ret; } + /* Get the assigned pid before we start the task */ + + pid = tcb->cmn.pid; + /* Perform file actions */ if (actions != NULL) @@ -116,20 +121,30 @@ static int nxtask_spawn_create(FAR const char *name, int priority, ret = spawn_file_actions(&tcb->cmn, actions); if (ret < 0) { - nxtask_uninit(tcb); - return ret; + goto errout_with_taskinit; } } - /* Get the assigned pid before we start the task */ + /* Set the attributes */ - pid = tcb->cmn.pid; + if (attr) + { + ret = spawn_execattrs(pid, attr); + if (ret < 0) + { + goto errout_with_taskinit; + } + } /* Activate the task */ nxtask_activate(&tcb->cmn); return pid; + +errout_with_taskinit: + nxtask_uninit(tcb); + return ret; } /**************************************************************************** @@ -188,13 +203,6 @@ static int nxtask_spawn_exec(FAR pid_t *pidp, FAR const char *name, int pid; int ret = OK; - /* Disable pre-emption so that we can modify the task parameters after - * we start the new task; the new task will not actually begin execution - * until we re-enable pre-emption. - */ - - sched_lock(); - /* Use the default priority and stack size if no attributes are provided */ if (attr) @@ -212,7 +220,7 @@ static int nxtask_spawn_exec(FAR pid_t *pidp, FAR const char *name, ret = nxsched_get_param(0, ¶m); if (ret < 0) { - goto errout; + return ret; } priority = param.sched_priority; @@ -223,12 +231,12 @@ static int nxtask_spawn_exec(FAR pid_t *pidp, FAR const char *name, pid = nxtask_spawn_create(name, priority, stackaddr, stacksize, entry, argv, - envp ? envp : environ, actions); + envp ? envp : environ, actions, attr); if (pid < 0) { ret = pid; serr("ERROR: nxtask_spawn_create failed: %d\n", ret); - goto errout; + return ret; } /* Return the task ID to the caller */ @@ -238,20 +246,6 @@ static int nxtask_spawn_exec(FAR pid_t *pidp, FAR const char *name, *pidp = pid; } - /* Now set the attributes. Note that we ignore all of the return values - * here because we have already successfully started the task. If we - * return an error value, then we would also have to stop the task. - */ - - if (attr) - { - spawn_execattrs(pid, attr); - } - - /* Re-enable pre-emption and return */ - -errout: - sched_unlock(); return ret; } From 3e8ead320654e80acebbbe990968d8500fa4ff13 Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Tue, 31 Oct 2023 11:46:02 +0200 Subject: [PATCH 133/138] arch/risc-v/src/mpfs/mpfs_serial.c: Allow switching uart output to console off By setting "isconsole" to false, mpfs_serial stops outputting to console. This can be used to disable output to debug console in low level. Signed-off-by: Jukka Laitinen --- arch/risc-v/src/mpfs/mpfs_serial.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/risc-v/src/mpfs/mpfs_serial.c b/arch/risc-v/src/mpfs/mpfs_serial.c index 8fb857274a557..9064a1f060c4d 100644 --- a/arch/risc-v/src/mpfs/mpfs_serial.c +++ b/arch/risc-v/src/mpfs/mpfs_serial.c @@ -1355,6 +1355,13 @@ static void up_send(struct uart_dev_s *dev, int ch) { struct up_dev_s *priv = (struct up_dev_s *)dev->priv; +#ifdef HAVE_SERIAL_CONSOLE + if (dev == &CONSOLE_DEV && !dev->isconsole) + { + return; + } +#endif + while ((up_serialin(priv, MPFS_UART_LSR_OFFSET) & UART_LSR_THRE) == 0); @@ -1547,6 +1554,12 @@ int up_putc(int ch) #ifdef HAVE_SERIAL_CONSOLE struct up_dev_s *priv = (struct up_dev_s *)CONSOLE_DEV.priv; uint32_t ier; + + if (!CONSOLE_DEV.isconsole) + { + return ch; + } + up_disableuartint(priv, &ier); #endif From c74cd1086c807db1dd150882d32485a36b721d63 Mon Sep 17 00:00:00 2001 From: Jari Nippula Date: Fri, 3 Nov 2023 14:53:04 +0200 Subject: [PATCH 134/138] arch/risc-v/src/mpfs: Add hardware/mpfs_wdog.h --- arch/risc-v/src/mpfs/hardware/mpfs_wdog.h | 75 +++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 arch/risc-v/src/mpfs/hardware/mpfs_wdog.h diff --git a/arch/risc-v/src/mpfs/hardware/mpfs_wdog.h b/arch/risc-v/src/mpfs/hardware/mpfs_wdog.h new file mode 100644 index 0000000000000..a2059e1f41958 --- /dev/null +++ b/arch/risc-v/src/mpfs/hardware/mpfs_wdog.h @@ -0,0 +1,75 @@ +/**************************************************************************** + * arch/risc-v/src/mpfs/hardware/mpfs_wdog.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_WDOG_H +#define __ARCH_RISCV_SRC_MPFS_HARDWARE_MPFS_WDOG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Magic value for REFRESH register to reload watchdog countdown counter */ + +#define WDOG_REFRESH_RELOAD (0xdeadc0de) + +/* Magic value for FORCE register to perform immediate system reset */ + +#define WDOG_FORCE_IMMEDIATE_RESET (0x0c) + +/**************************************************************************** + * Register Offsets + ****************************************************************************/ + +#define MPFS_WDOG_REFRESH_OFFSET 0x000 /* Write value 0xdeadc0de to reset wdog. Read to get current count value */ +#define MPFS_WDOG_CONTROL_OFFSET 0x004 /* WDOG counter register */ +#define MPFS_WDOG_STATUS_OFFSET 0x008 /* WDOG status register */ +#define MPFS_WDOG_TIME_OFFSET 0x00C /* Set WDOG time value */ +#define MPFS_WDOG_MSVP_OFFSET 0x010 /* Set MSVP int level */ +#define MPFS_WDOG_TRIGGER_OFFSET 0x014 /* Set NMI int level */ +#define MPFS_WDOG_FORCE_OFFSET 0x018 /* Force trigger WDOG NMI seq. Writing 0xc triggers immediate reset */ + +/**************************************************************************** + * Control register masks + ****************************************************************************/ + +#define WDOG_CONTROL_INTEN_MSVP_MASK (1 << 0) /* Bit 0: Enable MVRP interrupt when MVRP level is passed */ +#define WDOG_CONTROL_INTEN_TRIG_MASK (1 << 1) /* Bit 1: Enable NMI interrupt. This bit is permanenty set */ +#define WDOG_CONTROL_INTEN_SLEEP_MASK (1 << 2) /* Bit 2: Enable MVRP interrupt when MVRP level is passed and M3 is sleeping */ +#define WDOG_CONTROL_ACTIVE_SLEEP_MASK (1 << 3) /* Bit 3: Set WDOG operational during CPU sleep */ +#define WDOG_CONTROL_ENABLE_FORBITTEN_MASK (1 << 4) /* Bit 4: Enable trigger wdog from write during forbitten window */ + +/**************************************************************************** + * Status register masks + ****************************************************************************/ + +#define WDOG_STATUS_MVRP_TRIPPED_MASK (1 << 0) /* Bit 0: MVRP level has passed. Write to clear interrupt */ +#define WDOG_STATUS_WDOG_TRIPPED_MASK (1 << 1) /* Bit 1: TRIGGER level has passed and NMI is asserted. Write to clear interrupt */ +#define WDOG_STATUS_FORBITTEN_MASK (1 << 2) /* Bit 2: Watchdog in forbitten window */ +#define WDOG_STATUS_TRIGGERED_MASK (1 << 3) /* Bit 3: Watchdog has triggered */ +#define WDOG_STATUS_LOCKED_MASK (1 << 4) /* Bit 4: Following registers are locked and cannot be changed */ +#define WDOG_STATUS_DEVRST_MASK (1 << 5) /* Bit 5: DEVRST caused NMI */ + +#endif /* __ARCH_RISCV_SRC_MPFS_HARDWARE_MPFS_WDOG_H */ From a18cb5106fe98eed0161ac1bfaf2a6d215b28552 Mon Sep 17 00:00:00 2001 From: Eero Nurkkala Date: Mon, 6 Nov 2023 17:25:13 +0200 Subject: [PATCH 135/138] risc-v/mpfs: i2c: prevent out of bounds read access priv->msgid may grow past its boundaries, causing struct i2c_msg_s *msg = &priv->msgv[priv->msgid] to read data out of boundaris. Signed-off-by: Eero Nurkkala --- arch/risc-v/src/mpfs/mpfs_i2c.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_i2c.c b/arch/risc-v/src/mpfs/mpfs_i2c.c index 23843a0981312..35701ae5d491b 100644 --- a/arch/risc-v/src/mpfs/mpfs_i2c.c +++ b/arch/risc-v/src/mpfs/mpfs_i2c.c @@ -492,7 +492,10 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg) /* Jump to the next message */ - priv->msgid++; + if (priv->msgid < (priv->msgc - 1)) + { + priv->msgid++; + } } else { @@ -511,7 +514,10 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg) /* Jump to the next message */ - priv->msgid++; + if (priv->msgid < (priv->msgc - 1)) + { + priv->msgid++; + } } else { From 8d702563a7c79978daffb5adb1f6918e92adf8b0 Mon Sep 17 00:00:00 2001 From: Eero Nurkkala Date: Thu, 9 Nov 2023 11:14:55 +0200 Subject: [PATCH 136/138] risc-v/mpfs: add tamper detection support This adds support for detecting various tamper events. The interrupt handler makes noise at every detection. Perhaps easiest test is to attach JTAG debugger. TAMPER_TESTS -define has some nonexisting (not in repos) calls, perhaps could remove it alltogether. Signed-off-by: Eero Nurkkala --- arch/risc-v/src/mpfs/Kconfig | 6 + arch/risc-v/src/mpfs/Make.defs | 4 + arch/risc-v/src/mpfs/mpfs_tamper.c | 396 +++++++++++++++++++++++++++++ arch/risc-v/src/mpfs/mpfs_tamper.h | 86 +++++++ 4 files changed, 492 insertions(+) create mode 100644 arch/risc-v/src/mpfs/mpfs_tamper.c create mode 100644 arch/risc-v/src/mpfs/mpfs_tamper.h diff --git a/arch/risc-v/src/mpfs/Kconfig b/arch/risc-v/src/mpfs/Kconfig index 9f9c18bcbba56..156309df1f219 100644 --- a/arch/risc-v/src/mpfs/Kconfig +++ b/arch/risc-v/src/mpfs/Kconfig @@ -426,6 +426,12 @@ config MPFS_COREMMC_IRQNUM range 0 63 depends on MPFS_COREMMC +config MPFS_TAMPER + bool "Tamper detection" + default n + ---help--- + Enable tamper detection mechanisms. + config MPFS_IHC_CLIENT bool "IHC slave" depends on RPTUN && !MPFS_BOOTLOADER diff --git a/arch/risc-v/src/mpfs/Make.defs b/arch/risc-v/src/mpfs/Make.defs index 925e4467619a8..e168aa6586171 100644 --- a/arch/risc-v/src/mpfs/Make.defs +++ b/arch/risc-v/src/mpfs/Make.defs @@ -112,6 +112,10 @@ ifeq ($(CONFIG_MPFS_CORESPI),y) CHIP_CSRCS += mpfs_corespi.c endif +ifeq ($(CONFIG_MPFS_TAMPER),y) +CHIP_CSRCS += mpfs_tamper.c +endif + ifeq ($(CONFIG_MPFS_CRYPTO),y) include mpfs/crypto.defs endif diff --git a/arch/risc-v/src/mpfs/mpfs_tamper.c b/arch/risc-v/src/mpfs/mpfs_tamper.c new file mode 100644 index 0000000000000..4729854ac0283 --- /dev/null +++ b/arch/risc-v/src/mpfs/mpfs_tamper.c @@ -0,0 +1,396 @@ +/**************************************************************************** + * arch/risc-v/src/mpfs/mpfs_tamper.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 + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register base-addresses */ + +#define MPFS_TAMPER_CTRL_BASE 0x4b00c000 +#define MPFS_TAMPER_TVS_BASE 0x4b00d000 + +/* CTRL Register offsets */ + +#define MPFS_SELECTED_EVENTS_OFFSET 0x00 +#define MPFS_STATUS_EVENTS_OFFSET 0x04 +#define MPFS_CLEAR_EVENTS_OFFSET 0x08 +#define MPFS_ENABLE_EVENTS_OFFSET 0x0c +#define MPFS_ENABLE_TVS_OFFSET 0x10 +#define MPFS_RESET_REASON_OFFSET 0x14 +#define MPFS_TAMPER_RESPONSE_OFFSET 0x18 + +/* Selected eventlist */ + +#define MPFS_SELECTED_EVENTS (MPFS_TAMPER_CTRL_BASE + \ + MPFS_SELECTED_EVENTS_OFFSET) + +#define FLAG_JTAG_ACTIVE (1 << 0) +#define FLAG_MESH_ERROR (1 << 1) +#define FLAG_CLOCK_MONITOR_GLITCH (1 << 2) +#define FLAG_CLOCK_MONITOR_FREQ (1 << 3) +#define FLAG_SECDED (1 << 4) +#define FLAG_SCB_BUS_ERROR (1 << 5) +#define FLAG_SC_WATCHDOG (1 << 6) +#define FLAG_LOCK_ERROR (1 << 7) +#define FLAG_DIGEST (1 << 8) +#define FLAG_INST_PASSCODE_FAIL (1 << 9) +#define FLAG_INST_KEY_VALIDATION_FAIL (1 << 10) +#define FLAG_INST_UNUSED (1 << 11) +#define FLAG_BITSTREAM_AUTHENTICATION_FAIL (1 << 12) +#define FLAG_DETECT_LOW_1P0 (1 << 13) +#define FLAG_DETECT_LOW_1P8 (1 << 14) +#define FLAG_DETECT_LOW_2P5 (1 << 15) +#define FLAG_DETECT_HIGH_1P0 (1 << 16) +#define FLAG_DETECT_HIGH_1P8 (1 << 17) +#define FLAG_DETECT_HIGH_2P5 (1 << 18) +#define FLAG_DETECT_TEMPERATURE_LOW (1 << 19) +#define FLAG_DETECT_TEMPERATURE_HIGH (1 << 20) + +#define FLAGS_ALL 0x1fffff +#define FLAG_BITS 21 + +/* Status eventlist */ + +#define MPFS_STATUS_EVENTS (MPFS_TAMPER_CTRL_BASE + \ + MPFS_STATUS_EVENTS_OFFSET) + +/* Clear eventlist */ + +#define MPFS_CLEAR_EVENTS (MPFS_TAMPER_CTRL_BASE + \ + MPFS_CLEAR_EVENTS_OFFSET) + +/* Enable eventlist */ + +#define MPFS_ENABLE_EVENTS (MPFS_TAMPER_CTRL_BASE + \ + MPFS_ENABLE_EVENTS_OFFSET) + +/* Enable TVS */ + +#define MPFS_ENABLE_TVS (MPFS_TAMPER_CTRL_BASE +\ + MPFS_ENABLE_TVS_OFFSET) + +#define MPFS_ENABLE_TVS_MONITORING (1 << 0) +#define MPFS_ENABLE_VOLTAGE_MONITORING (1 << 1) + +/* Reset reason */ + +#define MPFS_RESET_REASON (MPFS_TAMPER_CTRL_BASE + \ + MPFS_RESET_REASON_OFFSET) + +/* Clock and reset */ + +#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) + +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif + +/* Mesh system defines */ + +#define MPFS_MESH_CR 0x200020b0 +#define MPFS_MESH_START (1 << 0) + +/* Debug output defines, info promoted to _err for visibility */ + +#ifdef CONFIG_DEBUG_ERROR +# define tinfo _err +#else +# define tinfo _none +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mpfs_tamper_event_string + * + * Description: + * Tamper event to string function + * + * Input Parameters: + * List of events + * + * Returned Value: + * Readable string + * + ****************************************************************************/ + +static const char *mpfs_tamper_event_string(uint32_t eventlist) +{ + int i; + + static const char *const names[] = + { + "JTAG ACTIVE", + "MESH ERROR", + "CLOCK MONITOR GLITCH", + "CLOCK MONITOR FREQ", + "SECDED", + "SCB BUS ERROR", + "SC WATCHDOG", + "LOCK ERROR", + "DIGEST", + "PASSCODE FAIL", + "KEY VALIDATION FAIL", + "INST UNUSED", + "BITSTREAM AUTH FAIL", + "LOW 1P0", + "LOW 1P8", + "LOW 2P5", + "HIGH 1P0", + "HIGH 1P8", + "HIGH 2P5", + "TEMPERATURE LOW", + "TEMPERATURE HIGH", + }; + + for (i = 0; i < ARRAY_SIZE(names); i++) + { + if ((1 << i) & eventlist) + { + break; + } + } + + if (i >= ARRAY_SIZE(names)) + { + return "UNDEFINED"; + } + + return names[i]; +} + +/**************************************************************************** + * Name: mpfs_tamper_interrupt + * + * Description: + * Tamper intinfoupt handler + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static int mpfs_tamper_interrupt(int irq, void *context, void *arg) +{ + uint32_t eventlist; + uint32_t sel; + uint32_t status; + uint32_t clr; + uint32_t enabled; + uint32_t entvs; + int i; + + sel = getreg32(MPFS_SELECTED_EVENTS); + status = getreg32(MPFS_STATUS_EVENTS); + clr = getreg32(MPFS_CLEAR_EVENTS); + enabled = getreg32(MPFS_ENABLE_EVENTS); + entvs = getreg32(MPFS_ENABLE_TVS); + + eventlist = sel; + + if (eventlist) + { + tinfo("**********************************************************\n"); + tinfo("Tamper detection has caught out the following event(s):\n"); + for (i = 0; i < FLAG_BITS; i++) + { + if ((1 << i) & eventlist) + { + tinfo(" <%s>\n", mpfs_tamper_event_string(eventlist)); + eventlist &= ~(1 << i); + } + } + + tinfo("Regs: 0x00: 0x%x, 0x04: 0x%x, 0x08: 0x%x, 0x0c: 0x%x," + " 0x10: 0x%x\n", + sel, status, clr, enabled, entvs); + tinfo("**********************************************************\n"); + } + + putreg32(sel, MPFS_CLEAR_EVENTS); + + return 0; +} + +/**************************************************************************** + * Name: mpfs_tamper_tests + * + * Description: + * Various tamper tests for testing + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef TAMPER_TESTS +extern int mpfs_systemservice_init(); +extern int mpfs_sys_get_serial_number(uint8_t *out_sn, uint16_t mb_offset); +extern int mpfs_sys_query_security(uint8_t *out_security_resp, + uint16_t mb_offset); +extern int mpfs_sys_query_design_information(uint8_t *out_security_resp, + uint16_t mb_offset); +extern int mpfs_sys_query_device_certificate(uint8_t *out_security_resp, + uint16_t mb_offset); +extern uint16_t mpfs_sys_unlock_debug_passcode(uint8_t *cmd_data, + uint16_t mb_offset, + uint16_t resp_offset); +extern void test_ecdsa(void); + +static void mpfs_tamper_tests(void) +{ + uint8_t buf[1024 + 4]; + + mpfs_systemservice_init(); + + /* Some of the functions do not exist */ + + mpfs_sys_get_serial_number(buf, 0); + mpfs_sys_query_security(buf, 0); + mpfs_sys_query_design_information(buf, 0); + mpfs_sys_query_device_certificate(buf, 0); + mpfs_sys_unlock_debug_passcode(buf, 0, 0); + test_ecdsa(); + mpfs_sys_authenticate_iap_image(0); +} +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mpfs_tamper_enable + * + * Description: + * Enables the tamper service + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void mpfs_tamper_enable(void) +{ + int ret; + + 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); + + tinfo("Enabling Tamper detection - if no FPGA support, will hang here\n"); + tinfo("Tamper reset reason 0x%x\n", getreg32(MPFS_RESET_REASON)); + + /* Enable events */ + + putreg32(FLAGS_ALL, MPFS_ENABLE_EVENTS); + putreg32(MPFS_ENABLE_TVS_MONITORING | MPFS_ENABLE_VOLTAGE_MONITORING, + MPFS_ENABLE_TVS); + + /* Start the mesh system */ + + modifyreg32(MPFS_MESH_CR, 0, MPFS_MESH_START); + + ret = irq_attach(MPFS_IRQ_FABRIC_F2H_10, mpfs_tamper_interrupt, NULL); + + if (ret == 0) + { + up_enable_irq(MPFS_IRQ_FABRIC_F2H_10); + } + else + { + tinfo("Tamper IRQ attach failed"); + } + +#ifdef TAMPER_TESTS + mpfs_tamper_tests(); +#endif +} + +/**************************************************************************** + * Name: mpfs_tamper_disable + * + * Description: + * Disables tamper service + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void mpfs_tamper_disable(void) +{ + modifyreg32(MPFS_MESH_CR, MPFS_MESH_START, 0); + + up_disable_irq(MPFS_IRQ_FABRIC_F2H_10); + irq_detach(MPFS_IRQ_FABRIC_F2H_10); + + putreg32(0x00, MPFS_ENABLE_EVENTS); + putreg32(0, MPFS_ENABLE_TVS); +} diff --git a/arch/risc-v/src/mpfs/mpfs_tamper.h b/arch/risc-v/src/mpfs/mpfs_tamper.h new file mode 100644 index 0000000000000..800c4471d956a --- /dev/null +++ b/arch/risc-v/src/mpfs/mpfs_tamper.h @@ -0,0 +1,86 @@ +/**************************************************************************** + * arch/risc-v/src/mpfs/mpfs_tamper.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_TAMPER_H +#define __ARCH_RISCV_SRC_MPFS_MPFS_TAMPER_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "chip.h" + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: mpfs_tamper_enable + * + * Description: + * Enables the tamper service + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void mpfs_tamper_enable(void); + +/**************************************************************************** + * Name: mpfs_tamper_disable + * + * Description: + * Disables tamper service + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void mpfs_tamper_disable(void); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_RISCV_SRC_MPFS_MPFS_TAMPER_H */ From bc9dd5801aee195b69d8423e9f75ff8301ca985e Mon Sep 17 00:00:00 2001 From: Eero Nurkkala Date: Mon, 13 Nov 2023 13:08:49 +0200 Subject: [PATCH 137/138] risc-v/mpfs: tamper: refine tests Use only tests that will trigger a tamper event. Leave other tests outside. Signed-off-by: Eero Nurkkala --- arch/risc-v/src/mpfs/mpfs_tamper.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_tamper.c b/arch/risc-v/src/mpfs/mpfs_tamper.c index 4729854ac0283..0a268a722f2f5 100644 --- a/arch/risc-v/src/mpfs/mpfs_tamper.c +++ b/arch/risc-v/src/mpfs/mpfs_tamper.c @@ -277,33 +277,27 @@ static int mpfs_tamper_interrupt(int irq, void *context, void *arg) ****************************************************************************/ #ifdef TAMPER_TESTS -extern int mpfs_systemservice_init(); -extern int mpfs_sys_get_serial_number(uint8_t *out_sn, uint16_t mb_offset); -extern int mpfs_sys_query_security(uint8_t *out_security_resp, - uint16_t mb_offset); -extern int mpfs_sys_query_design_information(uint8_t *out_security_resp, - uint16_t mb_offset); -extern int mpfs_sys_query_device_certificate(uint8_t *out_security_resp, - uint16_t mb_offset); extern uint16_t mpfs_sys_unlock_debug_passcode(uint8_t *cmd_data, uint16_t mb_offset, uint16_t resp_offset); -extern void test_ecdsa(void); +extern uint16_t mpfs_sys_authenticate_iap_image(uint32_t spi_idx); static void mpfs_tamper_tests(void) { - uint8_t buf[1024 + 4]; + /* MPFS_SYS_UNLOCK_DEBUG_PASSCODE_DATA_LEN = 32 */ - mpfs_systemservice_init(); + uint8_t buf[32]; - /* Some of the functions do not exist */ + /* Looks like the buf needs to be gargabed first */ + + memset(buf, 0xaa, sizeof(buf)); + + /* Issue: */ - mpfs_sys_get_serial_number(buf, 0); - mpfs_sys_query_security(buf, 0); - mpfs_sys_query_design_information(buf, 0); - mpfs_sys_query_device_certificate(buf, 0); mpfs_sys_unlock_debug_passcode(buf, 0, 0); - test_ecdsa(); + + /* Issue: */ + mpfs_sys_authenticate_iap_image(0); } #endif From bb125da93db0a28d1f30b80288215660f1e24695 Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Mon, 27 Nov 2023 15:38:49 +0200 Subject: [PATCH 138/138] mpfs_opensbi: Re-organize SBI areas so that RW areas follow each other Change the ordering of the SBI areas so that: - The first area is the executable area (.text) - The second area is the heap (RW) - The last area is the scratch registers (RW) This makes it easier to encode PMP areas for OpenSBI. --- arch/risc-v/src/mpfs/mpfs_opensbi.c | 55 ++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/arch/risc-v/src/mpfs/mpfs_opensbi.c b/arch/risc-v/src/mpfs/mpfs_opensbi.c index cb6a66837bbc0..90f6995e85520 100644 --- a/arch/risc-v/src/mpfs/mpfs_opensbi.c +++ b/arch/risc-v/src/mpfs/mpfs_opensbi.c @@ -105,6 +105,8 @@ extern const uint8_t __mpfs_nuttx_start[]; extern const uint8_t __mpfs_nuttx_end[]; extern const uint8_t _ssbi_zerodev[]; extern const uint8_t _esbi_zerodev[]; +extern const uint8_t _sbi_heap_start[]; +extern const uint8_t _sbi_heap_size[]; /**************************************************************************** * Private Function Prototypes @@ -470,27 +472,41 @@ static void mpfs_opensbi_scratch_setup(uint32_t hartid) (unsigned long)mpfs_hart_to_scratch; g_scratches[hartid].scratch.platform_addr = (unsigned long)&platform; - /* Our FW area in l2lim section. OpenSBI needs to be aware of it in order - * to protect the area. However, we set the PMP values already and lock - * them so that OpenSBI has no chance override then. + /* Our FW area, heap and the scratch area are in l2lim. + * + * The memory is organized as follows: + * + * ---------------------------------------------------------------------- + * | | | | + * | SBI .text (0000h) | SBI heap (8000h) | SBI scratch (8000h + 4000h) | + * | | | | + * ---------------------------------------------------------------------- + * + * The reason for this organization is that the RX and RW areas can be set + * to the physical memory protection unit (PMP) as two contiguous areas. */ g_scratches[hartid].scratch.fw_start = (unsigned long)_ssbi_zerodev; g_scratches[hartid].scratch.fw_size = (unsigned long)_esbi_zerodev - (unsigned long)_ssbi_zerodev; - g_scratches[hartid].scratch.fw_rw_offset = - (unsigned long)g_scratches[hartid].scratch.fw_size; + /* RW area starts from the heap */ - /* fw_rw_offset needs to be an aligned address */ + g_scratches[hartid].scratch.fw_heap_offset = + (unsigned long)_sbi_heap_start - + (unsigned long)g_scratches[hartid].scratch.fw_start; - g_scratches[hartid].scratch.fw_rw_offset += 1024 * 2; - g_scratches[hartid].scratch.fw_rw_offset &= 0xffffff800; - g_scratches[hartid].scratch.fw_size = - g_scratches[hartid].scratch.fw_rw_offset; + g_scratches[hartid].scratch.fw_heap_size = + (unsigned long)_sbi_heap_size; - g_scratches[hartid].scratch.fw_heap_offset = - (unsigned long)g_scratches[hartid].scratch.fw_size; + g_scratches[hartid].scratch.fw_rw_offset = + g_scratches[hartid].scratch.fw_heap_offset; + + /* Because sbi_heap_init does not work otherwise */ + + g_scratches[hartid].scratch.fw_size = + g_scratches[hartid].scratch.fw_heap_offset + + g_scratches[hartid].scratch.fw_heap_size; /* Heap minimum is 16k. Otherwise sbi_heap.c fails: * hpctrl.hksize = hpctrl.size / HEAP_HOUSEKEEPING_FACTOR; @@ -500,10 +516,17 @@ static void mpfs_opensbi_scratch_setup(uint32_t hartid) * hpctrl.hksize gets to be zero making the OpenSBI crash. */ - g_scratches[hartid].scratch.fw_heap_size = 1024 * 16; - g_scratches[hartid].scratch.fw_size = - g_scratches[hartid].scratch.fw_heap_offset + - g_scratches[hartid].scratch.fw_heap_size; + if (g_scratches[hartid].scratch.fw_heap_size < 0x4000) + { + sbi_panic(__func__); + } + + /* fw_rw_offset needs to be an aligned address */ + + if (g_scratches[hartid].scratch.fw_rw_offset & 0x7ff) + { + sbi_panic(__func__); + } } /****************************************************************************