diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7ad4eec56a101..52d74ba26b23a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -66,13 +66,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" @@ -90,7 +90,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 @@ -100,7 +100,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 @@ -122,7 +122,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 @@ -172,6 +172,7 @@ jobs: continue-on-error: true macOS: + if: ${{ false }} # disable for now permissions: contents: none runs-on: macos-12 diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index f7a50ab05c2c5..489e9bbda0fef 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 diff --git a/.github/workflows/docker_linux.yml b/.github/workflows/docker_linux.yml index d06d7c996792b..1a1dab87c1027 100644 --- a/.github/workflows/docker_linux.yml +++ b/.github/workflows/docker_linux.yml @@ -61,7 +61,7 @@ jobs: run: | df -h - name: Push Linux image - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v4 with: context: tools/ci/docker/linux platforms: linux/amd64 diff --git a/arch/arm/src/lc823450/lc823450_i2c.c b/arch/arm/src/lc823450/lc823450_i2c.c index 69960dd82682a..b507702cf84df 100644 --- a/arch/arm/src/lc823450/lc823450_i2c.c +++ b/arch/arm/src/lc823450/lc823450_i2c.c @@ -305,7 +305,7 @@ lc823450_i2c_sem_waitdone(struct lc823450_i2c_priv_s *priv) /* Get the timeout value */ - timeout = MSEC2TICK(priv->timeoms + (MSEC_PER_TICK / 2)); + timeout = MSEC2TICK(priv->timeoms); timeout += SEC2TICK(CONFIG_LC823450_I2C_TIMEOSEC); /* Signal the interrupt handler that we are waiting. NOTE: Interrupts diff --git a/arch/arm/src/stm32f7/stm32_ethernet.c b/arch/arm/src/stm32f7/stm32_ethernet.c index a26f55cb67c9b..a0bfc70a36432 100644 --- a/arch/arm/src/stm32f7/stm32_ethernet.c +++ b/arch/arm/src/stm32f7/stm32_ethernet.c @@ -3126,7 +3126,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; diff --git a/arch/arm/src/stm32f7/stm32_i2c.c b/arch/arm/src/stm32f7/stm32_i2c.c index 6a629f6da832e..4972407c18839 100644 --- a/arch/arm/src/stm32f7/stm32_i2c.c +++ b/arch/arm/src/stm32f7/stm32_i2c.c @@ -433,6 +433,8 @@ struct stm32_i2c_config_s struct stm32_i2c_priv_s { + const struct i2c_ops_s *ops; /* Standard I2C operations */ + /* Port configuration */ const struct stm32_i2c_config_s *config; @@ -470,14 +472,6 @@ struct stm32_i2c_priv_s #endif }; -/* I2C Device, Instance */ - -struct stm32_i2c_inst_s -{ - const struct i2c_ops_s *ops; /* Standard I2C operations */ - struct stm32_i2c_priv_s *priv; /* Common driver private data structure */ -}; - /**************************************************************************** * Private Function Prototypes ****************************************************************************/ @@ -533,6 +527,16 @@ static int stm32_i2c_pm_prepare(struct pm_callback_s *cb, int domain, * Private Data ****************************************************************************/ +/* Device Structures, Instantiation */ + +static const struct i2c_ops_s stm32_i2c_ops = +{ + .transfer = stm32_i2c_transfer, +#ifdef CONFIG_I2C_RESET + .reset = stm32_i2c_reset, +#endif +}; + #ifdef CONFIG_STM32F7_I2C1 static const struct stm32_i2c_config_s stm32_i2c1_config = { @@ -549,6 +553,7 @@ static const struct stm32_i2c_config_s stm32_i2c1_config = static struct stm32_i2c_priv_s stm32_i2c1_priv = { + .ops = &stm32_i2c_ops, .config = &stm32_i2c1_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, @@ -585,6 +590,7 @@ static const struct stm32_i2c_config_s stm32_i2c2_config = static struct stm32_i2c_priv_s stm32_i2c2_priv = { + .ops = &stm32_i2c_ops, .config = &stm32_i2c2_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, @@ -621,6 +627,7 @@ static const struct stm32_i2c_config_s stm32_i2c3_config = static struct stm32_i2c_priv_s stm32_i2c3_priv = { + .ops = &stm32_i2c_ops, .config = &stm32_i2c3_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, @@ -657,6 +664,7 @@ static const struct stm32_i2c_config_s stm32_i2c4_config = static struct stm32_i2c_priv_s stm32_i2c4_priv = { + .ops = &stm32_i2c_ops, .config = &stm32_i2c4_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, @@ -677,16 +685,6 @@ static struct stm32_i2c_priv_s stm32_i2c4_priv = }; #endif -/* Device Structures, Instantiation */ - -static const struct i2c_ops_s stm32_i2c_ops = -{ - .transfer = stm32_i2c_transfer, -#ifdef CONFIG_I2C_RESET - .reset = stm32_i2c_reset, -#endif -}; - /**************************************************************************** * Private Functions ****************************************************************************/ @@ -2273,8 +2271,7 @@ static int stm32_i2c_deinit(struct stm32_i2c_priv_s *priv) static int stm32_i2c_process(struct i2c_master_s *dev, struct i2c_msg_s *msgs, int count) { - struct stm32_i2c_inst_s *inst = (struct stm32_i2c_inst_s *)dev; - struct stm32_i2c_priv_s *priv = inst->priv; + struct stm32_i2c_priv_s *priv = (struct stm32_i2c_priv_s *)dev; uint32_t status = 0; uint32_t cr1; uint32_t cr2; @@ -2505,15 +2502,11 @@ static int stm32_i2c_process(struct i2c_master_s *dev, static int stm32_i2c_transfer(struct i2c_master_s *dev, struct i2c_msg_s *msgs, int count) { - struct stm32_i2c_priv_s *priv; + struct stm32_i2c_priv_s *priv = (struct stm32_i2c_priv_s *)dev; int ret; DEBUGASSERT(dev); - /* Get I2C private structure */ - - priv = ((struct stm32_i2c_inst_s *)dev)->priv; - /* Ensure that address or flags don't change meanwhile */ ret = nxmutex_lock(&priv->lock); @@ -2536,7 +2529,7 @@ static int stm32_i2c_transfer(struct i2c_master_s *dev, #ifdef CONFIG_I2C_RESET static int stm32_i2c_reset(struct i2c_master_s *dev) { - struct stm32_i2c_priv_s *priv; + struct stm32_i2c_priv_s *priv = (struct stm32_i2c_priv_s *)dev; unsigned int clock_count; unsigned int stretch_count; uint32_t scl_gpio; @@ -2546,10 +2539,6 @@ static int stm32_i2c_reset(struct i2c_master_s *dev) DEBUGASSERT(dev); - /* Get I2C private structure */ - - priv = ((struct stm32_i2c_inst_s *)dev)->priv; - /* Our caller must own a ref */ DEBUGASSERT(priv->refs > 0); @@ -2748,7 +2737,6 @@ static int stm32_i2c_pm_prepare(struct pm_callback_s *cb, int domain, struct i2c_master_s *stm32_i2cbus_initialize(int port) { struct stm32_i2c_priv_s *priv = NULL; /* private data of device with multiple instances */ - struct stm32_i2c_inst_s *inst = NULL; /* device, single instance */ #if STM32_HSI_FREQUENCY != 16000000 || defined(INVALID_CLOCK_SOURCE) # warning STM32_I2C_INIT: Peripheral clock is HSI and it must be 16mHz or the speed/timing calculations need to be redone. @@ -2783,18 +2771,6 @@ struct i2c_master_s *stm32_i2cbus_initialize(int port) return NULL; } - /* Allocate instance */ - - if (!(inst = kmm_malloc(sizeof(struct stm32_i2c_inst_s)))) - { - return NULL; - } - - /* Initialize instance */ - - inst->ops = &stm32_i2c_ops; - inst->priv = priv; - /* Init private data for the first time, increment refs count, * power-up hardware and configure GPIOs. */ @@ -2813,7 +2789,7 @@ struct i2c_master_s *stm32_i2cbus_initialize(int port) } nxmutex_unlock(&priv->lock); - return (struct i2c_master_s *)inst; + return (struct i2c_master_s *)priv; } /**************************************************************************** @@ -2826,10 +2802,9 @@ struct i2c_master_s *stm32_i2cbus_initialize(int port) int stm32_i2cbus_uninitialize(struct i2c_master_s *dev) { - struct stm32_i2c_priv_s *priv; + struct stm32_i2c_priv_s *priv = (struct stm32_i2c_priv_s *)dev; DEBUGASSERT(dev); - priv = ((struct stm32_i2c_inst_s *)dev)->priv; /* Decrement refs and check for underflow */ @@ -2842,7 +2817,6 @@ int stm32_i2cbus_uninitialize(struct i2c_master_s *dev) if (--priv->refs) { nxmutex_unlock(&priv->lock); - kmm_free(dev); return OK; } @@ -2857,7 +2831,6 @@ int stm32_i2cbus_uninitialize(struct i2c_master_s *dev) stm32_i2c_deinit(priv); nxmutex_unlock(&priv->lock); - kmm_free(dev); return OK; } diff --git a/arch/risc-v/src/mpfs/Kconfig b/arch/risc-v/src/mpfs/Kconfig index 4489adba2b18d..173a85eb4cb98 100644 --- a/arch/risc-v/src/mpfs/Kconfig +++ b/arch/risc-v/src/mpfs/Kconfig @@ -130,7 +130,7 @@ choice prompt "Choose DDR type" depends on MPFS_DDR_INIT default MPFS_DDR_TYPE_LPDDR4 - + config MPFS_DDR_TYPE_DDR3 bool "Use DDR3" @@ -335,7 +335,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 @@ -388,6 +388,43 @@ 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_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 @@ -472,6 +509,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 d1ce44951d39c..a35b2bf2c37e7 100644 --- a/arch/risc-v/src/mpfs/Make.defs +++ b/arch/risc-v/src/mpfs/Make.defs @@ -70,6 +70,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/hardware/mpfs_i2c.h b/arch/risc-v/src/mpfs/hardware/mpfs_i2c.h index d90fcde550aab..689e33e8185a7 100644 --- a/arch/risc-v/src/mpfs/hardware/mpfs_i2c.h +++ b/arch/risc-v/src/mpfs/hardware/mpfs_i2c.h @@ -43,6 +43,7 @@ #define MPFS_I2C_CTRL_CR1_MASK (1 << 1) #define MPFS_I2C_CTRL_CR0_MASK (1 << 0) +#define MPFS_I2C_ST_IDLE 0xF8 /* No activity, I2C bus idle */ #define MPFS_I2C_ST_RESET_ACTIVATED 0xD0 /* Master reset is activated */ #define MPFS_I2C_ST_RX_DATA_NACK 0x58 /* Data received, NACK sent */ #define MPFS_I2C_ST_RX_DATA_ACK 0x50 /* Data received, ACK sent */ 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 ****************************************************************************/ diff --git a/arch/risc-v/src/mpfs/mpfs_emmcsd.c b/arch/risc-v/src/mpfs/mpfs_emmcsd.c index 372d87c952a79..b95e2c41c942b 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 */ @@ -1802,6 +1802,58 @@ 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) +{ + struct mpfs_dev_s *priv = (struct mpfs_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 * @@ -1845,7 +1897,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; } @@ -1866,13 +1919,22 @@ 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; } /* 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); + } } /**************************************************************************** diff --git a/arch/risc-v/src/mpfs/mpfs_entrypoints.c b/arch/risc-v/src/mpfs/mpfs_entrypoints.c index f059e0ac2e84b..44fe89f7117f0 100644 --- a/arch/risc-v/src/mpfs/mpfs_entrypoints.c +++ b/arch/risc-v/src/mpfs/mpfs_entrypoints.c @@ -27,11 +27,18 @@ #ifdef CONFIG_MPFS_BOOTLOADER #include +#include #include #include +/**************************************************************************** + * Extern Function Declarations + ****************************************************************************/ + +extern void mpfs_opensbi_prepare_hart(void); + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -53,71 +60,48 @@ static uint64_t g_app_entrypoints[] = CONFIG_MPFS_HART4_ENTRYPOINT }; -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -static void jump_to_app(void) naked_function; -static void jump_to_app(void) -{ - __asm__ __volatile__ - ( - "csrr a0, mhartid\n" /* Hart ID */ - "slli t1, a0, 3\n" /* To entrypoint offset */ - "la t0, g_app_entrypoints\n" /* Entrypoint table base */ - "add t0, t0, t1\n" /* Index in table */ - "ld t0, 0(t0)\n" /* Load the address from table */ - "jr t0" /* Jump to entrypoint */ - ); -} - -/**************************************************************************** - * Public Data - ****************************************************************************/ - -/* Default boot address for every hart */ - -extern void mpfs_opensbi_prepare_hart(void); - -/* Trampoline functions, jump to SBI if so configured, to app if not */ - -const uint64_t g_entrypoints[5] = -{ -#ifdef CONFIG_MPFS_HART0_SBI - (uint64_t)mpfs_opensbi_prepare_hart, -#else - (uint64_t)jump_to_app, -#endif - +static uint64_t g_hart_use_sbi = #ifdef CONFIG_MPFS_HART1_SBI - (uint64_t)mpfs_opensbi_prepare_hart, -#else - (uint64_t)jump_to_app, + (1 << 1) | #endif #ifdef CONFIG_MPFS_HART2_SBI - (uint64_t)mpfs_opensbi_prepare_hart, -#else - (uint64_t)jump_to_app, + (1 << 2) | #endif #ifdef CONFIG_MPFS_HART3_SBI - (uint64_t)mpfs_opensbi_prepare_hart, -#else - (uint64_t)jump_to_app, + (1 << 3) | #endif #ifdef CONFIG_MPFS_HART4_SBI - (uint64_t)mpfs_opensbi_prepare_hart, -#else - (uint64_t)jump_to_app, + (1 << 4) | #endif -}; + 0; /**************************************************************************** * Public Functions ****************************************************************************/ +void mpfs_jump_to_app(void) naked_function; +void mpfs_jump_to_app(void) +{ + __asm__ __volatile__ + ( + "csrr a0, mhartid\n" /* Hart ID */ +#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 */ + "andi t0, t0, 1\n" /* Check the 0 bit */ + "bgtz t0, mpfs_opensbi_prepare_hart\n" /* If bit was 1, jump to sbi */ +#endif + "slli t1, a0, 3\n" /* To entrypoint offset */ + "la t0, g_app_entrypoints\n" /* Entrypoint table base */ + "add t0, t0, t1\n" /* Index in table */ + "ld t0, 0(t0)\n" /* Load the address from table */ + "jr t0\n" /* Jump to entrypoint */ + ); +} + /**************************************************************************** * Name: mpfs_set_entrypt * @@ -168,4 +152,37 @@ uintptr_t mpfs_get_entrypt(uint64_t hartid) return 0; } +/**************************************************************************** + * Name: mpfs_set_use_sbi + * + * Description: + * Set booting via SBI. + * + * Input Parameters: + * use_sbi - set to true if sbi is needed, false otherwise + * + * Returned value: + * OK on success, ERROR on failure + * + ****************************************************************************/ + +int mpfs_set_use_sbi(uint64_t hartid, bool use_sbi) +{ + if (hartid < ENTRYPT_CNT) + { + if (use_sbi) + { + g_hart_use_sbi |= (1 << hartid); + } + else + { + g_hart_use_sbi &= ~(1 << hartid); + } + + return OK; + } + + return ERROR; +} + #endif /* CONFIG_MPFS_BOOTLOADER */ diff --git a/arch/risc-v/src/mpfs/mpfs_entrypoints.h b/arch/risc-v/src/mpfs/mpfs_entrypoints.h new file mode 100644 index 0000000000000..949972db74f2c --- /dev/null +++ b/arch/risc-v/src/mpfs/mpfs_entrypoints.h @@ -0,0 +1,93 @@ +/**************************************************************************** + * arch/risc-v/src/mpfs/mpfs_entrypoints.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_ENTRYPOINTS_H +#define __ARCH_RISCV_SRC_MPFS_MPFS_ENTRYPOINTS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/**************************************************************************** + * Name: mpfs_get_entrypt + * + * Description: + * Obtain Hart entrypoint + * + * Input Parameters: + * hartid - Hart ID to read + * + * Returned value: + * Entrypoint on success; 0 on failure + * + ****************************************************************************/ + +uintptr_t mpfs_get_entrypt(uint64_t hartid); + +/**************************************************************************** + * Name: mpfs_set_entrypt + * + * Description: + * Modify Hart entrypoint + * + * Input Parameters: + * hartid - Hart ID to modify + * entry - Entrypoint to set + * + * Returned value: + * OK on success, ERROR on failure + * + ****************************************************************************/ + +int mpfs_set_entrypt(uint64_t hartid, uintptr_t entry); + +/**************************************************************************** + * Name: mpfs_set_use_sbi + * + * Description: + * Set booting via SBI. + * + * Input Parameters: + * use_sbi - set to true if sbi is needed, false otherwise + * + * Returned value: + * OK on success, ERROR on failure + * + ****************************************************************************/ + +int mpfs_set_use_sbi(uint64_t hartid, bool use_sbi); + +#if defined(__cplusplus) +} +#endif + +#endif /* __ARCH_RISCV_SRC_MPFS_MPFS_ENTRYPOINTS_H */ diff --git a/arch/risc-v/src/mpfs/mpfs_ethernet.c b/arch/risc-v/src/mpfs/mpfs_ethernet.c index 0d4a56411f4b3..eb0cf3157e8b2 100644 --- a/arch/risc-v/src/mpfs/mpfs_ethernet.c +++ b/arch/risc-v/src/mpfs/mpfs_ethernet.c @@ -158,6 +158,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) @@ -253,6 +257,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 */ @@ -369,6 +374,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 @@ -450,6 +456,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); @@ -1531,6 +1545,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; } @@ -1574,6 +1595,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. 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..7fa4996cfe697 --- /dev/null +++ b/arch/risc-v/src/mpfs/mpfs_fpga_canfd.c @@ -0,0 +1,2912 @@ +/**************************************************************************** + * 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) + { +#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++) + { + 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) + { + /* 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 */ diff --git a/arch/risc-v/src/mpfs/mpfs_head.S b/arch/risc-v/src/mpfs/mpfs_head.S index 5a02329181f47..af25f49b98ed5 100644 --- a/arch/risc-v/src/mpfs/mpfs_head.S +++ b/arch/risc-v/src/mpfs/mpfs_head.S @@ -161,17 +161,8 @@ __start: csrw mie, zero csrw mip, zero - /* Offset to g_entrypoints vector, acc. to hart id */ - li t1,8 - mul t1, a0, t1 - - /* Load the entrypoint address */ - la t0, g_entrypoints - add t0, t0, t1 - ld t0, 0(t0) - - /* Jump to app */ - jr t0 + /* Jump to application */ + j mpfs_jump_to_app .continue_boot: diff --git a/arch/risc-v/src/mpfs/mpfs_i2c.c b/arch/risc-v/src/mpfs/mpfs_i2c.c index 5e7bde97b0b2e..5a52e34286758 100644 --- a/arch/risc-v/src/mpfs/mpfs_i2c.c +++ b/arch/risc-v/src/mpfs/mpfs_i2c.c @@ -205,40 +205,6 @@ static int mpfs_i2c_setfrequency(struct mpfs_i2c_priv_s *priv, * Private Functions ****************************************************************************/ -/**************************************************************************** - * Name: mpfs_disable_interrupts - * - * Description: - * Disable all interrupts. - * - * Returned Value: - * primask (current interrupt status) - * - ****************************************************************************/ - -static irqstate_t mpfs_disable_interrupts(void) -{ - irqstate_t primask; - primask = up_irq_save(); - return primask; -} - -/**************************************************************************** - * Name: mpfs_restore_interrupts - * - * Description: - * Restore interrupts. - * - * Parameters: - * primask - Earlier stored irqstate - * - ****************************************************************************/ - -static void mpfs_restore_interrupts(irqstate_t primask) -{ - up_irq_restore(primask); -} - /**************************************************************************** * Name: mpfs_i2c_init * @@ -256,12 +222,8 @@ static void mpfs_restore_interrupts(irqstate_t primask) static int mpfs_i2c_init(struct mpfs_i2c_priv_s *priv) { - uint32_t primask; - if (!priv->initialized) { - primask = mpfs_disable_interrupts(); - if (priv->id == 0) { modifyreg32(MPFS_SYSREG_SOFT_RESET_CR, @@ -299,8 +261,6 @@ static int mpfs_i2c_init(struct mpfs_i2c_priv_s *priv) MPFS_I2C_CTRL_ENS1_MASK); priv->initialized = true; - - mpfs_restore_interrupts(primask); } return OK; @@ -492,6 +452,12 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg) priv->status = MPFS_I2C_SUCCESS; break; + case MPFS_I2C_ST_IDLE: + + /* No activity, bus idle */ + + break; + case MPFS_I2C_ST_RESET_ACTIVATED: case MPFS_I2C_ST_BUS_ERROR: /* Bus errors */ default: @@ -540,15 +506,8 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg) static void mpfs_i2c_sendstart(struct mpfs_i2c_priv_s *priv) { - uint32_t primask; - - primask = mpfs_disable_interrupts(); - - modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_STA_MASK, MPFS_I2C_CTRL_STA_MASK); - up_enable_irq(priv->plic_irq); - - mpfs_restore_interrupts(primask); + modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_STA_MASK, MPFS_I2C_CTRL_STA_MASK); } static int mpfs_i2c_transfer(struct i2c_master_s *dev, @@ -668,9 +627,16 @@ static int mpfs_i2c_reset(struct i2c_master_s *dev) { struct mpfs_i2c_priv_s *priv = (struct mpfs_i2c_priv_s *)dev; int ret; + irqstate_t flags; DEBUGASSERT(priv != NULL); + flags = enter_critical_section(); + + /* Disabling I2C interrupts. + * NOTE: up_enable_irq() will be called at mpfs_i2c_sendstart() + */ + up_disable_irq(priv->plic_irq); priv->initialized = false; @@ -678,7 +644,7 @@ static int mpfs_i2c_reset(struct i2c_master_s *dev) ret = mpfs_i2c_init(priv); if (ret != OK) { - up_enable_irq(priv->plic_irq); + leave_critical_section(flags); return ret; } @@ -687,7 +653,7 @@ static int mpfs_i2c_reset(struct i2c_master_s *dev) priv->rx_size = 0; priv->rx_idx = 0; - /* up_enable_irq() will be called at mpfs_i2c_sendstart() */ + leave_critical_section(flags); return OK; } diff --git a/arch/risc-v/src/mpfs/mpfs_ihc.c b/arch/risc-v/src/mpfs/mpfs_ihc.c index 69e7ec4d2a53c..386999267e8ff 100644 --- a/arch/risc-v/src/mpfs/mpfs_ihc.c +++ b/arch/risc-v/src/mpfs/mpfs_ihc.c @@ -86,24 +86,23 @@ #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 */ -#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 /**************************************************************************** @@ -169,7 +168,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]; @@ -437,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)); @@ -982,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); @@ -1141,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; @@ -1255,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 */ diff --git a/arch/risc-v/src/opensbi/Make.defs b/arch/risc-v/src/opensbi/Make.defs index 1b213d960310e..94db1c4034dbf 100644 --- a/arch/risc-v/src/opensbi/Make.defs +++ b/arch/risc-v/src/opensbi/Make.defs @@ -37,10 +37,10 @@ INCLUDES += $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)opensbi$(DELIM)open SBI_DIR := opensbi OPENSBI_UNPACK = opensbi-3rdparty -OPENSBI_COMMIT = 4998a712b2ab504eff306110879ee05af6050177 -OPENSBI_URL = https://github.com/riscv-software-src/opensbi/tarball +OPENSBI_COMMIT = b18bb7ce78d4e5504a9cbd8df7b57d795f489a0a +OPENSBI_URL = https://github.com/tiiuae/opensbi/tarball OPENSBI_TARBALL = opensbi.tar.gz -OPENSBI_DIR = riscv-software-src-opensbi-4998a71 +OPENSBI_DIR = tiiuae-opensbi-b18bb7c $(OPENSBI_TARBALL): $(Q) echo "Downloading: OpenSBI" diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/configs/mcuboot_slot_confirm/defconfig b/boards/risc-v/esp32c3/esp32c3-devkit/configs/mcuboot_slot_confirm/defconfig index 45cd0adccbd52..fecfd9755e858 100644 --- a/boards/risc-v/esp32c3/esp32c3-devkit/configs/mcuboot_slot_confirm/defconfig +++ b/boards/risc-v/esp32c3/esp32c3-devkit/configs/mcuboot_slot_confirm/defconfig @@ -25,7 +25,6 @@ CONFIG_DEV_ZERO=y CONFIG_ESP32C3_APP_FORMAT_MCUBOOT=y CONFIG_ESP32C3_ESPTOOL_TARGET_SECONDARY=y CONFIG_ESP32C3_SPIFLASH=y -CONFIG_EXAMPLES_MCUBOOT_SLOT_CONFIRM=y CONFIG_EXPERIMENTAL=y CONFIG_FS_PROCFS=y CONFIG_FS_SMARTFS=y 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..32507993c60e8 --- /dev/null +++ b/boards/risc-v/mpfs/icicle/configs/canfd/defconfig @@ -0,0 +1,84 @@ +# +# 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_NET_ETHERNET is not set +# CONFIG_NET_IPv4 is not set +# CONFIG_NSH_DISABLE_LOSMART 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_NET=y +CONFIG_DEBUG_NET_ERROR=y +CONFIG_DEBUG_NET_INFO=y +CONFIG_DEBUG_NET_WARN=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEBUG_WARN=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_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 +CONFIG_NSH_DISABLE_UMOUNT=y +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 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 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..78d417dfdee52 --- /dev/null +++ b/boards/risc-v/mpfs/icicle/configs/standalone/defconfig @@ -0,0 +1,62 @@ +# +# 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_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 diff --git a/drivers/can/can.c b/drivers/can/can.c index 6885732fd39c0..7e838c168f76a 100644 --- a/drivers/can/can.c +++ b/drivers/can/can.c @@ -506,7 +506,7 @@ static ssize_t can_read(FAR struct file *filep, FAR char *buffer, FAR struct can_dev_s *dev = inode->i_private; #endif - caninfo("buflen: %d\n", buflen); + caninfo("buflen: %zu\n", buflen); /* The caller must provide enough memory to catch the smallest possible * message. This is not a system error condition, but we won't permit @@ -743,7 +743,7 @@ static ssize_t can_write(FAR struct file *filep, FAR const char *buffer, int msglen; int ret = 0; - caninfo("buflen: %d\n", buflen); + caninfo("buflen: %zu\n", buflen); /* Interrupts must disabled throughout the following */ diff --git a/drivers/net/rpmsgdrv.c b/drivers/net/rpmsgdrv.c index 2873b50f73c08..5df10155a88ff 100644 --- a/drivers/net/rpmsgdrv.c +++ b/drivers/net/rpmsgdrv.c @@ -610,6 +610,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; @@ -1111,6 +1118,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 */ @@ -1150,6 +1158,6 @@ int net_rpmsg_drv_init(FAR const char *cpuname, /* 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; } diff --git a/include/nuttx/clock.h b/include/nuttx/clock.h index 3a641c144fec7..0ca726e0ce5ea 100644 --- a/include/nuttx/clock.h +++ b/include/nuttx/clock.h @@ -145,41 +145,49 @@ * preferred for that reason (at the risk of overflow) */ -#define TICK_PER_HOUR (USEC_PER_HOUR / USEC_PER_TICK) /* Truncates! */ -#define TICK_PER_MIN (USEC_PER_MIN / USEC_PER_TICK) /* Truncates! */ -#define TICK_PER_SEC (USEC_PER_SEC / USEC_PER_TICK) /* Truncates! */ -#define TICK_PER_MSEC (USEC_PER_MSEC / USEC_PER_TICK) /* Truncates! */ -#define TICK_PER_DSEC (USEC_PER_DSEC / USEC_PER_TICK) /* Truncates! */ -#define TICK_PER_HSEC (USEC_PER_HSEC / USEC_PER_TICK) /* Truncates! */ +/* TICK_PER_* truncates! */ -#define MSEC_PER_TICK (USEC_PER_TICK / USEC_PER_MSEC) /* Truncates! */ -#define NSEC_PER_TICK (USEC_PER_TICK * NSEC_PER_USEC) /* Exact */ +#define TICK_PER_HOUR (USEC_PER_HOUR / USEC_PER_TICK) +#define TICK_PER_MIN (USEC_PER_MIN / USEC_PER_TICK) +#define TICK_PER_SEC (USEC_PER_SEC / USEC_PER_TICK) +#define TICK_PER_MSEC (USEC_PER_MSEC / USEC_PER_TICK) +#define TICK_PER_DSEC (USEC_PER_DSEC / USEC_PER_TICK) +#define TICK_PER_HSEC (USEC_PER_HSEC / USEC_PER_TICK) -#define NSEC2TICK(nsec) (((nsec)+(NSEC_PER_TICK/2))/NSEC_PER_TICK) /* Rounds */ -#define USEC2TICK(usec) (((usec)+(USEC_PER_TICK/2))/USEC_PER_TICK) /* Rounds */ +/* MSEC_PER_TICK truncates! */ + +#define MSEC_PER_TICK (USEC_PER_TICK / USEC_PER_MSEC) +#define NSEC_PER_TICK (USEC_PER_TICK * NSEC_PER_USEC) + +/* ?SEC2TIC rounds up */ + +#define NSEC2TICK(nsec) (((nsec) + (NSEC_PER_TICK - 1)) / NSEC_PER_TICK) +#define USEC2TICK(usec) (((usec) + (USEC_PER_TICK - 1)) / USEC_PER_TICK) #if (MSEC_PER_TICK * USEC_PER_MSEC) == USEC_PER_TICK -# define MSEC2TICK(msec) (((msec)+(MSEC_PER_TICK/2))/MSEC_PER_TICK) /* Rounds */ +# define MSEC2TICK(msec) (((msec) + (MSEC_PER_TICK - 1)) / MSEC_PER_TICK) #else -# define MSEC2TICK(msec) USEC2TICK((msec) * USEC_PER_MSEC) /* Rounds */ +# define MSEC2TICK(msec) USEC2TICK((msec) * USEC_PER_MSEC) #endif -#define DSEC2TICK(dsec) MSEC2TICK((dsec) * MSEC_PER_DSEC) /* Rounds */ -#define HSEC2TICK(dsec) MSEC2TICK((dsec) * MSEC_PER_HSEC) /* Rounds */ -#define SEC2TICK(sec) MSEC2TICK((sec) * MSEC_PER_SEC) /* Rounds */ +#define DSEC2TICK(dsec) MSEC2TICK((dsec) * MSEC_PER_DSEC) +#define HSEC2TICK(dsec) MSEC2TICK((dsec) * MSEC_PER_HSEC) +#define SEC2TICK(sec) MSEC2TICK((sec) * MSEC_PER_SEC) -#define TICK2NSEC(tick) ((tick) * NSEC_PER_TICK) /* Exact */ -#define TICK2USEC(tick) ((tick) * USEC_PER_TICK) /* Exact */ +#define TICK2NSEC(tick) ((tick) * NSEC_PER_TICK) +#define TICK2USEC(tick) ((tick) * USEC_PER_TICK) #if (MSEC_PER_TICK * USEC_PER_MSEC) == USEC_PER_TICK -# define TICK2MSEC(tick) ((tick)*MSEC_PER_TICK) /* Exact */ +# define TICK2MSEC(tick) ((tick) * MSEC_PER_TICK) #else -# define TICK2MSEC(tick) (((tick)*USEC_PER_TICK)/USEC_PER_MSEC) /* Rounds */ +# define TICK2MSEC(tick) (((tick) * USEC_PER_TICK) / USEC_PER_MSEC) #endif -#define TICK2DSEC(tick) (((tick)+(TICK_PER_DSEC/2))/TICK_PER_DSEC) /* Rounds */ -#define TICK2HSEC(tick) (((tick)+(TICK_PER_HSEC/2))/TICK_PER_HSEC) /* Rounds */ -#define TICK2SEC(tick) (((tick)+(TICK_PER_SEC/2))/TICK_PER_SEC) /* Rounds */ +/* TIC2?SEC rounds to nearest */ + +#define TICK2DSEC(tick) (((tick) + (TICK_PER_DSEC / 2)) / TICK_PER_DSEC) +#define TICK2HSEC(tick) (((tick) + (TICK_PER_HSEC / 2)) / TICK_PER_HSEC) +#define TICK2SEC(tick) (((tick) + (TICK_PER_SEC / 2)) / TICK_PER_SEC) #if defined(CONFIG_DEBUG_FEATURES) && defined(CONFIG_SYSTEM_TIME64) && \ !defined(CONFIG_SCHED_TICKLESS) diff --git a/mm/mempool/mempool_multiple.c b/mm/mempool/mempool_multiple.c index 0ca738be06010..afa6a5e97950f 100644 --- a/mm/mempool/mempool_multiple.c +++ b/mm/mempool/mempool_multiple.c @@ -220,7 +220,7 @@ mempool_multiple_get_dict(FAR struct mempool_multiple_s *mpool, col = index - (row << mpool->dict_col_num_log2); if (mpool->dict[row] == NULL || mpool->dict[row][col].addr != addr || - blk - addr >= mpool->dict[row][col].size) + (FAR char *)blk - (FAR char *)addr >= mpool->dict[row][col].size) { return NULL; } diff --git a/net/rpmsg/rpmsg_sockif.c b/net/rpmsg/rpmsg_sockif.c index 3852be3d2b5db..10620224de4a8 100644 --- a/net/rpmsg/rpmsg_sockif.c +++ b/net/rpmsg/rpmsg_sockif.c @@ -1028,7 +1028,6 @@ static ssize_t rpmsg_socket_send_continuous(FAR struct socket *psock, nxmutex_unlock(&conn->sendlock); if (ret < 0) { - rpmsg_release_tx_buffer(&conn->ept, msg); break; } @@ -1127,10 +1126,6 @@ static ssize_t rpmsg_socket_send_single(FAR struct socket *psock, ret = rpmsg_sendto_nocopy(&conn->ept, msg, total, conn->ept.dest_addr); nxmutex_unlock(&conn->sendlock); - if (ret < 0) - { - rpmsg_release_tx_buffer(&conn->ept, msg); - } return ret > 0 ? len : ret; } diff --git a/openamp/0001-openamp-add-ns_unbind_notify-support.patch b/openamp/0001-openamp-add-ns_unbind_notify-support.patch new file mode 100644 index 0000000000000..d3fad4628da38 --- /dev/null +++ b/openamp/0001-openamp-add-ns_unbind_notify-support.patch @@ -0,0 +1,42 @@ +From 57afc457bc16cca04762391f77d22b9219cb0e5f Mon Sep 17 00:00:00 2001 +From: Guiding Li +Date: Tue, 20 Jul 2021 17:52:13 +0800 +Subject: [PATCH 01/12] openamp: add ns_unbind_notify support + +This is for notify rdev unbind event + +Signed-off-by: Guiding Li +--- + lib/include/openamp/rpmsg.h | 1 + + lib/rpmsg/rpmsg_virtio.c | 3 +++ + 2 files changed, 4 insertions(+) + +diff --git a/lib/include/openamp/rpmsg.h open-amp/lib/include/openamp/rpmsg.h +index 8b8ec2e..e6acce8 100644 +--- a/lib/include/openamp/rpmsg.h ++++ open-amp/lib/include/openamp/rpmsg.h +@@ -118,6 +118,7 @@ struct rpmsg_device { + unsigned long bitmap[metal_bitmap_longs(RPMSG_ADDR_BMP_SIZE)]; + metal_mutex_t lock; + rpmsg_ns_bind_cb ns_bind_cb; ++ rpmsg_ns_bind_cb ns_unbind_cb; + struct rpmsg_device_ops ops; + bool support_ns; + }; +diff --git a/lib/rpmsg/rpmsg_virtio.c open-amp/lib/rpmsg/rpmsg_virtio.c +index 57a2083..d5f168c 100644 +--- a/lib/rpmsg/rpmsg_virtio.c ++++ open-amp/lib/rpmsg/rpmsg_virtio.c +@@ -585,6 +585,9 @@ static int rpmsg_virtio_ns_callback(struct rpmsg_endpoint *ept, void *data, + metal_mutex_release(&rdev->lock); + if (_ept && _ept->ns_unbind_cb) + _ept->ns_unbind_cb(_ept); ++ if (rdev->ns_unbind_cb) ++ rdev->ns_unbind_cb(rdev, name, dest); ++ + } else { + if (!_ept) { + /* +-- +2.25.1 + diff --git a/openamp/0001-ns-acknowledge-the-received-creation-message.patch b/openamp/0002-ns-acknowledge-the-received-creation-message.patch similarity index 84% rename from openamp/0001-ns-acknowledge-the-received-creation-message.patch rename to openamp/0002-ns-acknowledge-the-received-creation-message.patch index 1f7ebb421aadd..7a74173cb3834 100644 --- a/openamp/0001-ns-acknowledge-the-received-creation-message.patch +++ b/openamp/0002-ns-acknowledge-the-received-creation-message.patch @@ -1,7 +1,7 @@ -From 1e43e60aa7ae118309cf256c50bd17f313540eba Mon Sep 17 00:00:00 2001 +From 73d9754ab14a2b5c3e25574ec860489031e32f00 Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Mon, 7 Jan 2019 02:15:42 +0800 -Subject: [PATCH 01/10] ns: acknowledge the received creation message +Subject: [PATCH 02/12] ns: acknowledge the received creation message the two phase handsake make the client could initiate the transfer immediately without the server side send any dummy message first. @@ -12,14 +12,14 @@ Signed-off-by: Xiang Xiao lib/include/openamp/rpmsg_virtio.h | 1 + lib/rpmsg/rpmsg.c | 5 ++++- lib/rpmsg/rpmsg_internal.h | 4 ++-- - lib/rpmsg/rpmsg_virtio.c | 15 ++++++++++++--- - 5 files changed, 20 insertions(+), 6 deletions(-) + lib/rpmsg/rpmsg_virtio.c | 16 ++++++++++++---- + 5 files changed, 20 insertions(+), 7 deletions(-) diff --git a/lib/include/openamp/rpmsg.h open-amp/lib/include/openamp/rpmsg.h -index 64678cfc..ff3ff8fb 100644 +index e6acce8..3560bb5 100644 --- a/lib/include/openamp/rpmsg.h +++ open-amp/lib/include/openamp/rpmsg.h -@@ -126,6 +126,7 @@ struct rpmsg_device { +@@ -121,6 +121,7 @@ struct rpmsg_device { rpmsg_ns_bind_cb ns_unbind_cb; struct rpmsg_device_ops ops; bool support_ns; @@ -28,7 +28,7 @@ index 64678cfc..ff3ff8fb 100644 /** diff --git a/lib/include/openamp/rpmsg_virtio.h open-amp/lib/include/openamp/rpmsg_virtio.h -index 80ce9981..874c9723 100644 +index ff1e171..255396c 100644 --- a/lib/include/openamp/rpmsg_virtio.h +++ open-amp/lib/include/openamp/rpmsg_virtio.h @@ -28,6 +28,7 @@ extern "C" { @@ -40,10 +40,10 @@ index 80ce9981..874c9723 100644 /** * struct rpmsg_virtio_shm_pool - shared memory pool used for rpmsg buffers diff --git a/lib/rpmsg/rpmsg.c open-amp/lib/rpmsg/rpmsg.c -index 0d3e1d03..e8757d80 100644 +index 214b2a9..ba2b7a8 100644 --- a/lib/rpmsg/rpmsg.c +++ open-amp/lib/rpmsg/rpmsg.c -@@ -317,10 +317,13 @@ int rpmsg_create_ept(struct rpmsg_endpoint *ept, struct rpmsg_device *rdev, +@@ -302,10 +302,13 @@ int rpmsg_create_ept(struct rpmsg_endpoint *ept, struct rpmsg_device *rdev, rpmsg_register_endpoint(rdev, ept, name, addr, dest, cb, unbind_cb); metal_mutex_release(&rdev->lock); @@ -59,7 +59,7 @@ index 0d3e1d03..e8757d80 100644 if (status) rpmsg_unregister_endpoint(ept); diff --git a/lib/rpmsg/rpmsg_internal.h open-amp/lib/rpmsg/rpmsg_internal.h -index ab6e0f29..3e6ae37f 100644 +index ab6e0f2..3e6ae37 100644 --- a/lib/rpmsg/rpmsg_internal.h +++ open-amp/lib/rpmsg/rpmsg_internal.h @@ -39,12 +39,12 @@ extern "C" { @@ -78,10 +78,10 @@ index ab6e0f29..3e6ae37f 100644 /** diff --git a/lib/rpmsg/rpmsg_virtio.c open-amp/lib/rpmsg/rpmsg_virtio.c -index cab72e68..5726c2ca 100644 +index d5f168c..0868f71 100644 --- a/lib/rpmsg/rpmsg_virtio.c +++ open-amp/lib/rpmsg/rpmsg_virtio.c -@@ -638,7 +638,7 @@ static int rpmsg_virtio_ns_callback(struct rpmsg_endpoint *ept, void *data, +@@ -579,7 +579,7 @@ static int rpmsg_virtio_ns_callback(struct rpmsg_endpoint *ept, void *data, metal_mutex_acquire(&rdev->lock); _ept = rpmsg_get_endpoint(rdev, name, RPMSG_ADDR_ANY, dest); @@ -90,16 +90,17 @@ index cab72e68..5726c2ca 100644 if (_ept) _ept->dest_addr = RPMSG_ADDR_ANY; metal_mutex_release(&rdev->lock); -@@ -646,7 +646,7 @@ static int rpmsg_virtio_ns_callback(struct rpmsg_endpoint *ept, void *data, +@@ -587,8 +587,7 @@ static int rpmsg_virtio_ns_callback(struct rpmsg_endpoint *ept, void *data, _ept->ns_unbind_cb(_ept); if (rdev->ns_unbind_cb) rdev->ns_unbind_cb(rdev, name, dest); +- - } else { + } else if (ns_msg->flags == RPMSG_NS_CREATE) { if (!_ept) { /* * send callback to application, that can -@@ -660,7 +660,15 @@ static int rpmsg_virtio_ns_callback(struct rpmsg_endpoint *ept, void *data, +@@ -602,7 +601,15 @@ static int rpmsg_virtio_ns_callback(struct rpmsg_endpoint *ept, void *data, } else { _ept->dest_addr = dest; metal_mutex_release(&rdev->lock); @@ -115,7 +116,7 @@ index cab72e68..5726c2ca 100644 } return RPMSG_SUCCESS; -@@ -745,6 +753,7 @@ int rpmsg_init_vdev_with_config(struct rpmsg_virtio_device *rvdev, +@@ -683,6 +690,7 @@ int rpmsg_init_vdev_with_config(struct rpmsg_virtio_device *rvdev, #endif /*!VIRTIO_DRIVER_ONLY*/ vdev->features = rpmsg_virtio_get_features(rvdev); rdev->support_ns = !!(vdev->features & (1 << VIRTIO_RPMSG_F_NS)); @@ -123,7 +124,7 @@ index cab72e68..5726c2ca 100644 #ifndef VIRTIO_DEVICE_ONLY if (role == RPMSG_HOST) { -@@ -841,7 +850,7 @@ int rpmsg_init_vdev_with_config(struct rpmsg_virtio_device *rvdev, +@@ -778,7 +786,7 @@ int rpmsg_init_vdev_with_config(struct rpmsg_virtio_device *rvdev, * Create name service announcement endpoint if device supports name * service announcement feature. */ diff --git a/openamp/0002-Negotiate-individual-buffer-size-dynamically.patch b/openamp/0003-Negotiate-individual-buffer-size-dynamically.patch similarity index 88% rename from openamp/0002-Negotiate-individual-buffer-size-dynamically.patch rename to openamp/0003-Negotiate-individual-buffer-size-dynamically.patch index a309b31d43669..bff1f954c266b 100644 --- a/openamp/0002-Negotiate-individual-buffer-size-dynamically.patch +++ b/openamp/0003-Negotiate-individual-buffer-size-dynamically.patch @@ -1,13 +1,14 @@ -From 285e4d359458ef09d397a41de04ada9a6b8d48e7 Mon Sep 17 00:00:00 2001 +From c3949d3b4a8883ec54f5db9ae55acac5ada75b81 Mon Sep 17 00:00:00 2001 From: Chao An Date: Mon, 10 Dec 2018 16:26:39 +0800 -Subject: [PATCH 02/10] Negotiate individual buffer size dynamically +Subject: [PATCH 03/12] Negotiate individual buffer size dynamically If slave support VIRTIO_RPMSG_F_BUFSZ(0x04) feature, master determine the buffer size from config space(first 8 bytes), otherwise the default size(512 bytes) will be used. Signed-off-by: Chao An +Signed-off-by: ligd --- lib/include/openamp/remoteproc.h | 17 +++++++++++++++++ lib/include/openamp/rpmsg_virtio.h | 4 +++- @@ -15,7 +16,7 @@ Signed-off-by: Chao An 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/lib/include/openamp/remoteproc.h open-amp/lib/include/openamp/remoteproc.h -index 7c79a292..d1efab85 100644 +index 41f5d57..e9111ff 100644 --- a/lib/include/openamp/remoteproc.h +++ open-amp/lib/include/openamp/remoteproc.h @@ -303,6 +303,23 @@ struct fw_rsc_vdev { @@ -43,7 +44,7 @@ index 7c79a292..d1efab85 100644 * struct fw_rsc_vendor - remote processor vendor specific resource * @len: length of the resource diff --git a/lib/include/openamp/rpmsg_virtio.h open-amp/lib/include/openamp/rpmsg_virtio.h -index 874c9723..0b22e840 100644 +index 255396c..aaba7e1 100644 --- a/lib/include/openamp/rpmsg_virtio.h +++ open-amp/lib/include/openamp/rpmsg_virtio.h @@ -16,6 +16,7 @@ @@ -62,7 +63,7 @@ index 874c9723..0b22e840 100644 /** * struct rpmsg_virtio_shm_pool - shared memory pool used for rpmsg buffers -@@ -72,7 +74,7 @@ struct rpmsg_virtio_config { +@@ -68,7 +70,7 @@ struct rpmsg_virtio_config { */ struct rpmsg_virtio_device { struct rpmsg_device rdev; @@ -72,10 +73,10 @@ index 874c9723..0b22e840 100644 struct virtqueue *rvq; struct virtqueue *svq; diff --git a/lib/rpmsg/rpmsg_virtio.c open-amp/lib/rpmsg/rpmsg_virtio.c -index 5726c2ca..69537399 100644 +index 0868f71..186f23f 100644 --- a/lib/rpmsg/rpmsg_virtio.c +++ open-amp/lib/rpmsg/rpmsg_virtio.c -@@ -737,7 +737,8 @@ int rpmsg_init_vdev_with_config(struct rpmsg_virtio_device *rvdev, +@@ -674,7 +674,8 @@ int rpmsg_init_vdev_with_config(struct rpmsg_virtio_device *rvdev, if (config == NULL) { return RPMSG_ERR_PARAM; } @@ -85,7 +86,7 @@ index 5726c2ca..69537399 100644 } #else /*!VIRTIO_DEVICE_ONLY*/ /* Ignore passed config in the virtio-device-only configuration. */ -@@ -755,6 +756,13 @@ int rpmsg_init_vdev_with_config(struct rpmsg_virtio_device *rvdev, +@@ -692,6 +693,13 @@ int rpmsg_init_vdev_with_config(struct rpmsg_virtio_device *rvdev, rdev->support_ns = !!(vdev->features & (1 << VIRTIO_RPMSG_F_NS)); rdev->support_ack = !!(vdev->features & (1 << VIRTIO_RPMSG_F_ACK)); diff --git a/openamp/0003-rpmsg-wait-endpoint-ready-in-rpmsg_send-and-rpmsg_se.patch b/openamp/0004-rpmsg-wait-endpoint-ready-in-rpmsg_send-and-rpmsg_se.patch similarity index 83% rename from openamp/0003-rpmsg-wait-endpoint-ready-in-rpmsg_send-and-rpmsg_se.patch rename to openamp/0004-rpmsg-wait-endpoint-ready-in-rpmsg_send-and-rpmsg_se.patch index 9bbcc089fdc2e..f94531e1155b2 100644 --- a/openamp/0003-rpmsg-wait-endpoint-ready-in-rpmsg_send-and-rpmsg_se.patch +++ b/openamp/0004-rpmsg-wait-endpoint-ready-in-rpmsg_send-and-rpmsg_se.patch @@ -1,7 +1,7 @@ -From 931cd95ab99550befa75703cc36d5e6f6964b63e Mon Sep 17 00:00:00 2001 +From 415f9cdcf5a93cd018fa920e53a9090d5ec94c37 Mon Sep 17 00:00:00 2001 From: Guiding Li Date: Wed, 20 Feb 2019 11:36:57 +0800 -Subject: [PATCH 03/10] rpmsg: wait endpoint ready in rpmsg_send and +Subject: [PATCH 04/12] rpmsg: wait endpoint ready in rpmsg_send and rpmsg_send_nocopy because the remote need time to return the destination address @@ -9,11 +9,11 @@ because the remote need time to return the destination address Signed-off-by: Guiding Li --- lib/include/openamp/rpmsg.h | 59 ++++++++++++++++++++++++++----------- - lib/rpmsg/rpmsg_virtio.c | 7 ----- - 2 files changed, 42 insertions(+), 24 deletions(-) + lib/rpmsg/rpmsg_virtio.c | 8 ----- + 2 files changed, 42 insertions(+), 25 deletions(-) diff --git a/lib/include/openamp/rpmsg.h open-amp/lib/include/openamp/rpmsg.h -index ff3ff8fb..dbe42ea6 100644 +index 3560bb5..11c3ccb 100644 --- a/lib/include/openamp/rpmsg.h +++ open-amp/lib/include/openamp/rpmsg.h @@ -15,6 +15,7 @@ @@ -37,7 +37,7 @@ index ff3ff8fb..dbe42ea6 100644 /* Error macros. */ #define RPMSG_SUCCESS 0 #define RPMSG_ERROR_BASE -2000 -@@ -147,6 +154,19 @@ int rpmsg_send_offchannel_raw(struct rpmsg_endpoint *ept, uint32_t src, +@@ -142,6 +149,19 @@ int rpmsg_send_offchannel_raw(struct rpmsg_endpoint *ept, uint32_t src, uint32_t dst, const void *data, int len, int wait); @@ -57,17 +57,14 @@ index ff3ff8fb..dbe42ea6 100644 /** * rpmsg_send() - send a message across to the remote processor * @ept: the rpmsg endpoint -@@ -165,11 +185,20 @@ int rpmsg_send_offchannel_raw(struct rpmsg_endpoint *ept, uint32_t src, +@@ -160,8 +180,17 @@ int rpmsg_send_offchannel_raw(struct rpmsg_endpoint *ept, uint32_t src, static inline int rpmsg_send(struct rpmsg_endpoint *ept, const void *data, int len) { -+ int tc = 0; -+ - if (!ept) - return RPMSG_ERR_PARAM; - - return rpmsg_send_offchannel_raw(ept, ept->addr, ept->dest_addr, data, - len, true); ++ int tc = 0; ++ + for (; tc < RPMSG_TICK_COUNT; tc += RPMSG_TICKS_PER_INTERVAL) { + if (is_rpmsg_ept_ready(ept)) + return rpmsg_send_offchannel_raw(ept, ept->addr, @@ -80,17 +77,14 @@ index ff3ff8fb..dbe42ea6 100644 } /** -@@ -476,11 +505,20 @@ static inline int rpmsg_sendto_nocopy(struct rpmsg_endpoint *ept, +@@ -434,8 +463,17 @@ static inline int rpmsg_sendto_nocopy(struct rpmsg_endpoint *ept, static inline int rpmsg_send_nocopy(struct rpmsg_endpoint *ept, const void *data, int len) { -+ int tc = 0; -+ - if (!ept) - return RPMSG_ERR_PARAM; - - return rpmsg_send_offchannel_nocopy(ept, ept->addr, - ept->dest_addr, data, len); ++ int tc = 0; ++ + for (; tc < RPMSG_TICK_COUNT; tc += RPMSG_TICKS_PER_INTERVAL) { + if (is_rpmsg_ept_ready(ept)) + return rpmsg_send_offchannel_nocopy(ept, ept->addr, @@ -103,7 +97,7 @@ index ff3ff8fb..dbe42ea6 100644 } /** -@@ -524,19 +562,6 @@ int rpmsg_create_ept(struct rpmsg_endpoint *ept, struct rpmsg_device *rdev, +@@ -508,19 +546,6 @@ int rpmsg_create_ept(struct rpmsg_endpoint *ept, struct rpmsg_device *rdev, */ void rpmsg_destroy_ept(struct rpmsg_endpoint *ept); @@ -124,7 +118,7 @@ index ff3ff8fb..dbe42ea6 100644 } #endif diff --git a/lib/rpmsg/rpmsg_virtio.c open-amp/lib/rpmsg/rpmsg_virtio.c -index 69537399..c56e0cea 100644 +index 186f23f..d19d3b1 100644 --- a/lib/rpmsg/rpmsg_virtio.c +++ open-amp/lib/rpmsg/rpmsg_virtio.c @@ -10,7 +10,6 @@ @@ -135,7 +129,7 @@ index 69537399..c56e0cea 100644 #include #include #include -@@ -19,12 +18,6 @@ +@@ -19,13 +18,6 @@ #define RPMSG_NUM_VRINGS 2 @@ -145,9 +139,10 @@ index 69537399..c56e0cea 100644 -/* Time to wait - In multiple of 1 msecs. */ -#define RPMSG_TICKS_PER_INTERVAL 1000 - - /** - * struct vbuff_reclaimer_t - vring buffer recycler - * +- + /* Default configuration */ + #ifndef VIRTIO_DEVICE_ONLY + #define RPMSG_VIRTIO_DEFAULT_CONFIG \ -- 2.25.1 diff --git a/openamp/0004-openamp-add-new-ops-notify_wait-support.patch b/openamp/0005-openamp-add-new-ops-notify_wait-support.patch similarity index 82% rename from openamp/0004-openamp-add-new-ops-notify_wait-support.patch rename to openamp/0005-openamp-add-new-ops-notify_wait-support.patch index c7b4c68ba4253..91d052dbe902f 100644 --- a/openamp/0004-openamp-add-new-ops-notify_wait-support.patch +++ b/openamp/0005-openamp-add-new-ops-notify_wait-support.patch @@ -1,12 +1,11 @@ -From ddc209c9475a2822ffe5d18441bd01718acdbc11 Mon Sep 17 00:00:00 2001 -From: ligd -Date: Fri, 29 Jul 2022 22:57:23 +0800 -Subject: [PATCH 04/10] openamp: add new ops notify_wait() support +From 00d0f99b49a5647107bc16249a141d1c727ec11e Mon Sep 17 00:00:00 2001 +From: Guiding Li +Date: Thu, 18 Nov 2021 20:54:45 +0800 +Subject: [PATCH 2/9] openamp: add new ops notify_wait() support This can avoid looping check tx buffer -Change-Id: Ie340ed06c306ce978ff165aacaf5b830e3645af8 -Signed-off-by: ligd +Signed-off-by: Guiding Li --- lib/include/openamp/remoteproc.h | 12 ++++++++++++ lib/include/openamp/remoteproc_virtio.h | 2 ++ @@ -15,11 +14,11 @@ Signed-off-by: ligd lib/include/openamp/virtio.h | 1 + lib/remoteproc/remoteproc.c | 11 +++++++++++ lib/remoteproc/remoteproc_virtio.c | 14 ++++++++++++++ - lib/rpmsg/rpmsg_virtio.c | 7 +++++++ - 8 files changed, 57 insertions(+) + lib/rpmsg/rpmsg_virtio.c | 5 +++++ + 8 files changed, 55 insertions(+) diff --git a/lib/include/openamp/remoteproc.h open-amp/lib/include/openamp/remoteproc.h -index d1efab85..f6554404 100644 +index e9111ff..d276550 100644 --- a/lib/include/openamp/remoteproc.h +++ open-amp/lib/include/openamp/remoteproc.h @@ -428,6 +428,18 @@ struct remoteproc_ops { @@ -42,10 +41,10 @@ index d1efab85..f6554404 100644 * get_mem * diff --git a/lib/include/openamp/remoteproc_virtio.h open-amp/lib/include/openamp/remoteproc_virtio.h -index 6609a1fd..e65488d5 100644 +index 70cff97..eaca76a 100644 --- a/lib/include/openamp/remoteproc_virtio.h +++ open-amp/lib/include/openamp/remoteproc_virtio.h -@@ -25,6 +25,7 @@ extern "C" { +@@ -22,6 +22,7 @@ extern "C" { /* define vdev notification function user should implement */ typedef int (*rpvdev_notify_func)(void *priv, uint32_t id); @@ -53,7 +52,7 @@ index 6609a1fd..e65488d5 100644 /** * struct remoteproc_virtio -@@ -40,6 +41,7 @@ struct remoteproc_virtio { +@@ -37,6 +38,7 @@ struct remoteproc_virtio { void *vdev_rsc; struct metal_io_region *vdev_rsc_io; rpvdev_notify_func notify; @@ -62,22 +61,22 @@ index 6609a1fd..e65488d5 100644 struct metal_list node; }; diff --git a/lib/include/openamp/rpmsg.h open-amp/lib/include/openamp/rpmsg.h -index dbe42ea6..14440e20 100644 +index 11c3ccb..6f546e5 100644 --- a/lib/include/openamp/rpmsg.h +++ open-amp/lib/include/openamp/rpmsg.h -@@ -50,6 +50,7 @@ extern "C" { +@@ -49,6 +49,7 @@ extern "C" { + #define RPMSG_ERR_BUFF_SIZE (RPMSG_ERROR_BASE - 5) #define RPMSG_ERR_INIT (RPMSG_ERROR_BASE - 6) #define RPMSG_ERR_ADDR (RPMSG_ERROR_BASE - 7) - #define RPMSG_ERR_PERM (RPMSG_ERROR_BASE - 8) -+#define RPMSG_ERR_NXIO (RPMSG_ERROR_BASE - 9) ++#define RPMSG_ERR_NXIO (RPMSG_ERROR_BASE - 8) struct rpmsg_endpoint; struct rpmsg_device; diff --git a/lib/include/openamp/rpmsg_virtio.h open-amp/lib/include/openamp/rpmsg_virtio.h -index 0b22e840..11cb6df9 100644 +index aaba7e1..3ec0b0f 100644 --- a/lib/include/openamp/rpmsg_virtio.h +++ open-amp/lib/include/openamp/rpmsg_virtio.h -@@ -148,6 +148,15 @@ rpmsg_virtio_create_virtqueues(struct rpmsg_virtio_device *rvdev, +@@ -143,6 +143,15 @@ rpmsg_virtio_create_virtqueues(struct rpmsg_virtio_device *rvdev, callbacks); } @@ -94,7 +93,7 @@ index 0b22e840..11cb6df9 100644 * rpmsg_virtio_get_buffer_size - get rpmsg virtio buffer size * diff --git a/lib/include/openamp/virtio.h open-amp/lib/include/openamp/virtio.h -index 916132b4..0303a5b3 100644 +index 916132b..0303a5b 100644 --- a/lib/include/openamp/virtio.h +++ open-amp/lib/include/openamp/virtio.h @@ -162,6 +162,7 @@ struct virtio_dispatch { @@ -106,10 +105,10 @@ index 916132b4..0303a5b3 100644 int virtio_create_virtqueues(struct virtio_device *vdev, unsigned int flags, diff --git a/lib/remoteproc/remoteproc.c open-amp/lib/remoteproc/remoteproc.c -index f7f9f2df..001b11bf 100644 +index 9a0cf3e..4c101db 100644 --- a/lib/remoteproc/remoteproc.c +++ open-amp/lib/remoteproc/remoteproc.c -@@ -899,6 +899,16 @@ static int remoteproc_virtio_notify(void *priv, uint32_t id) +@@ -880,6 +880,16 @@ static int remoteproc_virtio_notify(void *priv, uint32_t id) return 0; } @@ -126,7 +125,7 @@ index f7f9f2df..001b11bf 100644 struct virtio_device * remoteproc_create_virtio(struct remoteproc *rproc, int vdev_id, unsigned int role, -@@ -957,6 +967,7 @@ remoteproc_create_virtio(struct remoteproc *rproc, +@@ -927,6 +937,7 @@ remoteproc_create_virtio(struct remoteproc *rproc, rproc_virtio_wait_remote_ready(vdev); rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); @@ -135,7 +134,7 @@ index f7f9f2df..001b11bf 100644 num_vrings = vdev_rsc->num_of_vrings; diff --git a/lib/remoteproc/remoteproc_virtio.c open-amp/lib/remoteproc/remoteproc_virtio.c -index 169e5b5f..4375c4c3 100644 +index cbfd966..ef5eef3 100644 --- a/lib/remoteproc/remoteproc_virtio.c +++ open-amp/lib/remoteproc/remoteproc_virtio.c @@ -30,6 +30,19 @@ static void rproc_virtio_virtqueue_notify(struct virtqueue *vq) @@ -167,10 +166,10 @@ index 169e5b5f..4375c4c3 100644 /* * We suppose here that the vdev is in a shared memory so that can diff --git a/lib/rpmsg/rpmsg_virtio.c open-amp/lib/rpmsg/rpmsg_virtio.c -index c56e0cea..4960aa8a 100644 +index d19d3b1..80bfbf7 100644 --- a/lib/rpmsg/rpmsg_virtio.c +++ open-amp/lib/rpmsg/rpmsg_virtio.c -@@ -373,6 +373,13 @@ static void *rpmsg_virtio_get_tx_payload_buffer(struct rpmsg_device *rdev, +@@ -339,6 +339,11 @@ static void *rpmsg_virtio_get_tx_payload_buffer(struct rpmsg_device *rdev, metal_mutex_release(&rdev->lock); if (rp_hdr || !tick_count) break; @@ -178,8 +177,6 @@ index c56e0cea..4960aa8a 100644 + status = rpmsg_virtio_notify_wait(rvdev, rvdev->rvq); + if (status == RPMSG_SUCCESS) + continue; -+ else if (status != RPMSG_ERR_NXIO) -+ break; + metal_sleep_usec(RPMSG_TICKS_PER_INTERVAL); tick_count--; diff --git a/openamp/0006-openamp-divide-shram-to-TX-shram-RX-shram-by-config-.patch b/openamp/0006-openamp-divide-shram-to-TX-shram-RX-shram-by-config-.patch new file mode 100644 index 0000000000000..7671a381344f5 --- /dev/null +++ b/openamp/0006-openamp-divide-shram-to-TX-shram-RX-shram-by-config-.patch @@ -0,0 +1,79 @@ +From bcaa279299ecd4194faffae71867c0371bf4f4a4 Mon Sep 17 00:00:00 2001 +From: Jiuzhu Dong +Date: Fri, 6 May 2022 10:41:57 +0800 +Subject: [PATCH 06/12] openamp: divide shram to TX shram & RX shram by + config:txrx_shpool + +In the multi core of lower power device, when one of core enters sleep, +it needs to put its corresponding share memory into retention mode to +save power consumption. Based on the limitations of the chip design, +when the CPU to which share memory belongs goes to sleep, the share +memory enters the retention mode, and other cores will not be able +to access it. When the share memory divides tx shm and rx shm +and the core of tx shm and rx shm are different, so that when one +CPU sleeps, the other CPU can still access its own tx shm. + +Signed-off-by: Guiding Li +Signed-off-by: Jiuzhu Dong +--- + lib/include/openamp/rpmsg_virtio.h | 10 ++++++++-- + lib/rpmsg/rpmsg_virtio.c | 5 +++-- + 2 files changed, 11 insertions(+), 4 deletions(-) + +diff --git a/lib/include/openamp/rpmsg_virtio.h open-amp/lib/include/openamp/rpmsg_virtio.h +index 3ec0b0f..c81b404 100644 +--- a/lib/include/openamp/rpmsg_virtio.h ++++ open-amp/lib/include/openamp/rpmsg_virtio.h +@@ -56,6 +56,7 @@ struct rpmsg_virtio_shm_pool { + struct rpmsg_virtio_config { + uint32_t h2r_buf_size; + uint32_t r2h_buf_size; ++ bool split_shpool; + }; + + /** +@@ -208,8 +209,13 @@ int rpmsg_init_vdev(struct rpmsg_virtio_device *rvdev, + * @param ns_bind_cb - callback handler for name service announcement without + * local endpoints waiting to bind. + * @param shm_io - pointer to the share memory I/O region. +- * @param shpool - pointer to shared memory pool. rpmsg_virtio_init_shm_pool has +- * to be called first to fill this structure. ++ * @param shpool - pointer to shared memory pool array. ++ * If the config->split_shpool is turn on, the array will contain ++ * two elements, the shpool of txshpool and rxshpool, Otherwise, ++ * the array has only one element, and txshpool rxshpool shares ++ * a shpool. ++ * And rpmsg_virtio_init_shm_pool has to be called first to fill ++ * each shpool in this array. + * @param config - pointer to configuration structure + * + * @return - status of function execution +diff --git a/lib/rpmsg/rpmsg_virtio.c open-amp/lib/rpmsg/rpmsg_virtio.c +index c555101..adc3dbc 100644 +--- a/lib/rpmsg/rpmsg_virtio.c ++++ open-amp/lib/rpmsg/rpmsg_virtio.c +@@ -24,6 +24,7 @@ + (&(const struct rpmsg_virtio_config) { \ + .h2r_buf_size = RPMSG_BUFFER_SIZE, \ + .r2h_buf_size = RPMSG_BUFFER_SIZE, \ ++ .split_shpool = false, \ + }) + #else + #define RPMSG_VIRTIO_DEFAULT_CONFIG NULL +@@ -705,11 +706,11 @@ int rpmsg_init_vdev_with_config(struct rpmsg_virtio_device *rvdev, + * Since device is RPMSG Remote so we need to manage the + * shared buffers. Create shared memory pool to handle buffers. + */ ++ rvdev->shpool = config->split_shpool ? shpool + 1 : shpool; + if (!shpool) + return RPMSG_ERR_PARAM; +- if (!shpool->size) ++ if (!shpool->size || !rvdev->shpool->size) + return RPMSG_ERR_NO_BUFF; +- rvdev->shpool = shpool; + + vq_names[0] = "rx_vq"; + vq_names[1] = "tx_vq"; +-- +2.25.1 + diff --git a/openamp/0005-rpmsg_virtio-don-t-need-check-status-when-get_tx_pay.patch b/openamp/0007-openamp-don-t-need-check-status-when-get_tx_payload.patch similarity index 52% rename from openamp/0005-rpmsg_virtio-don-t-need-check-status-when-get_tx_pay.patch rename to openamp/0007-openamp-don-t-need-check-status-when-get_tx_payload.patch index 3edd6d971db51..bc2797730b583 100644 --- a/openamp/0005-rpmsg_virtio-don-t-need-check-status-when-get_tx_pay.patch +++ b/openamp/0007-openamp-don-t-need-check-status-when-get_tx_payload.patch @@ -1,22 +1,21 @@ -From 5a9d63c1ce2878aa792c49a1205ebb73dbe6258f Mon Sep 17 00:00:00 2001 -From: ligd -Date: Mon, 28 Feb 2022 16:31:54 +0800 -Subject: [PATCH 05/10] rpmsg_virtio: don't need check status when - get_tx_payload +From 13f72065d4085cebe10687f486edaa014b4adf6c Mon Sep 17 00:00:00 2001 +From: Jiuzhu Dong +Date: Mon, 18 Apr 2022 15:20:52 +0800 +Subject: [PATCH 07/12] openamp: don't need check status when get_tx_payload -VELAOS-21 - -Change-Id: Icb01034dfab146b3a02ea2c70dbdf197d8ed419f -Signed-off-by: ligd +Remove redundant check, because this status is already check in +rpmsg_init_vdev_with_config and rpmsg_virtio_wait_remote_ready. +Signed-off-by: Guiding Li +Signed-off-by: Jiuzhu Dong --- lib/rpmsg/rpmsg_virtio.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib/rpmsg/rpmsg_virtio.c open-amp/lib/rpmsg/rpmsg_virtio.c -index 4960aa8a..1f6ce593 100644 +index adc3dbc..92f5883 100644 --- a/lib/rpmsg/rpmsg_virtio.c +++ open-amp/lib/rpmsg/rpmsg_virtio.c -@@ -356,11 +356,6 @@ static void *rpmsg_virtio_get_tx_payload_buffer(struct rpmsg_device *rdev, +@@ -323,11 +323,6 @@ static void *rpmsg_virtio_get_tx_payload_buffer(struct rpmsg_device *rdev, /* Get the associated remote device for channel. */ rvdev = metal_container_of(rdev, struct rpmsg_virtio_device, rdev); diff --git a/openamp/0008-openamp-add-available_idx-to-dump.patch b/openamp/0008-openamp-add-available_idx-to-dump.patch new file mode 100644 index 0000000000000..290f96e355e87 --- /dev/null +++ b/openamp/0008-openamp-add-available_idx-to-dump.patch @@ -0,0 +1,34 @@ +From 3ae038f84432e657dff78ed135204210b42a33a9 Mon Sep 17 00:00:00 2001 +From: Guiding Li +Date: Tue, 31 May 2022 23:04:01 +0800 +Subject: [PATCH 08/12] openamp: add available_idx to dump + +Just update debug logs + +Signed-off-by: Guiding Li +--- + lib/virtio/virtqueue.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/lib/virtio/virtqueue.c open-amp/lib/virtio/virtqueue.c +index d989533..2d243b8 100644 +--- a/lib/virtio/virtqueue.c ++++ open-amp/lib/virtio/virtqueue.c +@@ -421,11 +421,11 @@ void virtqueue_dump(struct virtqueue *vq) + VRING_INVALIDATE(vq->vq_ring.used); + + metal_log(METAL_LOG_DEBUG, +- "VQ: %s - size=%d; free=%d; queued=%d; " +- "desc_head_idx=%d; avail.idx=%d; used_cons_idx=%d; " ++ "VQ: %s - size=%d; free=%d; queued=%d; desc_head_idx=%d; " ++ "available_idx=%d; avail.idx=%d; used_cons_idx=%d; " + "used.idx=%d; avail.flags=0x%x; used.flags=0x%x\r\n", + vq->vq_name, vq->vq_nentries, vq->vq_free_cnt, +- vq->vq_queued_cnt, vq->vq_desc_head_idx, ++ vq->vq_queued_cnt, vq->vq_desc_head_idx, vq->vq_available_idx, + vq->vq_ring.avail->idx, vq->vq_used_cons_idx, + vq->vq_ring.used->idx, vq->vq_ring.avail->flags, + vq->vq_ring.used->flags); +-- +2.25.1 + diff --git a/openamp/0009-Fix-warn-declaration-of-vring_rsc-shadows-a-previous.patch b/openamp/0009-Fix-warn-declaration-of-vring_rsc-shadows-a-previous.patch deleted file mode 100644 index 853565f0de436..0000000000000 --- a/openamp/0009-Fix-warn-declaration-of-vring_rsc-shadows-a-previous.patch +++ /dev/null @@ -1,36 +0,0 @@ -From e33b3fa0b6f111b54648f682102266b077a0c285 Mon Sep 17 00:00:00 2001 -From: Xiang Xiao -Date: Sun, 6 Nov 2022 00:51:35 +0800 -Subject: [PATCH 09/10] Fix warn: declaration of 'vring_rsc' shadows a previous - local - -regressed by commit 03c80a13417f67f94852cf7d5cb160f1bdf8271e -Author: Tammy Leino -Date: Mon Sep 26 08:14:35 2022 -0700 - - handle_vdev_rsc must return error if notifyid cannot be assigned - - Updated handle_vdev_rsc to return error if a unique id cannot be assigned - Signed-off-by: Tammy Leino - -Signed-off-by: Xiang Xiao ---- - lib/remoteproc/rsc_table_parser.c | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/lib/remoteproc/rsc_table_parser.c open-amp/lib/remoteproc/rsc_table_parser.c -index 80879380..4cccf4f1 100644 ---- a/lib/remoteproc/rsc_table_parser.c -+++ open-amp/lib/remoteproc/rsc_table_parser.c -@@ -144,8 +144,6 @@ int handle_vdev_rsc(struct remoteproc *rproc, void *rsc) - - num_vrings = vdev_rsc->num_of_vrings; - for (i = 0; i < num_vrings; i++) { -- struct fw_rsc_vdev_vring *vring_rsc; -- - vring_rsc = &vdev_rsc->vring[i]; - notifyid = vring_rsc->notifyid; - notifyid = remoteproc_allocate_id(rproc, --- -2.25.1 - diff --git a/openamp/0009-openamp-firstly-take-all-buffer-from-shram-pool.patch b/openamp/0009-openamp-firstly-take-all-buffer-from-shram-pool.patch new file mode 100644 index 0000000000000..c22cf3138e3ba --- /dev/null +++ b/openamp/0009-openamp-firstly-take-all-buffer-from-shram-pool.patch @@ -0,0 +1,38 @@ +From 8aff77d4ceea809da273b68763aea737ed81da38 Mon Sep 17 00:00:00 2001 +From: Guiding Li +Date: Tue, 2 Aug 2022 11:12:19 +0800 +Subject: [PATCH 09/12] openamp: firstly take all buffer from shram pool + +1. the memory already alloced for shram +2. this can help dump the right free cnt + +Signed-off-by: Guiding Li +--- + lib/rpmsg/rpmsg_virtio.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/lib/rpmsg/rpmsg_virtio.c open-amp/lib/rpmsg/rpmsg_virtio.c +index 92f5883..4f26b01 100644 +--- a/lib/rpmsg/rpmsg_virtio.c ++++ open-amp/lib/rpmsg/rpmsg_virtio.c +@@ -154,12 +154,13 @@ static void *rpmsg_virtio_get_tx_buffer(struct rpmsg_virtio_device *rvdev, + + #ifndef VIRTIO_DEVICE_ONLY + if (role == RPMSG_HOST) { +- data = virtqueue_get_buffer(rvdev->svq, len, idx); +- if (!data && rvdev->svq->vq_free_cnt) { +- data = rpmsg_virtio_shm_pool_get_buffer(rvdev->shpool, +- rvdev->config.h2r_buf_size); ++ data = rpmsg_virtio_shm_pool_get_buffer(rvdev->shpool, ++ rvdev->config.h2r_buf_size); ++ if (data) { + *len = rvdev->config.h2r_buf_size; + *idx = 0; ++ } else { ++ data = virtqueue_get_buffer(rvdev->svq, len, idx); + } + } + #endif /*!VIRTIO_DEVICE_ONLY*/ +-- +2.25.1 + diff --git a/openamp/0006-rpmsg-notify-the-user-when-the-remote-address-is-rec.patch b/openamp/0010-rpmsg-notify-the-user-when-the-remote-address-is-rec.patch similarity index 75% rename from openamp/0006-rpmsg-notify-the-user-when-the-remote-address-is-rec.patch rename to openamp/0010-rpmsg-notify-the-user-when-the-remote-address-is-rec.patch index b7666e9b7f8f6..688288ad17731 100644 --- a/openamp/0006-rpmsg-notify-the-user-when-the-remote-address-is-rec.patch +++ b/openamp/0010-rpmsg-notify-the-user-when-the-remote-address-is-rec.patch @@ -1,21 +1,21 @@ -From a2c9d79f9b77f057d89ede1395559c0645169b7a Mon Sep 17 00:00:00 2001 +From 442ccb015805eb5f7d700f80db9893d319ce5781 Mon Sep 17 00:00:00 2001 From: ligd Date: Tue, 19 Oct 2021 19:45:14 +0800 -Subject: [PATCH 06/10] rpmsg: notify the user when the remote address is +Subject: [PATCH 10/12] rpmsg: notify the user when the remote address is received Change-Id: I2f0601fb38944e0cfb8888aa397740161b159e40 Signed-off-by: ligd --- lib/include/openamp/rpmsg.h | 4 ++++ - lib/rpmsg/rpmsg_virtio.c | 6 ++++++ - 2 files changed, 10 insertions(+) + lib/rpmsg/rpmsg_virtio.c | 9 +++++++-- + 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/include/openamp/rpmsg.h open-amp/lib/include/openamp/rpmsg.h -index 14440e20..fbd7f619 100644 +index 6f546e5..10d4f5b 100644 --- a/lib/include/openamp/rpmsg.h +++ open-amp/lib/include/openamp/rpmsg.h -@@ -58,6 +58,7 @@ struct rpmsg_device; +@@ -57,6 +57,7 @@ struct rpmsg_device; /* Returns positive value on success or negative error value on failure */ typedef int (*rpmsg_ept_cb)(struct rpmsg_endpoint *ept, void *data, size_t len, uint32_t src, void *priv); @@ -23,7 +23,7 @@ index 14440e20..fbd7f619 100644 typedef void (*rpmsg_ns_unbind_cb)(struct rpmsg_endpoint *ept); typedef void (*rpmsg_ns_bind_cb)(struct rpmsg_device *rdev, const char *name, uint32_t dest); -@@ -70,6 +71,8 @@ typedef void (*rpmsg_ns_bind_cb)(struct rpmsg_device *rdev, +@@ -69,6 +70,8 @@ typedef void (*rpmsg_ns_bind_cb)(struct rpmsg_device *rdev, * @dest_addr: address of the default remote endpoint binded. * @cb: user rx callback, return value of this callback is reserved * for future use, for now, only allow RPMSG_SUCCESS as return value. @@ -32,7 +32,7 @@ index 14440e20..fbd7f619 100644 * @ns_unbind_cb: end point service unbind callback, called when remote * ept is destroyed. * @node: end point node. -@@ -84,6 +87,7 @@ struct rpmsg_endpoint { +@@ -83,6 +86,7 @@ struct rpmsg_endpoint { uint32_t addr; uint32_t dest_addr; rpmsg_ept_cb cb; @@ -41,13 +41,16 @@ index 14440e20..fbd7f619 100644 struct metal_list node; void *priv; diff --git a/lib/rpmsg/rpmsg_virtio.c open-amp/lib/rpmsg/rpmsg_virtio.c -index 1f6ce593..efbcd68d 100644 +index 4f26b01..e55e135 100644 --- a/lib/rpmsg/rpmsg_virtio.c +++ open-amp/lib/rpmsg/rpmsg_virtio.c -@@ -658,12 +658,18 @@ static int rpmsg_virtio_ns_callback(struct rpmsg_endpoint *ept, void *data, +@@ -598,14 +598,19 @@ static int rpmsg_virtio_ns_callback(struct rpmsg_endpoint *ept, void *data, + _ept->dest_addr = dest; + metal_mutex_release(&rdev->lock); if (_ept->name[0] && rdev->support_ack) - rpmsg_send_ns_message(_ept, - RPMSG_NS_CREATE_ACK); +- rpmsg_send_ns_message(_ept, +- RPMSG_NS_CREATE_ACK); ++ rpmsg_send_ns_message(_ept, RPMSG_NS_CREATE_ACK); + /* notify application that the endpoint has been bound */ + if (_ept->ns_bound_cb) + _ept->ns_bound_cb(_ept); diff --git a/openamp/0010-rptun-fix-rptun-don-t-wait-issue-when-get-tx-patyloa.patch b/openamp/0010-rptun-fix-rptun-don-t-wait-issue-when-get-tx-patyloa.patch deleted file mode 100644 index 99768f79e3b62..0000000000000 --- a/openamp/0010-rptun-fix-rptun-don-t-wait-issue-when-get-tx-patyloa.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 160e7ee44228668074347226e9c0d9068c480d98 Mon Sep 17 00:00:00 2001 -From: Jiuzhu Dong -Date: Thu, 11 Aug 2022 21:54:53 +0800 -Subject: [PATCH 10/10] rptun: fix rptun don't wait issue when get tx patyload - buffer - -Signed-off-by: Jiuzhu Dong -Signed-off-by: ligd ---- - lib/rpmsg/rpmsg_virtio.c | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/lib/rpmsg/rpmsg_virtio.c open-amp/lib/rpmsg/rpmsg_virtio.c -index 49817799..06c6890b 100644 ---- a/lib/rpmsg/rpmsg_virtio.c -+++ open-amp/lib/rpmsg/rpmsg_virtio.c -@@ -372,8 +372,6 @@ static void *rpmsg_virtio_get_tx_payload_buffer(struct rpmsg_device *rdev, - status = rpmsg_virtio_notify_wait(rvdev, rvdev->rvq); - if (status == RPMSG_SUCCESS) - continue; -- else if (status != RPMSG_ERR_NXIO) -- break; - - metal_sleep_usec(RPMSG_TICKS_PER_INTERVAL); - tick_count--; --- -2.25.1 - diff --git a/openamp/0007-openamp-avoid-double-calling-ns_bound-when-each-othe.patch b/openamp/0011-openamp-avoid-double-calling-ns_bound-when-each-othe.patch similarity index 84% rename from openamp/0007-openamp-avoid-double-calling-ns_bound-when-each-othe.patch rename to openamp/0011-openamp-avoid-double-calling-ns_bound-when-each-othe.patch index 31a781f0a1010..8a51530b5304a 100644 --- a/openamp/0007-openamp-avoid-double-calling-ns_bound-when-each-othe.patch +++ b/openamp/0011-openamp-avoid-double-calling-ns_bound-when-each-othe.patch @@ -1,7 +1,7 @@ -From 0e77783658066c02903cc6693460f3bb577e3030 Mon Sep 17 00:00:00 2001 +From 8405b71cb738096a223c5f7ca02b9fa0de5ae0d6 Mon Sep 17 00:00:00 2001 From: Jiuzhu Dong Date: Mon, 11 Apr 2022 13:31:35 +0800 -Subject: [PATCH 07/10] openamp: avoid double calling ns_bound when each other +Subject: [PATCH 11/12] openamp: avoid double calling ns_bound when each other calls create_ept VELAPLATFO-1522 @@ -13,10 +13,10 @@ Signed-off-by: Jiuzhu Dong 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/rpmsg/rpmsg_virtio.c open-amp/lib/rpmsg/rpmsg_virtio.c -index efbcd68d..49817799 100644 +index e55e135..cd3a13d 100644 --- a/lib/rpmsg/rpmsg_virtio.c +++ open-amp/lib/rpmsg/rpmsg_virtio.c -@@ -652,7 +652,7 @@ static int rpmsg_virtio_ns_callback(struct rpmsg_endpoint *ept, void *data, +@@ -594,7 +594,7 @@ static int rpmsg_virtio_ns_callback(struct rpmsg_endpoint *ept, void *data, metal_mutex_release(&rdev->lock); if (rdev->ns_bind_cb) rdev->ns_bind_cb(rdev, name, dest); @@ -25,7 +25,7 @@ index efbcd68d..49817799 100644 _ept->dest_addr = dest; metal_mutex_release(&rdev->lock); if (_ept->name[0] && rdev->support_ack) -@@ -662,14 +662,19 @@ static int rpmsg_virtio_ns_callback(struct rpmsg_endpoint *ept, void *data, +@@ -603,14 +603,19 @@ static int rpmsg_virtio_ns_callback(struct rpmsg_endpoint *ept, void *data, if (_ept->ns_bound_cb) _ept->ns_bound_cb(_ept); } diff --git a/openamp/0008-remoteproc-make-all-elf_-functions-static-except-elf.patch b/openamp/0012-remoteproc-make-all-elf_-functions-static-except-elf.patch similarity index 97% rename from openamp/0008-remoteproc-make-all-elf_-functions-static-except-elf.patch rename to openamp/0012-remoteproc-make-all-elf_-functions-static-except-elf.patch index fb5e9d5e11f4a..6e25df2204df3 100644 --- a/openamp/0008-remoteproc-make-all-elf_-functions-static-except-elf.patch +++ b/openamp/0012-remoteproc-make-all-elf_-functions-static-except-elf.patch @@ -1,7 +1,7 @@ -From bcd10078fe4266cadbc437b130832dd90c00df33 Mon Sep 17 00:00:00 2001 +From fb046d85d5e098f58af037322f0de2f663e8f460 Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Fri, 15 Nov 2019 19:01:49 +0800 -Subject: [PATCH 08/10] remoteproc: make all elf_* functions static except +Subject: [PATCH 12/12] remoteproc: make all elf_* functions static except elf_identify it's the best practice to reduce the name scope as small as possible @@ -13,7 +13,7 @@ Signed-off-by: Xiang Xiao 2 files changed, 14 insertions(+), 107 deletions(-) diff --git a/lib/include/openamp/elf_loader.h open-amp/lib/include/openamp/elf_loader.h -index e7dda748..916a23f9 100644 +index e7dda74..916a23f 100644 --- a/lib/include/openamp/elf_loader.h +++ open-amp/lib/include/openamp/elf_loader.h @@ -323,99 +323,6 @@ extern const struct loader_ops elf_ops; @@ -117,7 +117,7 @@ index e7dda748..916a23f9 100644 #if defined __cplusplus } diff --git a/lib/remoteproc/elf_loader.c open-amp/lib/remoteproc/elf_loader.c -index c90b8d46..ffb253fb 100644 +index c90b8d4..ffb253f 100644 --- a/lib/remoteproc/elf_loader.c +++ open-amp/lib/remoteproc/elf_loader.c @@ -392,9 +392,9 @@ int elf_identify(const void *img_data, size_t len) diff --git a/openamp/Makefile b/openamp/Makefile index 4bf73b0c526ce..2313df27fd3e8 100644 --- a/openamp/Makefile +++ b/openamp/Makefile @@ -20,7 +20,7 @@ include $(TOPDIR)/Make.defs -VERSION ?= 2022.10.0 +VERSION ?= 2022.04.0 include libmetal.defs include open-amp.defs diff --git a/openamp/libmetal.defs b/openamp/libmetal.defs index 4ed70cd327b4f..ff86294ec38d7 100644 --- a/openamp/libmetal.defs +++ b/openamp/libmetal.defs @@ -67,17 +67,15 @@ LIBMETAL_HDRS_SEDEXP := \ s/@PROJECT_MACHINE_UPPER@/$(CONFIG_ARCH_CHIP)/g; \ s/cmakedefine/undef/g" -ifeq ($(wildcard libmetal/.git),) libmetal.zip: # Download and unpack tarball if no git repo found +ifeq ($(wildcard libmetal/.git),) $(Q) curl -L https://github.com/OpenAMP/libmetal/archive/v$(VERSION).zip -o libmetal.zip $(Q) unzip -o libmetal.zip $(Q) mv libmetal-$(VERSION) libmetal +endif .libmetal_headers: libmetal.zip -else -.libmetal_headers: -endif $(eval headers := $(wildcard libmetal/lib/compiler/gcc/*.h)) $(eval headers += $(wildcard libmetal/lib/processor/$(LIBMETAL_ARCH)/*.h)) $(eval headers += $(wildcard libmetal/lib/system/nuttx/*.h)) diff --git a/openamp/open-amp.defs b/openamp/open-amp.defs index c0012aba56f34..e0fcf76fe3c47 100644 --- a/openamp/open-amp.defs +++ b/openamp/open-amp.defs @@ -29,27 +29,27 @@ CSRCS += open-amp/lib/rpmsg/rpmsg_virtio.c CSRCS += open-amp/lib/virtio/virtio.c CSRCS += open-amp/lib/virtio/virtqueue.c +open-amp.zip: # Download and unpack tarball if no git repo found ifeq ($(wildcard open-amp/.git),) -open-amp.zip: $(Q) curl -L https://github.com/OpenAMP/open-amp/archive/v$(VERSION).zip -o open-amp.zip $(Q) unzip -o open-amp.zip $(Q) mv open-amp-$(VERSION) open-amp - $(Q) patch -p0 < 0001-ns-acknowledge-the-received-creation-message.patch - $(Q) patch -p0 < 0002-Negotiate-individual-buffer-size-dynamically.patch - $(Q) patch -p0 < 0003-rpmsg-wait-endpoint-ready-in-rpmsg_send-and-rpmsg_se.patch - $(Q) patch -p0 < 0004-openamp-add-new-ops-notify_wait-support.patch - $(Q) patch -p0 < 0005-rpmsg_virtio-don-t-need-check-status-when-get_tx_pay.patch - $(Q) patch -p0 < 0006-rpmsg-notify-the-user-when-the-remote-address-is-rec.patch - $(Q) patch -p0 < 0007-openamp-avoid-double-calling-ns_bound-when-each-othe.patch - $(Q) patch -p0 < 0008-remoteproc-make-all-elf_-functions-static-except-elf.patch - $(Q) patch -p0 < 0009-Fix-warn-declaration-of-vring_rsc-shadows-a-previous.patch - $(Q) patch -p0 < 0010-rptun-fix-rptun-don-t-wait-issue-when-get-tx-patyloa.patch + $(Q) patch -p0 < 0001-openamp-add-ns_unbind_notify-support.patch + $(Q) patch -p0 < 0002-ns-acknowledge-the-received-creation-message.patch + $(Q) patch -p0 < 0003-Negotiate-individual-buffer-size-dynamically.patch + $(Q) patch -p0 < 0004-rpmsg-wait-endpoint-ready-in-rpmsg_send-and-rpmsg_se.patch + $(Q) patch -p0 < 0005-openamp-add-new-ops-notify_wait-support.patch + $(Q) patch -p0 < 0006-openamp-divide-shram-to-TX-shram-RX-shram-by-config-.patch + $(Q) patch -p0 < 0007-openamp-don-t-need-check-status-when-get_tx_payload.patch + $(Q) patch -p0 < 0008-openamp-add-available_idx-to-dump.patch + $(Q) patch -p0 < 0009-openamp-firstly-take-all-buffer-from-shram-pool.patch + $(Q) patch -p0 < 0010-rpmsg-notify-the-user-when-the-remote-address-is-rec.patch + $(Q) patch -p0 < 0011-openamp-avoid-double-calling-ns_bound-when-each-othe.patch + $(Q) patch -p0 < 0012-remoteproc-make-all-elf_-functions-static-except-elf.patch +endif .openamp_headers: open-amp.zip -else -.openamp_headers: -endif $(eval headers := $(wildcard open-amp/lib/include/openamp/*.h)) $(shell mkdir -p $(TOPDIR)$(DELIM)include$(DELIM)openamp$(DELIM)) $(foreach header,$(headers),$(shell cp -rf $(header) $(TOPDIR)$(DELIM)include$(DELIM)openamp$(DELIM)))