This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TCAN4550:芯片应用问题

Guru**** 2763455 points

Other Parts Discussed in Thread: TCAN4550

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/interface-group/interface/f/interface-forum/1237781/tcan4550-application-issues-of-chips

器件型号:TCAN4550

测试 TCAN4550可以正常发送和接收标准帧一万次、但在测试扩展帧时、TCAN4550无法接收扩展帧数据、并且可以发送扩展帧。 是否还有任何其他需要为该驱动程序配置的内容?

tcan4x5x:

// SPDX-License-Identifier:GPL-2.0
// SPI 到德州仪器 TCAN4x5x 的 CAN 驱动器
//版权所有(C) 2018-19德州仪器(TI)公司- http://www.ti.com/

#包含
#包含

#包含
#包含
#包含
#包含
#包含

#include "m_can.h"

#define device_name "tcan4x5x"
#define TCAN4X5X_EXT_CLK_DEF 40000000

#define TCAN4X5X_DEV_ID0 0x00
#define TCAN4X5X_DEV_ID1 0x04
#define TCAN4X5X_REV 0x08
#define TCAN4X5X_STATUS 0x0C
#define TCAN4X5X_ERROR_STATUS 0x10
#define TCAN4X5X_CONTROL 0x14

#define TCAN4X5X_CONFIG 0x800
#define TCAN4X5X_TS_PRESCALE 0x804
#define TCANX5X_TEST_REG 0x808
#define TCAN4X5X_INT_FLAGS 0x820
#define TCAN4X5X_MCAN_INT_REG 0x824
#define TCAN4X5X_INT_EN 0x830

/*中断位*/
#define TCAN4X5X_CANBUSTERMOPEN_INT_EN 位(30)
#define TCAN4X5X_CANHCANL_INT_EN 位(29)
#define TCAN4X5X_CANBAT_INT_EN 位(28)
#define TCAN4X5X_CANLGND_INT_EN 位(27)
#define TCAN4X5X_CANBUSOPEN_INT_EN 位(26)
#define TCAN4X5X_CANBUSGND_INT_EN 位(25)
#define TCAN4X5X_CANBBAT_INT_EN 位(24)
#define TCAN4X5X_UVSUP_INT_EN 位(22)
#define TCAN4X5X_UVIO_INT_EN 位(21)
#define TCAN4X5X_TSD_INT_EN 位(19)
#define TCAN4X5X_ECCERR_INT_EN 位(16)
#define TCAN4X5X_CANINT_INT_EN 位(15)
#define TCAN4X5X_LWU_INT_EN 位(14)
#define TCAN4X5X_CANSLNT_INT_EN 位(10)
#define TCANX5X_CANDOM_INT_EN 位(8)
#define TCAN4X5X_CANBUS_ERR_INT_EN 位(5)
#define TCAN4X5X_BUS_FAULT 位(4)
#define TCAN4X5X_MCAN_INT bit (1)
#define TCAN4X5X_ENABLE_TCAN_INT \
   (TCAN4X5X_MCAN_INT | TCAN4X5X_BUS_FAULT |\
   TCAN4X5X_CANBUS_ERR_INT_EN | TCAN4X5X_CANINT_INT_EN)

/* MCAN 中断位*/
#define TCAN4X5X_MCAN_IR_ARA 位(29)
#define TCAN4X5X_MCAN_IR_PED 位(28)
#define TCAN4X5X_MCAN_IR_PEA 位(27)
#define TCAN4X5X_MCAN_IR_WD 位(26)
#define TCAN4X5X_MCAN_IR_BO 位(25)
#define TCAN4X5X_MCAN_IR_EW 位(24)
#define TCAN4X5X_MCAN_IR_EP 位(23)
#define TCAN4X5X_MCAN_IR_ELO 位(22)
#define TCAN4X5X_MCAN_IR_BEU 位(21)
#define TCAN4X5X_MCAN_IR_BEC 位(20)
#define TCAN4X5X_MCAN_IR_DRX 位(19)
#define TCAN4X5X_MCAN_IR_TOO 位(18)
#define TCAN4X5X_MCAN_IR_MRAF 位(17)
#define TCAN4X5X_MCAN_IR_TSW 位(16)
#define TCAN4X5X_MCAN_IR_TEFL 位(15)
#define TCAN4X5X_MCAN_IR_TEFF 位(14)
#define TCAN4X5X_MCAN_IR_TEFW 位(13)
#define TCAN4X5X_MCAN_IR_TEFN 位(12)
#define TCAN4X5X_MCAN_IR_TFE 位(11)
#define TCAN4X5X_MCAN_IR_TCF 位(10)
#define TCAN4X5X_MCAN_IR_TC 位(9)
#define TCAN4X5X_MCAN_IR_HPM 位(8)
#define TCAN4X5X_MCAN_IR_RF1L 位(7)
#define TCAN4X5X_MCAN_IR_RF1F 位(6)
#define TCAN4X5X_MCAN_IR_RF1W 位(5)
#define TCAN4X5X_MCAN_IR_RF1N 位(4)
#define TCAN4X5X_MCAN_IR_RF0L 位(3)
#define TCAN4X5X_MCAN_IR_RF0F 位(2)
#define TCAN4X5X_MCAN_IR_RF0W 位(1)
#define TCAN4X5X_MCAN_IR_RF0N 位(0)
#define TCAN4X5X_ENABLE_MCAN_INT \
   (TCAN4X5X_MCAN_IR_TC | TCAN4X5X_MCAN_IR_RF0N |\
   TCAN4X5X_MCAN_IR_RF1N | TCAN4X5X_MCAN_IR_RF0F |\
   TCAN4X5X_MCAN_IR_RF1F)

#define TCAN4X5X_MRAM_START 0x8000
#define TCAN4X5X_MCAN_OFFSET 0x1000
#define TCAN4X5X_MAX_register 0x8ffc

#define TCAN4X5X_CLEAR_ALL_INT 0xffffffff
#define TCAN4X5X_SET_ALL_INT 0xffffffff

#define TCAN4X5X_WRITE_CMD (0x61 << 24)
#define TCAN4X5X_READ_CMD (0x41 << 24)

#define TCAN4X5X_MODE_SEL_MASK (bit (7)| bit (6))
#define TCAN4X5X_MODE_SLEEP 0x00
#define TCAN4X5X_MODE_STANDBY 位(6)
#define TCAN4X5X_MODE_NORMAL 位(7)

#define TCAN4X5X_SW_RESET 位(2)

#define TCAN4X5X_MCAN_PROFILETED 位(5)
#define TCAN4X5X_WATCHDOG_EN 位(3)
#define TCAN4X5X_WD_60_MS_TIMER 0
#define TCAN4X5X_WD_600_MS_TIMER 位(28)
#define TCAN4X5X_WD_3_S_TIMER 位(29)
#define TCAN4X5X_WD_6_S_TIMER (位(28)|位(29))

结构 tcan4x5x_priv{
   struct regmap *regmap;
   结构 SPI_DEVICE * SPI;

   struct m_can_classdev *mcan_dev;

   //struct GPIO_desc *重置 GPIO;
   U32 RESET_GPIO;
   结构 GPIO_desc * device_wake_gpio;
   结构 GPIO_desc * device_state_gpio;
   结构稳压器*电源;

   /*基于寄存器的 IP */
   int mRAM_start;
   INT REG_OFFSET;
};

静态 void tcan4x5x_check_wake (struct tcan4x5x_priv *priv)
{
   INT WAKE_STATE = 0;

   如果(priv->device_state_gpio)
      WAKE_STATE = gpiod_get_value (priv->device_state_pio);

   如果(priv->device_wake_gpio && wake_state){
      gpiod_set_value (priv->device_wake_gpio、0);
      usleep_range (5、50);
      gpiod_set_value (priv->device_wake_gpio、1);
   }


static int tcan4x5x_reset (struct tcan4x5x_priv *priv)
{
   int ret = 0;

   if (GPIO_is_valid (priv->reset_GPIO)){
      //gpiod_set_value (priv->reset_GPIO、1);
      GPIO_DIRECTION_OUTPUT (priv->reset_GPIO,1);
      /* tpulse_width 最小值30us */
      usleep_range (30,100);
      //gpiod_set_value (priv->reset_GPIO、0);
      GPIO_Direction_output (priv->reset_GPIO、0);
   }其他{
      printk ("lim %s %d\n"、__func__、__line__);
      //ret = regmap_write (priv->regmap、TCAN4X5X_CONFIG、
      //        TCAN4X5X_SW_RESET);
      //IF (ret)
      //   返回转塔;
   }

   usleep_range (700,1000);

   返回支架;


静态 int regmap_SPI_collect_write (void *上下文、const void * reg、
              size_t reg_len、const void * val、
              size_t val_len)
{
   结构设备*dev =上下文;
   结构 SPI_DEVICE * SPI = TO_SPI_DEVICE (dev);
   结构 SPI_MESSAGE m;
   u32地址;
   结构 SPI_TRANSMIT t[2]={
      {.tx_buf =&addr、.len = reg_len、.cs_change = 0、}、
      {.tx_buf = val、.len = val_len、}、
   };

   addr = TCAN4X5X_WRITE_CMD |(*((U16 *) reg)<< 8)| val_len >> 2;

   SPI_MESSAGE_INIT (&m);
   SPI_MESSAGE_ADD_TAIL (&t[0]、&m);
   SPI_MESSAGE_ADD_TAIL (&t[1]、&m);

   返回 SPI_SYNC (SPI、&m);


静态 int tcan4x5x_regmap_write (void *上下文、const void *数据、size_t count)
{
   u16 * reg =(U16 *)(data);
   const u32 * val = data + 4;

   返回 regmap_SPI_collect_write (上下文、寄存器、4、val、计数- 4);


静态 int regmap_spi_async_write (void *上下文、
             const void * reg、size_t reg_len、
             const void * val、size_t val_len、
             结构 regmap_async *a)
{
   返回-ENOTSup;


静态结构 regmap_async *regmap_spi_async_alloc (void)
{
   返回 NULL;


静态 int tcan4x5x_regmap_read (void *上下文、
            const void * reg、size_t reg_size、
            void * val、size_t val_size)
{
   结构设备*dev =上下文;
   结构 SPI_DEVICE * SPI = TO_SPI_DEVICE (dev);

   u32 addr = TCAN4X5X_READ_CMD |(*(U16 *) reg)<< 8)| val_size >> 2;

   返回 SPI_WRITE_THEN_READ (SPI、&addr、reg_size、(u32 *) val、val_size);


静态结构 regmap_BUS tcan4x5x_BUS ={
   .write = tcan4x5x_regmap_write、
   .collect_write = regmap_SPI_collect_write、
   .async_write = regmap_spi_async_write、
   .async_alloc = regmap_spi_async_alloc、
   .read = tcan4x5x_regmap_read、
   .READ_FLAG_MASK = 0x00、
   .reg_format_endian_default = REGMAP ENDIAN_Native、
   .val_format_endian_default = REGMAP_ENDIAN_Native、
};

静态 u32 tcan4x5x_read_reg (struct m_can_classdev * cdev、int reg)
{
   struct tcan4x5x_priv *priv = cdev->device_data;
   u32 val;

   regmap_read (priv->regmap、priv->reg_offset + reg、&val);

   返回 val;


静态 u32 tcan4x5x_read_fifo (struct m_can_classdev * cdv、int addr_offset)
{
   struct tcan4x5x_priv *priv = cdev->device_data;
   u32 val;

   regmap_read (priv->regmap、priv->mram_start + addr_offset、&val);

   返回 val;


静态 int tcan4x5x_write_reg (struct m_can_classdev * cdev、int reg、int val)
{
   struct tcan4x5x_priv *priv = cdev->device_data;

   return regmap_write (priv->regmap、priv->reg_offset + reg、val);


静态 int tcan4x5x_write_fifo (struct m_can_classdev * cdev、
               int addr_offset、int val)
{
   struct tcan4x5x_priv *priv = cdev->device_data;

   return regmap_write (priv->regmap、priv->mram_start + addr_offset、val);


静态 int tcan4x5x_power_enable (结构稳压器* reg、int enable)
{
   //if (IS_ERR_OR_NULL (reg))
      返回0;

   //if (启用)
   //   返回 regulator_enable (reg);
   //其他
   //   返回 regulator_disable (reg);


静态 int tcan4x5x_write_tcan_reg (struct m_can_classdev *cdev、
              int reg、int val)
{
   struct tcan4x5x_priv *priv = cdev->device_data;

   return regmap_write (priv->regmap、reg、val);


静态 int tcan4x5x_clear_interrupts (struct m_can_classdev *cdv)
{
   Int ret;
   //printk ("4x5x LPZ 测试\n");
   REt = tcan4x5x_write_tcan_reg (cdev、TCAN4X5X_STATUS、
                 TCAN4X5X_CLEAR_ALL_INT);
   IF (RET)
      返回支架;

   RET = tcan4x5x_write_tcan_reg (cdev、TCAN4X5X_MCAN_INT_REG、
                 TCAN4X5X_ENABLE_MCAN_INT);
   IF (RET)
      返回支架;

   REt = tcan4x5x_write_tcan_reg (cdev、TCAN4X5X_INT_flags、
                 TCAN4X5X_CLEAR_ALL_INT);
   IF (RET)
      返回支架;

   REt = tcan4x5x_write_tcan_reg (cdev、TCAN4X5X_ERROR_STATUS、
                 TCAN4X5X_CLEAR_ALL_INT);
   IF (RET)
      返回支架;

   返回支架;


静态 int tcan4x5x_init (struct m_can_classdev *cdv)
{
   struct tcan4x5x_priv *tcan4x5x = cdev->device_data;
   Int ret;

   tcan4x5x_check_wake (tcan4x5x);

   REt = tcan4x5x_clear_interrupts (cdv);
   IF (RET)
      返回支架;

   REt = tcan4x5x_write_tcan_reg (cdev、TCAN4X5X_INT_EN、
                 TCAN4X5X_ENABLE_TCAN_INT);
   IF (RET)
      返回支架;

   /*归零 MCAN 缓冲器*/
   m_can_init_ram (cdev);

   REt = regmap_update_bits (tcan4x5x->regmap、TCAN4X5X_CONFIG、
            TCAN4X5X_MODE_SEL_MASK、TCAN4X5X_MODE_NORMAL);
   IF (RET)
      返回支架;

   返回支架;


静态 int tcan4x5x_parse_config (struct m_can_classdev *cdv)
{
   struct tcan4x5x_priv *tcan4x5x = cdev->device_data;
   Int ret;

   tcan4x5x->device_wake_gpio = devm_gpiod_get (cdev->dev、"device-wake"、
                     GPIOD_OUT_HIGH);
   if (is_ERR(tcan4x5x->device_wake_gpio)){
      dev_err (cdev->dev、"device-wake GPIO 未定义\n");
      //返回-EINVAL;
   }

   //tcan4x5x->reset_GPIO = devm_gpiod_get_optional (cdev->dev、"reset"、
   //                      GPIOD_OUT_LOW);
   tcan4x5x->reset_GPIO = of_get_named_gpio(cdev->dev->of_node、"tcan-reset"、0);
   if (tcan4x5x->reset_GPIO <0){
      //tcan4x5x->RESET_GPIO = NULL;
      printk ("lim %s %d\n"、__func__、__line__);
   其他(else)
      if (GPIO_is_valid (tcan4x5x->reset_GPIO){
         printk ("lim %s %d\n"、__func__、__line__);
         REt = GPIO_request (tcan4x5x->RESET_GPIO、"tcanreset");
         如果(ret){
            printk (Kern_ERR "%s":LIM 复位 GPIO 请求失败"、__func__);
         其他(else)
            printk ("lim %s %d\n"、__func__、__line__);
            GPIO_DIRECTION_OUTPUT (tcan4x5x->RESET_GPIO、0);
         }
      }
   }

   REt = tcan4x5x_reset (tcan4x5x);
   IF (RET)
      返回支架;

   tcan4x5x->device_state_pio = devm_gpiod_get_optional (cdv->dev、
                          "器件状态"、
                          GPIOD_IN);
   如果(IS_ERR (tcan4x5x->DEVICE_STATE_GPIO))
      tcan4x5x->device_state_pio = NULL;

   tcan4x5x->power = devm_regulator_get_optional (cdev->dev、
                       "VSUP");
   如果(ptr_ERR (tcan4x5x->power)==-EPROBE_DEFPIT)
      返回-EPROBE_DEFPIT;

   返回0;


静态常量结构 regmap_config tcan4x5x_regmap ={
   .reg_bits = 32、
   .val_bits = 32、
   .cache_type = REGCACHE_none、
   .max_register = TCAN4X5X_MAX_register、
};

静态结构 m_can_ops tcan4x5x_ops ={
   .init = tcan4x5x_init、
   .read_reg = tcan4x5x_read_reg、
   .write_reg = tcan4x5x_write_reg、
   write_fifo = tcan4x5x_write_fifo、
   .read_fifo = tcan4x5x_read_fifo、
   .clear_interrupts = tcan4x5x_clear_interrupts、
};

静态 int tcan4x5x_can_probe (struct spi_device *spi)
{
   struct tcan4x5x_priv *priv;
   struct m_can_classdev *mcan_class;
   int freq、ret;

   mcan_class = m_can_class_allocate_dev (&spi->dev);
   如果(!mcan_class)
      返回-ENOMEM;

   PRIV = devm_kzalloc (&spi->dev、sizeof (* priv)、gfp_kernel);
   如果(!priv)
      返回-ENOMEM;

   mcan_class->device_data = priv;

   m_can_class_get_Clocks (mcan_class);
   if (is_ERR(mcan_class->cclk){
      dev_err (&spi->dev、"no can clock source defined\n");
      FREQ = TCAN4X5X_EXT_CLK_DEF;
   }其他{
      Freq = clk_get_rate (mcan_class->cclk);
   }

   /*完整性检查*/
   if (freq < 20000000 || freq > TCAN4X5X_EXT_CLK_DEF)
      返回-ERANGE;

   PRIV->REG_OFFSET = TCAN4X5X_MCAN_OFFSET;
   PRIV->MRAM_START = TCAN4X5X_MRAM_START;
   PRIV->SPI = SPI;
   PRIV->mcan_dev = mcan_class;

   mcan_class->pm_clock_support = 0;
   mcan_class->can.clock.freq = freq;
   mcan_class->dev =&SPI->dev
   mcan_class->ops =&tcan4x5x_ops;
   mcan_class->is_peripheral = true;
   mcan_class->net->IRQ = SPI->IRQ;

   SPI_SET_drvdata (spi、priv);

   REt = tcan4x5x_parse_config (mcan_class);
   IF (RET)
      转至 out_clk;

   /*配置 SPI 总线*/
   SPI->BITS_PER_WORD = 32;
   REt = SPI_SETUP (SPI);
   IF (RET)
      转至 out_clk;

   PRIV->regmap = devm_regmap_init (&spi->dev、&tcan4x5x_bus、
               &SPI->DEV,&tcan4x5x_regmap;
   如果(is_ERR(priv->regmap)){
      REt = PTR_ERR (priv->regmap);
      转至 out_clk;
   }

   tcan4x5x_power_enable (priv->power、1);

   REt = tcan4x5x_init (mcan_class);
   IF (RET)
      转至 out_power;

   REt = m_can_class_register (mcan_class);
   IF (RET)
      转至 out_power;

   netdev_info (mcan_class->net、"TCAN4X5X 成功初始化。\n");
   返回0;

out_power:
   tcan4x5x_power_enable (priv->power、0);
out_clk:
   if (!is_ERR(mcan_class->cclk){
      clk_disable_unpreparate (mcan_class->cclk);
      clk_disable_unpreparate (mcan_class->hclk);
   }

   dev_err (&spi->dev、"Probe failed, err=%d\n"、ret);
   返回支架;


静态 int tcan4x5x_can_remove (结构 SPI_DEVICE *SPI)
{
   struct tcan4x5x_priv *priv = spi_get_drvdata (spi);

   m_can_class_unregister (priv->mcan_dev);

   tcan4x5x_power_enable (priv->power、0);

   返回0;


static const struct of_device_id tcan4x5x_of_match[]={
   {.compatible ="ti,tcan4x5x",},
   {}
};
module_device_table (of、tcan4x5x_of_match);

静态常量结构 spi_device_id tcan4x5x_id_table[]={
   {
      .name      ="tcan4x5x"、
      .driver_data   = 0、
   }、
   {}
};
module_device_table (spi、tcan4x5x_id_table);

静态结构 SPI_driver tcan4x5x_can_driver ={
   .driver ={
      .name = device_name、
      .of_match_table = tcan4x5x_of_match、
      .pm = NULL、
   }、
   .id_table = tcan4x5x_id_table、
   .probe = tcan4x5x_can_probe、
   .remove = tcan4x5x_can_remove、
};
module_spi_driver (tcan4x5x_can_driver);

模块作者("Dan Murphy ");
模块描述("德州仪器(TI) TCAN4x5x CAN 驱动器");
module_license ("GPL v2");

m_can.h:

/* SPDX-License-Identifier:GPL-2.0 */
/* Bosch M_CAN 控制器的 CAN 总线驱动器
 *版权所有(C) 2018德州仪器公司- http://www.ti.com/
 */

#ifndef _CAN_M_CAN_H_
#define _CAN_M_CAN_H_

#包含
#包含
#包含
#包含
#包含
#包含
#包含
#包含
#包含
#包含
#包含
#包含
#包含
#包含
#包含
#包含
#包含
#包含
#包含
#包含
#包含
#包含

/* m_CAN LEC 值*/
enum m_can_lec_type{
   LEC_NO_ERROR = 0、
   LEC_STUFF_ERROR、
   LEC_FORM_ERROR、
   LEC_ACK_ERROR、
   LEC_BIT1_ERROR、
   LEC_BIT0_ERROR、
   LEC_CRC_ERROR、
   LEC_UNUSED、
};

enum m_can_mRAM_cfg{
   MRAM_SIDF = 0、
   MRAM_XIDF、
   MRAM_RXF0、
   MRAM_RXF1、
   MRAM_RXB、
   MRAM_TXE、
   MRAM_TXB、
   MRAM_CFG_NUM、
};

/*消息 RAM 中每个 FIFO/缓冲器的地址偏移和元素数量*/
结构 mRAM_cfg{
   U16关闭;
   u8 数字;
};

struct m_can_classdev;
结构 m_can_ops{
   /*特定于器件的回调*/
   int (* clear_interrupts)(struct m_can_classdev *cdev);
   u32 (* read_reg)(struct m_can_classdev *cdev、int reg);
   int (* write_reg)(struct m_can_classdev *cdev、int reg、int val);
   u32 (* read_fifo)(struct m_can_classdev *cdv、int addr_offset);
   int (* write_fifo)(struct m_can_classdev * cdv、int addr_offset、
          Int val);
   int (* init)(struct m_can_classdev *cdev);
};

结构 m_can_classdev{
   struct can_prival can;
   struct napi_struct napi;
   struct net_device *net;
   结构设备*dev;
   结构 clk *hclk;
   struct clk *cclk;

   struct workqueue_struct *tx_wq;
   结构 work_struct tx_work;
   结构 sk_buff * tx_skb;

   结构 can_bittiming_const * bit_timing;
   结构 can_bittiming_const * data_timing;

   struct m_can_ops *ops;

   结构 mutex mcan_lock;

   void * device_data;

   int 版本;
   内部频率;
   u32 irqstatus;

   int pm_clock_support;
   int is_peripheral;

   结构 mRAM_cfg mcfg[mRAM_CFG_NUM];
};

struct m_can_classdev *m_can_class_allocate_dev (struct 设备*dev);
void m_can_class_free_dev (struct net_device *net);
int m_can_class_register (struct m_can_classdev *cdev);
void m_can_class_unregister (struct m_can_classdev *cdev);
int m_can_class_get_Clocks (struct m_can_classdev *cdev);
void m_can_init_ram (struct m_can_classdev *priv);
void m_can_config_endisable (struct m_can_classdev *priv、bool enable);

int m_can_class_suspend (结构设备*dev);
int m_can_class_resume (结构设备*dev);
#endif   /*_CAN_M_H_*/

m_can.c:

// SPDX-License-Identifier:GPL-2.0
//针对 Bosch M_CAN 控制器的 CAN 总线驱动器
//版权所有(C) 2014 Freescale Semiconductor、Inc.
//     董爱生
//版权所有(C) 2018-19德州仪器(TI)公司- http://www.ti.com/

/* Bosch M_CAN 用户手册可从以下位置获取:
 * www.bosch-semiconductors.de/.../
 * mcan_users_manual_v302.pdf
 */

#包含
#包含
#包含
#包含
#包含
#包含
#包含
#包含
#包含
#包含
#包含
#包含

#include "m_can.h"

/*寄存器定义*/
enum m_can_reg{
   M_CAN_CREL   = 0x0、
   M_CAN_ENDN   = 0x4、
   M_CAN_CUST   = 0x8、
   M_CAN_DBTP   = 0xc、
   M_CAN_TEST   = 0x10
   M_CAN_RWD   = 0x14、
   M_CAN_CCCR   = 0x18、
   M_CAN_NBTP   = 0x1c、
   M_CAN_TSCC   = 0x20、
   M_CAN_TSCV   = 0x24、
   M_CAN_TOCC   = 0x28、
   M_CAN_TOCV   = 0x2C、
   M_CAN_ECR   = 0x40、
   M_CAN_PSR   = 0x44、
/* TDCR 寄存器仅适用于版本>= 3.1.x */
   M_CAN_TDCR   = 0x48、
   M_CAN_IR   = 0x50、
   M_CAN_IE   = 0x54、
   M_CAN_ILS   = 0x58、
   M_CAN_Ile   = 0x5c、
   M_CAN_GFC   = 0x80、
   M_CAN_SIDFC   = 0x84、
   M_CAN_XIDFC   = 0x88、
   M_CAN_XIDAM   = 0x90、
   M_CAN_HPM   = 0x94、
   M_CAN_NDAT1   = 0x98、
   M_CAN_NDAT2   = 0x9C、
   M_CAN_RXF0C   = 0xa0、
   M_CAN_RXF0S   = 0xa4、
   M_CAN_RXF0A   = 0xa8、
   M_CAN_RXBC   = 0xac、
   M_CAN_RXF1C   = 0xb0、
   M_CAN_RXF1S   = 0xb4、
   M_CAN_RXF1A   = 0xb8、
   M_CAN_RXESC   = 0xbc、
   M_CAN_TXBC   = 0xc0、
   M_CAN_TXFQS   = 0xc4、
   M_CAN_TXESC   = 0xc8、
   M_CAN_TXBRP   = 0xcc、
   M_CAN_TXBAR   = 0xd0、
   M_CAN_TXBCR   = 0xd4、
   M_CAN_TXBTO   = 0xd8、
   M_CAN_TXBCF   = 0xdc、
   M_CAN_TXBTIE   = 0xe0、
   M_CAN_TXBCIE   = 0xe4、
   M_CAN_TXEFC   = 0xf0、
   M_CAN_TXEFS   = 0xf4、
   M_CAN_TXEFA   = 0xF8、
};

/* NAPI 相关*/
#define M_CAN_NAPI_Weight   64

/*消息 RAM 配置数据长度*/
#define MRAM_CFG_LEN   8

/*内核释放寄存器(CREL)*/
#define CREL_REL_SHIFT      28
#define CREL_REL_MASK      (0xF << CREL_REL_SHIFT)
#define CREL_STEP_SHIFT      24
#define CREL_STEP_MASK (      0xF << CREL_STEP_SHIFT)
#define CREL_SUBSTEP_SHIFT   20
#define CREL_SUBSTEP_MASK (   0xF << CREL_SUBSTEP_SHIFT)

/*数据位时序和预分频器寄存器(DBTP)*/
#define DBTP_TDC      位(23)
#define DBTP_DBRP_SHIFT      16
#define DBTP_DBRP_MASK      (0x1f << DBTP_DBRP_SHIFT)
#define DBTP_DTSEG1_SHIFT   8
#define DBTP_DTSEG1_MASK   (0x1f << DBTP_DTSEG1_SHIFT)
#define DBTP_DTSEG2_SHIFT   4
#define DBTP_DTSEG2_MASK (   0xF << DBTP_DTSEG2_SHIFT)
#define DBTP_DSJW_SHIFT      0
#define DBTP_DSJW_MASK (      0xF << DBTP_DSJW_SHIFT)

/*发送器延迟补偿寄存器(TDCR)*/
#define TDCR_TDCO_SHIFT      8
#define TDCR_TDCO_MASK (      0x7F << TDCR_TDCO_SHIFT)
#define TDCR_TDCF_SHIFT      0
#define TDCR_TDCF_MASK (      0x7F << TDCR_TDCF_SHIFT)

/*测试寄存器(TEST)*/
#define TEST_LBCK      位(4)

/* CC 控制寄存器(CCCR)*/
#define CCCR_CMR_MASK      0x3
#define CCCR_CMR_SHIFT      10
#define CCCR_CMR_CANFD      0x1
#define CCCR_CMR_CANFD_BRS   0x2
#define CCCR_CMR_CAN      0x3
#define CCCR_CME_MASK      0x3
#define CCCR_CME_SHIFT      8
#define CCCR_CME_CAN      0
#define CCCR_CME_CANFD      0x1
#define CCCR_CME_CANFD_BRS   0x2
#define CCCR_TXP      bit (14)(定义 CCCR_TXP 位)
#define CCCR_TEST      位(7)
#define CCCR_DAR      位(6)
#define CCCR_MON      位(5)
#define CCCR_CSR      位(4)
#define CCCR_CSA      bit (3)(定义 CCCR_CSA 位)
#define CCCR_asm      bit (2)(定义 CCCR_ASM 位)
#define CCCR_CCE      位(1)
#define CCCR_init      bit (0)(定义 CCCR_init 位)
#define CCCR_CANFD      0x10
/*版本>= 3.1.x */
#define CCCR_EFBI      位(13)
#define CCCR_PXHD      位(12)
#define CCCR_BRSE      位(9)
#define CCCR_FDOE      bit (8)(定义 CCCR_FDOE 位)
/*仅适用于版本>= 3.2.x */
#define CCCR_NISO      bit (15)(定义 CCCR_NISO 位)

/*标称位时序和预分频器寄存器(NBTP)*/
#define NBTP_NSJW_SHIFT      25
#define NBTP_NSJW_MASK      (0x7f << NBTP_NSJW_SHIFT)
#define NBTP_NBRP_SHIFT      16
#define NBTP_NBRP_MASK      (0x1ff << NBTP_NBRP_SHIFT)
#define NBTP_NTSEG1_SHIFT   8
#define NBTP_NTSEG1_MASK   (0xff << NBTP_NTSEG1_SHIFT)
#define NBTP_NTSEG2_SHIFT   0
#define NBTP_NTSEG2_MASK (   0x7f << NBTP_NTSEG2_SHIFT)

/*错误计数器寄存器(ECR)*/
#define ECR_RP         位(15)
#define ECR_REC_SHIFT      8
#define ECR_REC_MASK (      0x7f << ECR_REC_SHIFT)
#define ECR_TEC_SHIFT      0
#define ECR_TEC_MASK      0xff

/*协议状态寄存器(PSR)*/
#define PSR_BO      位(7)
#define PSR_EW      位(6)
#define PSR_EP      位(5)
#define PSR_LEC_MASK   0x7

/*中断寄存器(IR)*/
#define IR_ALL_INT   0xffffffff

/*版本> 3.1.x 的位被重命名*/
#define IR_ARA      位(29)
#define IR_PED      位(28)
#define IR_PEA      位(27)

/*版本3.0.x 的位*/
#define IR_STE      位(31)
#define IR_FOE      位(30)
#define IR_ACKE      BIT (29)
#define IR_BE      位(28)
#define IR_CRCE      bit (27)
#define IR_WDI      位(26)
#define IR_BO      位(25)
#define IR_EW      bit (24)(定义 IR_EW 位)
#define IR_EP      位(23)
#define IR_ELO      位(22)
#define IR_BEU      位(21)
#define IR_BEC      位(20)
#define IR_DRX      位(19)
#define IR_TOO      位(18)
#define IR_MRAF      位(17)
#define IR_TSW      位(16)
#define IR_TEFL      位(15)
#define IR_TEFF      位(14)
#define IR_TEFW      位(13)
#define IR_TEFN      位(12)
#define IR_TFE      位(11)
#define IR_TCF      位(10)
#define IR_TC      位(9)
#define IR_HPM      位(8)
#define IR_RF1L      位(7)
#define IR_RF1F      位(6)
#define IR_RF1W      位(5)
#define IR_RF1N      位(4)
#define IR_RF0L      位(3)
#define IR_RF0F      位(2)
#define IR_RF0W      位(1)
#define IR_RF0N      位(0)
#define IR_ERR_STATE   (IR_BO | IR_EW | IR_EP)

/*版本3.0.x 的中断*/
#define IR_ERR_LEC_30X   (IR_STE   | IR_FOE | IR_ACKE | IR_BE | IR_CRCE)
#define IR_ERR_BUS_30X   (IR_ERR_LEC_30X| IR_WDI | IR_ELO | IR_BUU |\
         IR_BEC | IR_TOO | IR_MRAF | IR_TSW | IR_TEFL |\
         IR_RF1L | IR_RF0L)
#define IR_ERR_ALL_30X   (IR_ERR_STATE | IR_ERR_BUS_30X)
/*版本中断>= 3.1.x */
#define IR_ERR_LEC_31X   (IR_PED | IR_PEA)
#define IR_ERR_BUS_31X     IR_ERR_LEC_31X | IR_WDI | IR_ELO | IR_BUU |\
         IR_BEC | IR_TOO | IR_MRAF | IR_TSW | IR_TEFL |\
         IR_RF1L | IR_RF0L)
#define IR_ERR_ALL_31X   (IR_ERR_STATE | IR_ERR_BUS_31X)

/*中断线路选择(ILS)*/
#define ILS_ALL_INT0 0x0    
#define ILS_ALL_INT1   0xFFFFFFFF

/*中断线路使能(Ile)*/
#define Ile_EINT1   位(1)
#define Ile_EINT0   位(0)

/* Rx FIFO 0/1配置(RXF0C/RXF1C)*/
#define RXFC_FWM_SHIFT   24
#define RXFC_FWM_MASK   (0x7f << RXFC_FWM_SHIFT)
#define RXFC_FS_SHIFT   16
#define RXFC_FS_MASK (   0x7f << RXFC_FS_SHIFT)

/* Rx FIFO 0/1状态(RXF0S/RXF1S)*/
#define RXFS_RFL   位(25)
#define RXFS_FF      位(24)
#define RXFS_FPI_SHIFT   16
#define RXFS_FPI_MASK   0x3f0000
#define RXFS_FGI_SHIFT   8
#define RXFS_FGI_MASK   0x3f00
#define RXFS_FFL_MASK   0x7f

/* Rx 缓冲区/ FIFO 元素大小配置(RXESC)*/
#define M_CAN_RXESC_8BYTES   0x0
#define M_CAN_RXESC_64BYTES   0x777

/* Tx 缓冲器配置(TXBC)*/
#define TXBC_NDTB_SHIFT      16
#define TXBC_NDTB_MASK (      0x3f << TXBC_NDTB_SHIFT)
#define TXBC_TFQS_SHIFT      24
#define TXBC_TFQS_MASK (      0x3f << TXBC_TFQS_SHIFT)

/* Tx FIFO/队列状态(TXFQS)*/
#define TXFQS_TFQF      位(21)
#define TXFQS_TFQPI_SHIFT   16
#define TXFQS_TFQPI_MASK (   0x1f << TXFQS_TFQPI_SHIFT)
#define TXFQS_TFGI_SHIFT   8
#define TXFQS_TFGI_MASK (      0x1f << TXFQS_TFGI_SHIFT)
#define TXFQS_TFFL_SHIFT   0
#define TXFQS_TFFL_MASK (      0x3f << TXFQS_TFFL_SHIFT)

/* Tx 缓冲区元素大小配置(TXESC)*/
#define TXESC_TBDS_8BYTES   0x0
#define TXESC_TBDS_64BYTES   0x7

/* Tx 事件 FIFO 配置(TXEFC)*/
#define TXEFC_EFS_SHIFT      16
#define TXEFC_EFS_MASK (      0x3f << TXEFC_EFS_SHIFT)

/* Tx 事件 FIFO 状态(TXEFS)*/
#define TXEFS_TEFL      位(25)
#define TXEFS_EFF      位(24)
#define TXEFS_EFGI_SHIFT   8
#define   TXEFS_EFGI_MASK (      0x1f << TXEFS_EFGI_SHIFT)
#define TXEFS_EFFL_SHIFT   0
#define TXEFS_EFFL_MASK (      0x3f << TXEFS_EFFL_SHIFT)

/* Tx 事件 FIFO 确认(TXEFA)*/
#define TXEFA_EFAI_SHIFT   0
#define TXEFA_EFAI_MASK (      0x1f << TXEFA_EFAI_SHIFT)

/*消息 RAM 配置(以字节为单位)*/
#define SIDF_ELEMENT_SIZE   4
#define XIDF_ELEMENT_SIZE   8
#define RXF0_ELEMENT_SIZE   72
#define RXF1_ELEMENT_SIZE   72
#define rxB_ELEMENT_SIZE   72
#define TXE_ELEMENT_SIZE   8
#define TXB_ELEMENT_SIZE   72

/*消息 RAM 元素*/
#define M_CAN_FIFO_ID      0x0
#define M_CAN_FIFO_DLC      0x4
#define M_CAN_FIFO_DATA (   n)(0x8 +((n)<< 2))

/* Rx 缓冲区元素*/
/* R0 */
#define RX_BUF_ESI      位(31)
#define RX_BUF_Xtd      位(30)
#define RX_BUF_RTR      位(29)
/* R1 */
#define RX_BUF_ANMF      位(31)
#define RX_BUF_FDF      位(21)
#define RX_BUF_BRS      bit (20)(定义 RX_BUF_BRS 位)

/* Tx 缓冲区元素*/
/* T0 */
#define TX_BUF_ESI      位(31)
#define TX_BUF_Xtd      位(30)
#define TX_BUF_RTR      位(29)
/* T1 */
#define TX_BUF_EFC      位(23)
#define TX_BUF_FDF      位(21)
#define TX_BUF_BRS      bit (20)(定义 TX_BUF_BRS 位)
#define TX_BUF_MM_SHIFT      24
#define TX_BUF_MM_MASK      (0xff << TX_BUF_MM_SHIFT)

/* Tx 事件 FIFO 元素*/
/* e1 */
#define TX_EVENT_MM_SHIFT TX_BUF_MM_SHIFT    
#define TX_EVENT_MM_MASK   (0xff << TX_EVENT_MM_SHIFT)

静态内联 u32 m_can_read (struct m_can_classdev *cdev、enum m_can_reg)
{
   返回 cdev->ops->read_reg (cdv、reg);


静态内联 void m_can_write (struct m_can_classdev *cdev、enum m_can_reg、
               u32 val)
{
   cdv->ops->write_reg (cdv、reg、val);


静态 u32 m_can_fifo_read (struct m_can_classdev *cdev、
           u32 fgi、无符号 int 偏移)
{
   u32 addr_offset = cdV->mcfg[mRAM_RXF0].off + fgi * RXF0_ELEMENT_SIZE +
          偏移;

   返回 cdev->ops->read_fifo (cdv、addr_offset);


静态 void m_can_fifo_write (struct m_can_classdev *cdv、
             u32 fpi、无符号 int 偏移、u32 val)
{
   u32 addr_offset = cdV->mcfg[mRAM_TXB].off + FPI * TXB_ELEMENT_SIZE +
          偏移;

   cdc->ops->write_fifo (cdv、addr_offset、val);


静态内联 void m_can_fifo_write_no_off (struct m_can_classdev *cdv、
                 u32 fpi、u32 val)
{
   cdev->ops->write_fifo (cdv、fpi、val);


静态 u32 m_can_txe_fifo_read (struct m_can_classdev * cdev、u32 fgi、u32 offset)
{
   u32 addr_offset = cdev->mcfg[mRAM_Txe].off + fgi * txe_element_size +
          偏移;

   返回 cdev->ops->read_fifo (cdv、addr_offset);


静态内联 bool m_can_tx_fifo_full (struct m_can_classdev *cdv)
{
      返回!(m_can_read (cdev、M_CAN_TXFQS)和 TXFQS_TFQF);


void m_can_config_endisable (struct m_can_classdev *cdev、bool enable)
{
   U32 cccr = m_can_read (cdev、M_can_CCCR);
   U32超时= 10;
   u32 val = 0;
   // int tmp、tmpp = 0x0808 - 0x1000;

   /*如果时钟停止请求被设置、则清除该请求*/
   IF (CCCR 和 CCCR_CSR)
      CCCR &=~CCCR_CSR;

   如果(启用){             //不
      /*如果时钟停止请求被设置、则清除该请求*/
      if (cccr & CCCR_CSR){
         CCCR &=~CCCR_CSR;
         //TCAN4550_DBG ("%s"(%d) cccr &=~CCCR_CSR:0x%X\n"、__func__、__line__、cccr);
      }
#if 0
      /*测试*/
      M_CAN_WRITE (cdv、M_CAN_CCCR、0x18);
      PR_INFO ("######################## 写入 M_CAN_CCCR 0x18、读取0x%X.\n"、m_CAN_read (cdev、M_CAN_CCCR));

      tmp = m_can_read (cdev、M_can_IR);
      PR_INFO ("######################## 读取 M_CAN_IR 0x%X.\n"、tmp);
      M_CAN_WRITE (cdev、M_CAN_IR、tmp | 0x55);
      PR_INFO ("######################## 写入 M_CAN_IR 和0x55、读取0x%X.\n"、m_CAN_read (cdev、M_can_IR);

      PR_INFO ("|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| \n");

      m_can_write (cdv、tmpp、0xDBD5);
      PR_INFO ("######################## 写入0x0808 0xDBD5、读取0x%X.\n"、m_CAN_read (cdev、M_CAN_CCCR));

      tmp = m_can_read (cdv、tmpp);
      PR_INFO ("######################## 读取0x0808 0x%X.\n"、tmp);

      udelay (10);
#endif
      /*启用 m_can 配置*/
      M_CAN_WRITE (cdv、M_CAN_CCCR、cccr | CCCR_init);
      udelay (5);
      /*只有当 CCCR.init ='1'时、CCCR.CCE 才能被置位/复位*/
      m_can_write (cdv、M_CAN_CCCR、cccr | CCCR_init | CCCR_CCE);
   }其他{
      M_CAN_WRITE (cdv、M_CAN_CCCR、cccr &~(CCCR_init | CCCR_CCE));
   }

   /*模块初始化有延迟*/
   if (启用)
      VAL = CCCR_INIT | CCCR_CCE;

   while (((m_can_read (cdv、m_can_ccr)&(CCCR_init | CCCR_CCE))!= val){
      如果(timeout == 0){
         netdev_warn(cdev->net,"Failed to init module\n");
         返回;
      }
      超时--;
      udelay (1);
   }


静态内联 void m_can_enable_all_interrupts (struct m_can_classdev *cdev)
{
   /*此驱动程序中仅使用中断行0 */
   M_CAN_WRITE (cdev、M_CAN_Ile、Ile_EINT0);


静态内联 void m_can_disable_all_interrupts (struct m_can_classdev *cdev)
{
   M_CAN_WRITE (cdv、M_CAN_Ile、0x0);


静态空 m_can_clean (struct net_device *net)
{
   struct m_can_classdev *cdev = netdev_priv(net);

   if (cdev->tx_skb){
      int putidx = 0;

      net->stats.tx_errors++;
      如果(cdev->version >30)
         putidx =(((m_can_read (cdv、M_can_TXFQS)&
              TXFQS_TFQPI_MASK)>> TXFQS_TFQPI_SHIFT);

      can_free_echo_skb (cdev->net、putidx);
      cdev->tx_skb = NULL;
   }


静态 void m_can_read_fifo (struct net_device *dev、u32 rxfs)
{
   struct net_device_stats *stats =&dev->stats;
   struct m_can_classdev *cdev = netdev_priv (dev);
   struct canfd_FRAME *cf;
   结构 sk_buff * skb;
   u32 id、fgi、dlc;
   INT I;

   /*计算读取数据的 FIFO 获取索引*/
   fgi =(rxfs 和 RXFS_FGI_MASK)>> RXFS_FGI_SHIFT;
   DLC = m_can_fifo_read (cdev、fgi、M_can_FIFO_DLC);
   IF (DLC 和 RX_BUF_FDF)
      SKB = alloc_canfd_skb (dev、&cf);
   否则
      SKB = alloc_can_skb (dev、(结构 CAN_FRAME **)&cf);
   如果(!skb){
      stats->rx_drops++;
      返回;
   }

   IF (DLC 和 RX_BUF_FDF)
      cf->len = can_dlc2len ((DLC >> 16)和0x0F);
   否则
      cf ->len = GET_CAN_DLC ((DLC >> 16)和0x0F);

   ID = m_can_fifo_read (cdev、fgi、M_can_FIFO_ID);
   如果(ID 和 RX_BUF_Xtd)
      cf->can_id =(id & can_EFF_mask)| can_EFF_FLAG;
   否则
      cf ->can_id =(id >> 18)和 can_SFF_mask;

   如果(ID 和 RX_BUF_ESI){
      cf -> flags |= CANFD_ESI;
      netdev_dbg (dev,"ESI 错误\n");
   }

   如果(!(DLC & RX_BUF_FDF)&&(ID 和 RX_BUF_RTR){
      cf ->can_id |= can_rtr_FLAG;
   }其他{
      中频(DLC 和 RX_BUF_BRS)
         cf->flags |= CANFD_BRS;

      对于(i = 0;i < cf -> len;i += 4)
         *(u32 *)(cf->data + i)=
            m_can_fifo_read (cdev、fgi、
                  M_CAN_FIFO_DATA (I / 4));
   }

   /*确认 Rx FIFO 0 */
   M_CAN_WRITE (cdv、M_CAN_RXF0A、fgi);

   stats->rx_packets++;
   stats->rx_Bytes += cf->len;

   netif_receive_skb (skb);


静态 int m_can_do_Rx_poll (struct net_device *dev、int quota)
{
   struct m_can_classdev *cdev = netdev_priv (dev);
   u32 pkts = 0;
   u32 rxfs、num;

   rxfs = m_can_read (cdev、M_can_RXF0S);
   if (!(rxfs & RXFS_FFL_MASK){
      netdev_dbg (dev、"no messages in fifo0\n");
      返回0;
   }

   while (rxfs & RXFS_FFL_mask){
      IF (rxfs 和 RXFS_RFL)
         netdev_warn (dev、"Rx FIFO 0消息丢失\n");

      //TCAN4550_DBG ("^^^^^^ 已调用%s (%d)。 读取 fifo、rxfs:0x%X\n"、__func__、__line__、rxfs);
      m_can_read_fifo (dev、rxfs);

      //配额--;
      Pkts++;
      rxfs = m_can_read (cdev、M_can_RXF0S);
   }

   if (pkts)
      CAN_LED_EVENT (dev、CAN_LED_EVENT_RX);

   返回 pkts;


静态 int m_can_handle_lost_msg (struct net_device *dev)
{
   struct net_device_stats *stats =&dev->stats;
   结构 sk_buff * skb;
   struct can_FRAME *帧;

   netdev_err (dev,"msg lost in rxf0\n");

   stats->rx_errors++;
   stats->rx_over_errors++;

   SKB = alloc_can_err_skb (dev、&frame);
   如果(不太可能(!skb))
      返回0;

   frame->can_id |= can_ERR_CRTL;
   FRAME->DATA[1]= CAN_ERR_CRTL_RX_FLOOP;

   netif_receive_skb (skb);

   返回1;


static int m_can_handle_LEC_err (struct net_device *dev、
            enum m_CAN_LEC_TYPE LEC_TYPE)
{
   struct m_can_classdev *cdev = netdev_priv (dev);
   struct net_device_stats *stats =&dev->stats;
   struct can_FRAME *cf;
   结构 sk_buff * skb;

   cdev->can.can_stats.bus_error++;
   stats->rx_errors++;

   /*将错误条件传播到 CAN 堆栈*/
   SKB = alloc_can_err_skb (dev、&cf);
   如果(不太可能(!skb))
      返回0;

   /*检查"最后一个错误代码"、它会告诉我们
   * CAN 总线上发生的最后一个错误的类型
   */
   cf ->can_id |= can_ERR_PROT | can_ERR_BUSERROR;

   开关(LEC_TYPE){
   案例 LEC_STUFF_ERROR:
      netdev_dbg (dev,"stff error\n");
      cf->data[2]|= CAN_ERR_PROT_stuff;
      中断;
   案例 LEC_FORM_ERROR:
      netdev_dbg (dev,"form error\n");
      cf->data[2]|= CAN_ERR_PROT_FORM;
      中断;
   案例 LEC_ACK_ERROR:
      netdev_dbg (dev,"ack error\n");
      cf->data[3]= CAN_ERR_PROT_LOC_ACK;
      中断;
   案例 LEC_BIT1_ERROR:
      netdev_dbg (dev,"bit1错误\n");
      cf->data[2]|= CAN_ERR_PROT_BIT1;
      中断;
   案例 LEC_BIT0_ERROR:
      netdev_dbg (dev,"bit0错误\n");
      cf->data[2]|= CAN_ERR_PROT_BIT0;
      中断;
   案例 LEC_CRC_ERROR:
      netdev_dbg (dev,"crc error\n");
      cf->data[3]= CAN_ERR_PROT_LOC_CRC_SEQ;
      中断;
   默认值:
      中断;
   }

   stats->rx_packets++;
   stats->rx_Bytes += cf->can_dlc;
   netif_receive_skb (skb);

   返回1;


static int __m_can_get_Berr_counter (const struct net_device *dev、
               结构 can_Berr_counter *bec
{
   struct m_can_classdev *cdev = netdev_priv (dev);
   无符号 int ECR;

   ECR = m_can_read (cdev、M_CAN_ECR);
   bec->rxerr =(ECR & ECR_REC_MASK)>>ECR_REC_SHIFT;
   bec->txerr =(ECR 和 ECR_TEC_MASK)>>ECR_TEC_SHIFT;

   返回0;


静态 int m_can_clk_start (struct m_can_classdev *cdv)
{
   int 错误;

   如果(cdev->pm_clock_support == 0)
      返回0;

   ERR = PM_RUNTIME_GET_SYNC (cdev->dev);
   if (err <0){
      PM_runtime_put_noidle(cdev->dev);
      返回错误;
   }

   返回0;


静态 void m_can_clk_stop (struct m_can_classdev *cdv)
{
   if (cdev->pm_clock_support)
      PM_runtime_put_sync (cdev->dev);


静态 int m_can_get_Berr_counter (const struct net_device *dev、
             结构 can_Berr_counter *bec
{
   struct m_can_classdev *cdev = netdev_priv (dev);
   int 错误;

   ERR = m_can_clk_start (cdv);
   if (err)
      返回错误;

   __m_can_get_Berr_counter (dev、bec);

   m_can_clk_stop (cdev);

   返回0;


静态 int m_can_handle_state_change (struct net_device *dev、
                枚举 can_state new_state)
{
   struct m_can_classdev *cdev = netdev_priv (dev);
   struct net_device_stats *stats =&dev->stats;
   struct can_FRAME *cf;
   结构 sk_buff * skb;
   STRUT CAN_BERR_COUNTER BEC;
   无符号 int ECR;

   开关(new_state){
   案例 CAN_State_ERROR_WARNING:
      /*错误警告状态*/
      cdev->can.can_stats.error_warning++;
      cdev->can.state = CAN_STATE_ERROR_WARNING;
      中断;
   案例 CAN_State_ERROR_PASSIVE:
      /*错误被动状态*/
      cdev->can.can_stats.error_passive++;
      cdev->can.state = CAN_State_error_passive;
      中断;
   案例 CAN_State_bus_off:
      /*总线关闭状态*/
      cdev->can.state = CAN_State_bus_off;
      m_can_disable_all_interrupts (cdev);
      cdev->can.can_stats.bus_off++;
      can_Bus_off (dev);
      中断;
   默认值:
      中断;
   }

   /*将错误条件传播到 CAN 堆栈*/
   SKB = alloc_can_err_skb (dev、&cf);
   如果(不太可能(!skb))
      返回0;

   __m_can_get_Berr_counter (dev、&BEC);

   开关(new_state){
   案例 CAN_State_ERROR_WARNING:
      /*错误警告状态*/
      cf ->can_id |= can_ERR_CRTL;
      cf->data[1]=(bec.txerr > bec.rxerr)?
         CAN_ERR_CRTL_TX_WARNING:
         CAN_ERR_CRTL_RX_WARNING;
      cf->data[6]=bec.txerr;
      cf->data[7]=bec.rxerr;
      中断;
   案例 CAN_State_ERROR_PASSIVE:
      /*错误被动状态*/
      cf ->can_id |= can_ERR_CRTL;
      ECR = m_can_read (cdev、M_CAN_ECR);
      IF (ECR 和 ECR_RP)
         cf->data[1]|= CAN_ERR_CRTL_RX_PASSIVE;
      IF (BEC.txerr > 127)
         cf ->data[1]|= CAN_ERR_CRTL_TX_PASSIVE;
      cf->data[6]=bec.txerr;
      cf->data[7]=bec.rxerr;
      中断;
   案例 CAN_State_bus_off:
      /*总线关闭状态*/
      cf ->can_id |= can_ERR_BUSOFF;
      中断;
   默认值:
      中断;
   }

   stats->rx_packets++;
   stats->rx_Bytes += cf->can_dlc;
   netif_receive_skb (skb);

   返回1;


静态 int m_can_handle_state_errors (struct net_device *dev、u32 PSR)
{
   struct m_can_classdev *cdev = netdev_priv (dev);
   int work_done = 0;

   if (PSR & PSR_EW && cdev->can.state!= CAN_STATE_ERROR_WARNING){
      netdev_dbg (dev,"Entered error warning state\n");
      Work_done += m_can_handle_state_change (dev、
                        CAN_State_error_warning);
   }

   if (PSR & PSR_EP && cdev->can.state!= CAN_STATE_ERROR_PASSIVE){
      netdev_dbg (dev,"Entered error passive state\n");
      Work_done += m_can_handle_state_change (dev、
                        CAN_State_ERROR_PASSIVE);
   }

   if (PSR & PSR_BO && cdev->can.state!= CAN_STATE_BUS_OFF){
      netdev_dbg (dev,"输入错误总线关闭状态\n");
      Work_done += m_can_handle_state_change (dev、
                        CAN_State_bus_off);
   }

   返回 work_done;


静态 void m_can_handle_other_err (struct net_device *dev、u32 irqstatus)
{
   if (irqstatus 和 IR_WDI)
      netdev_err (dev,"Message RAM Watchdog"事件,由于缺少就绪\n");
   if (irqstatus 和 IR_ELO)
      netdev_err (dev,"Error Logging Overflow\n");
   IF (irqstatus 和 IR_BEU)
      netdev_err (dev,"位错误未校正\n");
   IF (irqstatus 和 IR_BEC)
      netdev_err (dev,"bit error corrected\n");
   if (irqstatus 和 ir_too)
      netdev_err (dev,"Timeout ached\n");
   IF (irqstatus 和 IR_MRAF)
      netdev_err (dev,"出现消息 RAM 访问失败\n");


静态内联 bool is_LEC_err (u32 PSR)
{
   PSR &= LEC_UNUSED;

   返回 PSR &&(PSR!= LEC_UNUSED);


静态内联 bool m_can_is_protocol_err (u32 irqstatus)
{
   //TCAN4550_DBG ("%s"(%d)已调用。\n"、__func__、__line__);
   返回 irqstatus 和 IR_ERR_LEC_31X;


静态 int m_can_handle_protocol_error (struct net_device *dev、u32 irqstatus)
{
   struct net_device_stats *stats =&dev->stats;
   struct m_can_classdev *cdev = netdev_priv (dev);
   struct can_FRAME *cf;
   结构 sk_buff * skb;

   //TCAN4550_DBG ("%s"(%d)已调用。\n"、__func__、__line__);

   /*将错误条件传播到 CAN 堆栈*/
   SKB = alloc_can_err_skb (dev、&cf);

   /*由于存在协议错误、因此更新 TX 错误统计信息*/
   stats->TX_ERROR++;

   /*更新仲裁丢失状态*/
   if (cdev->version >= 31&&(irqstatus & IR_PEA){
      netdev_dbg (dev,"Protocol error in Arbitration fail\n");
      cdev->can.can_stats.arbitration_lost++;
      如果(skb){
         cf ->can_id |= can_ERR_LOSTARB;
         cf->data[0]|= CAN_ERR_LOSTARB_UNSPEC;
      }
   }

   如果(不可能(!skb)){
      netdev_dbg (dev,"skb 分配失败\n");
      返回0;
   }
   netif_receive_skb (skb);

   返回1;


静态 int m_CAN_Handle_BUS_ERRORS (struct net_device *dev、u32 irqstatus、
              u32 PSR)
{
   struct m_can_classdev *cdev = netdev_priv (dev);
   int work_done = 0;

   IF (irqstatus 和 IR_RF0L)
      Work_done += m_can_handle_lost_msg (dev);

   /*处理总线上的 LEC 错误*/
   if ((cdev->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)&&
      is_LEC_err (PSR))
      work_done += m_can_handle_LEC_err (dev、PSR 和 LEC_unused);

   /*处理仲裁阶段的协议错误*/
   if ((cdev->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)&&
      m_can_is_protocol_err (irqstatus)){
      //TCAN4550_DBG ("%s"(%d)已调用。\n"、__func__、__line__);
      work_done += m_can_handle_protocol_error (dev、irqstatus);
   }

   //TCAN4550_DBG ("%s"(%d)已调用。\n"、__func__、__line__);

   /*其他未处理的错误中断*/
   m_can_handle_other_err (dev、irqstatus);

   返回 work_done;


静态 int m_can_rx_handler (struct net_device *dev、int quota)
{
   struct m_can_classdev *cdev = netdev_priv (dev);
   int work_done = 0;
   U32 irqstatus, PSR;

   irqstatus = cdev->irqstatus | m_can_read (cdv、m_can_ir);
   如果(!irqstatus)
      转至结束;

   /*针对"不需要激活 MRAF IRQ"问题的勘误解决方法
   *在 MCAN 处于错误被动状态时的帧接收期间
   *并且接收错误计数器的值为 MCAN_ECR.REC = 127
   *尽管没有设置 MCAN_IR.MRAF、但可能会发生
   *消息 RAM 访问失败。
   *如果启用了 MCAN_IR.MRAF、则会生成到主机 CPU 的中断
   *消息 RAM 访问失败中断例程需要检查
   *无论 MCAN_ECR.RP 是'1'还是 MCAN_ECR.REC = 127。
   *在这种情况下,重置 mCAN_IR.MRAF。 无需采取进一步措施。
   */
   如果(cdev->version <= 31 && irqstatus & IR_MRAF &&
      M_CAN_Read (cdev、M_CAN_ECR)和 ECR_RP){
      STRUT CAN_BERR_COUNTER BEC;

      __m_can_get_Berr_counter (dev、&BEC);
      if (bec.rxerr == 127){
         M_CAN_WRITE (cdev、M_CAN_IR、IR_MRAF);
         irqstatus &=~IR_MRAF;
      }
   }

   PSR = m_can_read (cdev、M_CAN_PSR);

   if (irqstatus 和 IR_ERR_STATE)
      Work_done += m_can_handle_state_errors(dev, PSR);

   IF (irqstatus 和 IR_ERR_BUS_30X)
      work_done += m_can_handle_BUS_errors (dev、irqstatus、PSR);

   IF (irqstatus 和 IR_RF0N)
      work_done += m_can_do_Rx_poll (dev、(quota - work_done));
结束:
   返回 work_done;


静态 int m_can_rx_peripheral (struct net_device *dev)
{
   struct m_can_classdev *cdev = netdev_priv (dev);

   m_can_rx_handler (dev、M_CAN_NAPI_weight);

   m_can_enable_all_interrupts (cdev);

   返回0;


静态 int m_can_poll (struct napi_struct *napi、int quota)
{
   struct net_device *dev = napi->dev;
   struct m_can_classdev *cdev = netdev_priv (dev);
   int work_done;

   Work_Done = m_can_Rx_handler (dev、quota);
   如果(Work_done < quota){
      napi_complete_done (napi、work_done);
      m_can_enable_all_interrupts (cdev);
   }

   返回 work_done;


静态空 m_can_echo_tx_event (struct net_device *dev)
{
   u32 TXE_COUNT = 0;
   u32 m_can_txfles;
   u32 fgi = 0;
   INT I = 0;
   无符号 int msg_mark;

   struct m_can_classdev *cdev = netdev_priv (dev);
   struct net_device_stats *stats =&dev->stats;

   /*读取 TX 事件 FIFO 状态*/
   m_can_txefs = m_can_read (cdv、m_can_TXEFS);

   /*获取 Tx 事件 FIFO 元素计数*/
   TXE_COUNT =(m_can_txefs 和 TXEFS_EFFL_MASK)
         >> TXEFS_EFFL_SHIFT;

   /*获取并处理所有发送的元素*/
   对于(i = 0;i < Txe_count;i++){
      /*检索获取索引*/
      FGi =(m_can_read (cdv、M_can_TXEFS)和 TXefs_EFGI_MASK)
         >> TXEFS_EFGI_SHIFT;

      /*获取消息标记*/
      MSG_MARK =(m_can_txe_fifo_read (cdv、fgi、4)&
            TX_EVENT_MM_MASK)>> TX_EVENT_MM_SHIFT;

      /* ack TXE 元素*/
      M_CAN_WRITE (cdev、M_CAN_TXEFA、(TXEFA_EFAI_MASK 和
                  (fgi << TXEFA_EFAI_SHIFT));

      /*更新统计信息*/
      stats->tx_bytes += can_get_echo_skb (dev、msg_mark);
      stats->TX_packets++;
   }


静态 irqreturn_t m_can_isr (int IRQ、void *dev_id)
{
   struct net_device *dev =(struct net_device *) dev_id;
   struct m_can_classdev *cdev = netdev_priv (dev);
   struct net_device_stats *stats =&dev->stats;
   u32 ir;

   //TCAN4550_DBG ("%s"(%d)已调用。\n"、__func__、__line__);

   mutex_lock (&cdev->mcan_lock);

   IR = m_can_read (cdev、M_CAN_IR);
   如果(!ir){
      PR_INFO ("%s"(%d)已调用。\n"、__func__、__line__);
      mutex_unlock (&cdev->mcan_lock);
      返回 IRQ_NONE;
   }
   /*确认所有 IRQ */
   IF (IR 和 IR_ALL_INT)
      m_can_write (cdev、m_can_ir);

   if (cdev->ops->clear_interrupts)
      cdv->ops->clear_interrupts (cdv);

   /*在发生以下情况时安排 NAPI
   *-接收 IRQ
   *-状态更改 IRQ
   *-总线错误 IRQ 和总线错误报告
   */
   if (((ir & IR_RF0N)||(ir & IR_ERR_ALL_30X)){
      cdev->irqstatus = ir;
      m_can_disable_all_interrupts (cdev);
      if (!cdev->is_peripheral)
         napi_schedule (&cdev->napi);
      否则
         m_can_rx_peripheral (dev);
   }

   if (cdev->version ==30){
      IF (IR 和 IR_TC){
         /*传输完成中断*/
         stats->tx_bytes += can_get_echo_skb (dev、0);
         stats->TX_packets++;
         //TCAN4550_DBG ("%s"(%d)已调用。\n"、__func__、__line__);
         //can_led_event (dev、CAN_LED_EVENT_TX);
         netif_wake_queue (dev);
      }
   }其他 {
      if (ir & IR_TEFN){
         /*已到达新的 TX FIFO 元素*/
         m_can_echo_tx_event (dev);
         CAN_LED_EVENT (dev、CAN_LED_EVENT_TX);
         if (netif_queue_stopped (dev)&&
            !M_CAN_TX_fifo_full (cdev)
            netif_wake_queue (dev);
      }
   }

   //TCAN4550_DBG ("%s"(%d)已调用。\n"、__func__、__line__);

   mutex_unlock (&cdev->mcan_lock);
   返回 IRQ_Handling;


静态常量结构 can_bittiming_const m_can_bittiming_const_30x ={
   .name = KBUILD_ModName、
   .tseg1_min = 2、      /*时间段1 = prop_seg + phase_seg1 */
   .tseg1_max = 64、
   .tseg2_min = 1、      /*时间段2 = PHASE_seg2 */
   .tseg2_max = 16、
   .SJW_max = 16、
   .BRP_MIN = 1、
   .BRP_max = 1024、
   .brp_inc = 1、
};

静态常量结构 can_bittiming_const m_can_data_bittiming_const_30x ={
   .name = KBUILD_ModName、
   .tseg1_min = 2、      /*时间段1 = prop_seg + phase_seg1 */
   .tseg1_max = 16、
   .tseg2_min = 1、      /*时间段2 = PHASE_seg2 */
   .tseg2_max = 8、
   .SJW_max = 4、
   .BRP_MIN = 1、
   .BRP_max = 32、
   .brp_inc = 1、
};

静态常量结构 can_bittiming_const m_can_bittiming_const_31X ={
   .name = KBUILD_ModName、
   .tseg1_min = 2、      /*时间段1 = prop_seg + phase_seg1 */
   .tseg1_max = 256、
   .tseg2_min = 1、      /*时间段2 = PHASE_seg2 */
   .tseg2_max = 128、
   .SJW_max = 128、
   .BRP_MIN = 1、
   .BRP_max = 512、
   .brp_inc = 1、
};

静态常量结构 can_bittiming_const m_can_data_bittiming_const_31x ={
   .name = KBUILD_ModName、
   .tseg1_min = 1、      /*时间段1 = prop_seg + PHASE_seg1 */
   .tseg1_max = 32、
   .tseg2_min = 1、      /*时间段2 = PHASE_seg2 */
   .tseg2_max = 16、
   .SJW_max = 16、
   .BRP_MIN = 1、
   .BRP_max = 32、
   .brp_inc = 1、
};

静态 int m_can_set_bittiming (struct net_device *dev)
{
   struct m_can_classdev *cdev = netdev_priv (dev);
   const 结构 can_bittiming *bt =&cdev->can.bittiming;
   const 结构 can_bittiming * DBT =&cdev->can.data_bittiming;
   u16 BRP、SJW、tseg1、tseg2;
   U32 REG_BTP;

   BRP=bt->BRP-1;
   SJW = bt->sjw - 1;
   tseg1 = bt->prop_seg + bt->phase_seg1 - 1;
   tseg2 = bt->phase_seg2 -1;
   REG_BTP =(BRP << NBTP_NBRP_SHIFT)|(SJW << NBTP_NSJW_SHIFT)|
      (tseg1 << NBTP_NTSEG1_SHIFT)|(tseg2 << NBTP_NTSEG2_SHIFT);
   m_can_write (cdev、M_CAN_NBTP、reg_BTP);

   if (cdev->can.ctrlmode & CAN_CTRLMODE_FD){
      REG_BTP = 0;
      BRP = DBT->BRP -1;
      SJW = DBT->SJW - 1;
      tseg1 = dbt->prop_seg + dbt->phase_seg1 -1;
      tseg2 = dbt->phase_seg2 -1;

      /*仅当比特率超过2.5MB/s 时、才需要 TDC。
      *这在"CAN FD 的位时间要求"一节中提到
      *在2013年国际 CAN 大会上发表的论文
      */
      如果(DBT->bitrate > 2500000){
         U32 tdco, SSP;

         /*使用相同的二次采样点值
         *作为数据采样点
         */
         SSP = DBT->SAMPLE_POINT;

         /*公式基于 Bosch 的 M_CAN 用户手册
         *发送器延迟补偿部分
         */
         tdco =(cdev->can.clock.freq / 1000)*
               SSP/DBT->bitrate;

         /*最大有效 TDCO 值是127 */
         如果(tdco > 127){
            netdev_warn (dev、"TDCO 值%u 超出最大值。 使用最大可能值\n"、
                  tdco);
            tdco = 127;
         }

         REG_BTP |= DBTP_TDC;
         M_CAN_WRITE (cdev、M_CAN_TDCR、
               tdco << TDCR_TDCO_SHIFT);
      }

      REG_BTP |=(BRP << DBTP_DBRP_SHIFT)|
           (SJW << DBTP_DSJW_SHIFT)|
           (tseg1 << DBTP_DTSEG1_SHIFT)|
           (tseg2 << DBTP_DTSEG2_SHIFT);

      M_CAN_WRITE (cdv、M_CAN_DBTP、reg_BTP);
   }

   返回0;


/*配置 M_CAN 芯片:
 *-设置 Rx 缓冲区/ FIFO 单元大小
 *-配置接收 FIFO
 *-接受不匹配的帧进入 FIFO 0
 *-配置 TX 缓冲器
 *      ->= v3.1.x:使用 TX FIFO
 *-配置模式
 *-设置位计时
 */
静态 void m_CAN_CHIP_CONFIG (struct net_device *dev)
{
   struct m_can_classdev *cdev = netdev_priv (dev);
   U32 cccr、测试;

   m_can_config_endisable (cdev、true);

   /* RX 缓冲器/FIFO 元素大小64字节数据字段*/
   M_CAN_WRITE (cdev、M_CAN_RXESC、M_CAN_RXESC_64BYTES);

   /*接受非匹配帧进入 FIFO 0 */
   M_CAN_WRITE (cdv、M_CAN_GFC、0x0);

   if (cdev->version ==30){
      //TCAN4550_DBG ("$$$$$$$$$ 读取 M_CAN_SIDFC 0x%X\n"、m_CAN_read (cdv、M_CAN_SIDFC);
      //TCAN4550_DBG ("$$$$$$$$$ 写入 M_CAN_SIDFC 0x%X\n"、(1 << TXBC_NDTB_SHIFT)|
      //      cdv->mcfg[mRAM_sidf].off);
      M_CAN_WRITE (cdev、M_CAN_SIDFC、(1 << TXBC_NDTB_SHIFT)|
            cdev->mcfg[mRAM_sidf].off);
   }

   /* XID */
   if (cdev->version ==30){
      //TCAN4550_DBG ("$$$$$$$$$ 读取 M_CAN_XIDFC 0x%X\n"、m_can_read (cdv、M_can_XIDFC);
      //TCAN4550_DBG ("$$$$$$$$$ 写入 M_CAN_XIDFC 0x%X\n"、(1 << TXBC_NDTB_SHIFT)|
      //      cdev->mcfg[mRAM_XIDF].off);
      M_CAN_WRITE (cdev、M_CAN_XIDFC、(1 << TXBC_NDTB_SHIFT)|
            cdev->mcfg[mRAM_XIDF].off);
   }

   /* Tx 缓冲器*/
   if (cdev->version ==30){
      /*当前仅支持一个 Tx 缓冲器*/
      M_CAN_WRITE (cdev、M_CAN_TXBC、(1 << TXBC_NDTB_SHIFT)|
            cdev->mcfg[mRAM_TXB].off);
   }其他{
      /* TX FIFO 用于较新的 IP 内核版本*/
      M_CAN_WRITE (cdv、M_CAN_TXBC、
            (cdev->mcfg[mRAM_TXB].num << TXBC_TFQS_SHIFT)|
            (cdev->mcfg[mRAM_TXB].off);
   }

   /*支持64字节有效载荷*/
   M_CAN_WRITE (cdv、M_CAN_TXESC、TXESC_TBDS_64BYTES);

   /* TX 事件 FIFO */
   if (cdev->version ==30){
      M_CAN_WRITE (cdv、M_CAN_TXEFC、(1 << TXEFC_EFS_SHIFT)|
            cdev->mcfg[mRAM_TXe].off);
   }其他{
      /*使用完整的 TX 事件 FIFO */
      M_CAN_WRITE (cdv、M_CAN_TXEFC、
            ((cdev->mcfg[mRAM_Txe].num << TXEFS_SHIFT)
             和 TXEFS_MASK)|
            cdev->mcfg[mRAM_TXe].off);
   }

   /* Rx FIFO 配置、阻塞模式、FIFO 大小1 */
   M_CAN_WRITE (cdev、M_CAN_RXF0C、
         (cdev->mcfg[mRAM_RXF0].num << RXFC_fs_shift)|
          cdev->mcfg[mRAM_RXF0].off);

   M_CAN_WRITE (cdv、M_CAN_RXF1C、
         (cdev->mcfg[mRAM_RXF1].num << RXFC_fs_shift)|
          cdev->mcfg[mRAM_RXF1].off);

   CCCR = m_can_read (cdev、M_CAN_CCCR);
   测试= m_can_read (cdv、m_can_test);
   TEST &=~TEST_LBCK;
   if (cdev->version ==30){
   /*版本3.0.x */

      CCCR &=~(CCCR_TEST | CCCR_MON |
         (CCCR_CMR_MASK << CCCR_CMR_SHIFT)|
         (CCCR_CME_MASK << CCCR_CME_SHIFT));

      if (cdev->can.ctrlmode & CAN_CTRLMODE_FD)
         cccr |= CCCR_CME_CANFD_BRS << CCCR_CME_SHIFT;

   }其他{
   /*版本3.1.x 或3.2.x */
      CCCR &=~(CCCR_TEST | CCCR_MON | CCCR_BRSE | CCCR_FDOE |
          CCCR_NISO);

      /*只有3.2.x 实现了 NISO 位*/
      IF (cdev->can.ctrlmode 和 CAN_CTRLMODE_FD_NON_ISO)
         CCCR |= CCCR_NISO;

      if (cdev->can.ctrlmode & CAN_CTRLMODE_FD)
         CCCR |=(CCCR_BRSE | CCCR_FDOE);
   }

   /*环回模式*/
   if (cdev->can.ctrlmode & CAN_CTRLMODE_Loopback){
      CCCR |= CCCR_TEST | CCCR_MON;
      TEST |= TEST_LBCK;
   }

   /*启用监视(所有版本)*/
   如果(cdev->can.ctrlmode 和 CAN_CTRLMODE_LISTENONLY)
      CCCR |= CCCR_MON;

   /*禁用自动重发(所有版本)*/
   if (cdev->can.ctrlmode 和 CAN_CTRLMODE_ONE_SHOT)
      CCCR |= CCCR_DAR;

   //TCAN4550_DBG ("######## 已调用%s (%d)。" 、__func__、__line__);

   /*写入配置*/
   M_CAN_WRITE (cdv、M_CAN_CCCR、cccr);
   M_CAN_WRITE (cdv、M_CAN_test、测试);

   /*启用中断*/
   M_CAN_WRITE (cdev、M_CAN_IR、IR_ALL_INT);
   if (!(cdev->can.ctrlmode 和 CAN_CTRLMODE_BERR_REPORTING))
      如果(cdev->version =30)
         M_CAN_WRITE (cdev、M_CAN_IE、IR_ALL_INT 和
               ~(IR_ERR_LEC_30X));
      否则
         M_CAN_WRITE (cdev、M_CAN_IE、IR_ALL_INT 和
               ~(IR_ERR_LEC_31X);
   否则
      M_CAN_WRITE (cdev、M_CAN_IE、IR_ALL_INT);

   /*将所有中断路由到 INT0 */
   M_CAN_WRITE (cdv、M_CAN_ILS、ILS_ALL_INT0);

   /*设置位时序参数*/
   m_can_set_bittiming (dev);

   m_can_config_endisable (cdv、false);

   if (cdev->ops->init)
      cdv->ops->init(cdev);


静态空 m_can_start (struct net_device *dev)
{
   struct m_can_classdev *cdev = netdev_priv (dev);

   /*基本 m_can 配置*/
   m_can_chip_config (dev);

   cdev->can.state = CAN_STATE_ERROR_ACTIVE;

   m_can_enable_all_interrupts (cdev);


静态 int m_can_set_mode (struct net_device *dev、enum can_mode 模式)
{
   开关(模式){
   案例 CAN_MODE_START:
      m_can_clean (dev);
      m_can_start (dev);
      netif_wake_queue (dev);
      中断;
   默认值:
      返回-EOPNOTSup;
   }

   返回0;


/*检查 M_CAN 的内核发布编号
 *如果检测到不受支持的设备,则返回0
 *否则它会返回版本和步骤编码为:
 *返回值= 10 * + 1 *
 */
静态 int m_can_check_core_release (struct m_can_classdev *cdv)
{
   u32 crel_reg;
   U8引脚;
   U8步进;
   内部分辨率;

   /*读取内核版本并分成版本号
   *示例:版本3.2.1 => rel=3;步骤=2;子步骤=1 ;
   */
   //crel_reg = m_can_read (cdv、m_can_CREL);
   crel_reg = m_can_read (cdv、(M_CAN_ENDN)- 0x1000);
   //crel_reg *= 2;
   //TCAN4550_DBG ("\n%s (%d) crel_reg:0x%X.\n"、__func__、__line__、crel_reg);
   Rel =(u8)(((crel_reg & CREL_REL_MASK)>> CREL_REL_SHIFT);
   STEP =(u8)(((crel_reg & CREL_STEP_MASK)>> CREL_STEP_SHIFT);

   如果(rel===3){
      /* M_CAN v3.x.y:创建返回值*/
      RES = 30 +阶跃;
   }其他{
      /*不支持的 M_CAN 版本*/
      RES = 0;
   }

   返回分辨率;


/*仅在版本3.2.x 中支持非 ISO
 *此函数检查该位是否可写入。
 */
静态 bool m_can_niso_supported (struct m_can_classdev *cdev)
{
   u32 cccr_reg、cccr_poll = 0;
   int niso_timeout =-ETIMEDOUT;
   INT I;

   m_can_config_endisable (cdev、true);
   cccr_reg = m_can_read (cdev、M_can_CCCR);
   cccr_reg |= CCCR_NISO;
   M_CAN_WRITE (cdv、M_CAN_CCCR、cccr_reg);

   对于(i = 0;i <= 10;i++){
      cccr_poll = m_can_read (cdev、M_CAN_CCCR);
      if (cccr_poll == cccr_reg){
         niso_timeout = 0;
         中断;
      }

      usleep_range (1、5);
   }

   /*清除 NISO */
   cccr_reg &&~(CCCR_NISO);
   M_CAN_WRITE (cdv、M_CAN_CCCR、cccr_reg);

   m_can_config_endisable (cdv、false);

   /*如果超时(-ETIMEDOUT)、则返回 false、否则返回 true */
   返回!niso_timeout;


静态 int m_can_dev_setup (struct m_can_classdev *m_can_dev)
{
   struct net_device *dev = m_can_dev->net;
   int m_can_version;

   m_can_version = m_can_check_core_release (m_can_dev);
   /*如果版本不受支持则返回*/
   如果(!m_can_version){
      dev_err (m_can_dev->dev、"Unsupported version number:%2d"、
         m_can_version);
      //返回-EINVAL;
   }

   if (!m_can_dev->is_peripheral)
      netif_napi_add (dev、&m_can_dev->NAPI、
               M_CAN_POLL、M_CAN_NAPI_Weight);

   /*所有 M_CAN 版本的共享属性*/
   m_can_dev->version = m_can_version;
   m_can_dev->can.do_set_mode = m_can_set_mode;
   m_can_dev->can.do_get_Berr_counter = m_can_get_Berr_counter;

   /*设置 M_CAN 支持的操作*/
   m_can_dev->can.ctrlmode_supported = CAN_CTRLMODE_loopback |
               CAN_CTRLMODE_LISTENONLY |
               CAN_CTRLMODE_BERR_REPORTING |
               CAN_CTRLMODE_FD |
               CAN_CTRLMODE_ONE_SHOT;

   /*根据 M_CAN 版本设置属性*/
   switch (m_can_dev->version){
   情形30:
      /* CAN_CTRLMODE_FD_NON_ISO 随 M_CAN IP v3.0.x 固定*/
      CAN_SET_STATIC_ctrlmode (DEV、CAN_CTRLMODE_FD_NON_ISO);
      m_can_dev->can.bittiming_const = m_can_dev->bit_timing?
         m_can_dev->bit_timing:&m_can_bittiming_const_30x;

      m_can_dev->can.data_bittiming_const = m_can_dev->data_timing?
                  m_can_dev->data_timing:
                  &m_can_data_bittiming_const_30X;
      中断;
   情形31:
      /* CAN_CTRLMODE_FD_NON_ISO 在 M_CAN IP v3.1.x 中固定*/
      CAN_SET_STATIC_ctrlmode (DEV、CAN_CTRLMODE_FD_NON_ISO);
      m_can_dev->can.bittiming_const = m_can_dev->bit_timing?
         m_can_dev->bit_timing:&m_can_bittiming_const_31x;

      m_can_dev->can.data_bittiming_const = m_can_dev->data_timing?
                  m_can_dev->data_timing:
                  &m_can_data_bittiming_const_31X;
      中断;
   情形32:
   情形33:
      /*支持 MCAN 版本 v3.2.x 和 v3.3.0 */
      m_can_dev->can.bittiming_const = m_can_dev->bit_timing?
         m_can_dev->bit_timing:&m_can_bittiming_const_31x;

      m_can_dev->can.data_bittiming_const = m_can_dev->data_timing?
                  m_can_dev->data_timing:
                  &m_can_data_bittiming_const_31X;

      m_can_dev->can.ctrlmode_supported |=
                  (M_CAN_NISO_SUPPORTED (m_CAN_dev)
                  ? CAN_CTRLMODE_FD_NON_ISO
                  :0);
      中断;
   默认值:
      dev_err (m_can_dev->dev、"Unsupported version number:%2d"、
         m_can_dev->version);
      返回-EINVAL;
   }

   if (m_can_dev->ops->init)
      m_can_dev->ops->init (m_can_dev);

   返回0;


静态空 m_can_stop (struct net_device *dev)
{
   struct m_can_classdev *cdev = netdev_priv (dev);

   /*禁用所有中断*/
   m_can_disable_all_interrupts (cdev);

   //*将初始化模式设置为从网络分离*/
   m_can_config_endisable (cdev、true);

   /*将状态设置为已停止*/
   cdev->can.state = CAN_State_Stopped;


静态 int m_can_close (struct net_device *dev)
{
   struct m_can_classdev *cdev = netdev_priv (dev);

   netif_stop_queue (dev);

   if (!cdev->is_peripheral)
      napi_disable (&cdev->napi);

   m_can_stop (dev);
   m_can_clk_stop (cdev);
   FREE_IRQ (dev->IRQ、dev);

   if (cdev->is_peripheral){
      cdev->tx_skb = NULL;
      destroy_workqueue (cdev->tx_wq);
      cdev->tx_wq = NULL;
   }

   close_candev (dev);
   CAN_LED_EVENT (dev、CAN_LED_EVENT_STOP);

   返回0;


静态 int m_can_next_echo_skb_taken (struct net_device * dev、int putidx)
{
   struct m_can_classdev *cdev = netdev_priv (dev);
   /*回送 SKB 索引的回绕*/
   unsigned int wrap = cdev->can.echo_skb_max;
   int next_idx;

   /*计算下一个索引*/
   next_idx =(++putidx >= wrap? 0:putidx);

   /*检查是否被占用*/
   return !!cdev->can.echo_skb[next_idx];


静态 netdev_tx_t m_can_tx_handler (struct m_can_classdev *cdv)
{
   struct canfd_FRAME *cf =(struct canfd_FRAME *) cdv->TX_skb->data;
   struct net_device *dev = cdev->net;
   struct sk_buff *skb = cdv->tx_skb;
   u32 id、cccr、fdflags;
   INT I;
   int putidx;

   //cdev->tx_skb = NULL;

   /*为 TX 缓冲区元素生成 ID 字段*/
   /*所有受支持的 M_CAN 版本通用*/
   if (CF->can_id & can_EFF_FLAG){
      id = cf->can_id 和 can_EFF_mask;
      ID |= TX_BUF_Xtd;
   }其他{
      ID =((cf->can_id 和 can_sfff_mask)<< 18);
   }

   if (CF->can_id & can_rtr_FLAG)
      ID |= TX_BUF_RTR;

   if (cdev->version ==30){
      netif_stop_queue (dev);

      /*消息 RAM 配置*/
      m_can_fifo_write (cdev、0、M_can_FIFO_ID、id);
      m_can_fifo_write (cdev、0、M_CAN_FIFO_DLC、
            can_len2dlc (cf->len)<<16);

      对于(i = 0;i < cf -> len;i += 4)
         m_can_fifo_write (cdev、0、
               M_CAN_FIFO_DATA (I/4)、
               *(u32 *)(cf->data + i));

      can_put_echo_skb (skb、dev、0);

      if (cdev->can.ctrlmode & CAN_CTRLMODE_FD){
         CCCR = m_can_read (cdev、M_CAN_CCCR);
         cccr &=~(CCCR_CMR_MASK << CCCR_CMR_SHIFT);
         if (can_is_canfd_skb (skb){
            IF (CF->FLAGS 和 CANFD_BRS)
               CCCR |= CCCR_CMR_CANFD_BRS <<
                  CCCR_CMR_SHIFT;
            否则
               CCCR |= CCCR_CMR_CANFD <<
                  CCCR_CMR_SHIFT;
         }其他{
            cccr |= CCCR_CMR_CAN << CCCR_CMR_SHIFT;
         }
         M_CAN_WRITE (cdv、M_CAN_CCCR、cccr);
      }
      M_CAN_WRITE (cdv、M_CAN_TXBTIE、0x1);
      M_CAN_WRITE (cdv、M_CAN_TXBAR、0x1);
      /*版本3.0.x 的 xmit 函数末尾*/

      //TCAN4550_DBG ("%s"(%d)已调用。\n"、__func__、__line__);

      返回 NETDEV_TX_OK;
   }其他{
      /*版本>= v3.1.x 的传输例程*/

      /*检查 FIFO 是否已满*/
      如果(m_can_tx_fifo_full (cdev)){
         /*这不应该发生*/
         netif_stop_queue (dev);
         netdev_warn (dev、
               "尽管 FIFO 已满、TX 队列仍处于活动状态。");

         if (cdev->is_peripheral){
            kfree_skb (skb);
            dev->stats.tx_drops++;
            返回 NETDEV_TX_OK;
         }其他{
            返回 NETDEV_TX_BUSY;
         }
      }

      /*获取帧的放置索引*/
      putidx =(((m_can_read (cdv、M_can_TXFQS)& TXFQS_TFQPI_MASK)
             >> TXFQS_TFQPI_SHIFT);
      /*将 ID 字段写入 FIFO 元素*/
      m_can_fifo_write (cdev、putidx、M_can_FIFO_ID);

      /*获取帧的 CAN FD 配置*/
      fdflags = 0;
      if (can_is_canfd_skb (skb){
         fdbags |= TX_BUF_FDF;
         IF (CF->FLAGS 和 CANFD_BRS)
            fdbags |= TX_BUF_BRS;
      }

      /*构造 DLC 字段。 还包含 CAN-FD 配置
      *使用 FIFO 的存储索引作为消息标记
      *它在 TX 中断中用于
      *发送正确的回波帧
      */
      m_can_fifo_write (cdev、putidx、M_CAN_FIFO_DLC、
            ((Putidx << TX_BUF_MM_SHIFT)和
             TX_BUF_MM_MASK)|
            (can_len2dlc (cf->len)<< 16)|
            fdbags | TX_BUF_EFC);

      对于(i = 0;i < cf -> len;i += 4)
         m_can_fifo_write (cdev、putidx、M_CAN_FIFO_DATA (i / 4)、
               *(u32 *)(cf->data + i));

      /*推送回送。
      *将根据消息标记在 TX 中断上环回
      */
      can_put_echo_skb (skb、dev、putidx);

      /*启用 TX FIFO 元素以开始传输 */
      M_CAN_WRITE (cdev、M_CAN_TXBAR、(1 << putidx));

      /*如果 FIFO 已满、则停止网络队列*/
      如果(m_can_tx_fifo_full (cdev)||
         m_can_next_echo_skb_已占用(dev、putidx))
         netif_stop_queue (dev);
   }

   返回 NETDEV_TX_OK;


静态空 m_can_tx_work_queue (struct work_struct *ws)
{
   struct m_can_classdev *cdev = container_of (ws、struct m_can_classdev、
                  工作);

   M_CAN_TX_handler (cdv);
   cdev->tx_skb = NULL;
   //TCAN4550_DBG ("######## 已调用%s (%d)。" 、__func__、__line__);


静态 netdev_tx_t m_can_start_xmit (struct sk_buff *skb、
               结构 net_device *dev)
{
   struct m_can_classdev *cdev = netdev_priv (dev);

   如果(can_droped_invalid_skb (dev、skb))
      返回 NETDEV_TX_OK;

   if (cdev->is_peripheral){
      if (cdev->tx_skb){
         netdev_err (dev,"hard_xmit called while TX business\n");
         返回 NETDEV_TX_BUSY;
      }

      if (cdev->can.state == can_state_bus_off){
         m_can_clean (dev);
      }其他{
         /*需要停止队列以避免大量请求
         *从发送。  建议的改进是通过
         *一种排队机制,可以排队等待 SKBS 和
         *按顺序处理。
         */
         cdev->tx_skb = skb;
         //netif_stop_queue (cdev->net);
         Queue_work (cdev->TX_wq、&cdev->TX_work);
      }
   }其他{
      cdev->tx_skb = skb;
      返回 m_can_tx_handler (cdev);
   }

   返回 NETDEV_TX_OK;


静态 int m_can_open (struct net_device *dev)
{
   struct m_can_classdev *cdev = netdev_priv (dev);
   int 错误;

   ERR = m_can_clk_start (cdv);
   if (err)
      返回错误;

   /*打开 CAN 设备*/
   ERR = OPEN_CANDEV (dev);
   如果(err){
      netdev_err (dev,"无法打开 CAN 设备\n");
      转到 EXIT_DISABLE_CLKS;
   }

   /*寄存器中断处理程序*/
   if (cdev->is_peripheral){
      cdev->tx_skb = NULL;
      cdev->tx_wq = alloc_workqueue ("mcan_wq"、
                    WQ_freezable | WQ_MEM_recover、0);
      如果(!cdev->TX_wq){
         ERR =-ENOMEM;
         转至 out_wq_fail;
      }

      init_work (&cdev->TX_work、m_can_TX_work_queue);

      ERR = Requested_Threaded_IRQ (DEV->IRQ、NULL、m_CAN_ISR、
                 IRQF_OneShot | IRQF_TRIGGER_FALLING、
                 dev->name, dev);
   }其他{
      ERR = Request_IRQ (dev->IRQ、m_can_ISR、IRQF_shared、dev->name、
             DEV);
   }

   if (err <0){
      netdev_err (dev,"请求中断失败\n");
      转至 EXIT_IRQ_FAIL;
   }

   mutex_init (&cdev->mcan_lock);
   /*启动 m_can 控制器*/
   m_can_start (dev);

   CAN_LED_EVENT (dev、CAN_LED_EVENT_OPEN);

   if (!cdev->is_peripheral)
      napi_enable (&cdev->napi);

   netif_start_queue (dev);

   返回0;

EXIT_IRQ_FAIL:
   if (cdev->is_peripheral)
      destroy_workqueue (cdev->tx_wq);
out_wq_fail:
   close_candev (dev);
EXIT_DISABLE_CLKS:
   m_can_clk_stop (cdev);
   返回错误;


静态常量结构 net_device_ops m_can_netdev_ops ={
   .nDo_open = m_can_open、
   .nDo_stop = m_can_Close
   .nDo_start_xmit = m_can_start_xmit、
   .ndo_change_mtu = can_change_mtu、
};

静态 int register_m_can_dev (struct net_device *dev)
{
   dev->flags |= IFF_ECHO;   /*我们支持局部 echo */
   dev->netdev_ops =&m_can_netdev_ops;

   返回 register_candev (dev);


静态 void m_can_of_parse_mRAM (struct m_can_classdev *cdev、
            const u32 *MRAM_CONFIG_VA值)
{
   cdev->mcfg[MRAM_SIDF].off = MRAM_CONFIG_VALs[0];
   cdev->mcfg[mRAM_sidf].num = mRAM_CONFIG_VALs[1];
   cdev->mcfg[mRAM_XIDF].off = cdev->mcfg[mRAM_SIDF].off +
         cdev->mcfg[mRAM_sidf].num * sidf_element_size;
   cdev->mcfg[mRAM_XIDF].num = mRAM_CONFIG_VAL[2];
   cdev->mcfg[MRAM_RXF0].off = cdev->mcfg[MRAM_XIDF].off +
         cdev->mcfg[mRAM_xidf].num * xidf_element_size;
   cdev->mcfg[MRAM_RXF0].num = MRAM_CONFIG_VALES[3]和
         (RXFC_FS_MASK >> RXFC_FS_SHIFT);
   cdev->mcfg[MRAM_RXF1].off = cdev->mcfg[MRAM_RXF0].off +
         cdev->mcfg[mRAM_RXF0].num * RXF0_ELEMENT_SIZE;
   cdev->mcfg[MRAM_RXF1].num = MRAM_CONFIG_VAL[2]和
         (RXFC_FS_MASK >> RXFC_FS_SHIFT);
   cdev->mcfg[mRAM_RXB].off = cdev->mcfg[MRAM_RXF1].off +
         cdev->mcfg[mRAM_RXF1].num * RXF1_ELEMENT_SIZE;
   cdev->mcfg[mRAM_RXB].num = MRAM_CONFIG_VA值[5];
   cdev->mcfg[mRAM_TXe].off = cdev->mcfg[mRAM_RXB].off +
         cdev->mcfg[mRAM_RXB].num * rxb_element_size;
   cdev->mcfg[mRAM_TXe].num = mRAM_CONFIG_VARs[6];
   cdev->mcfg[mRAM_TXB].off = cdev->mcfg[MRAM_TXE].off +
         cdev->mcfg[mRAM_TXe].num * txe_element_size;
   cdev->mcfg[mRAM_TXB].num = MRAM_CONFIG_VA值[7]
         (TXBC_NDTB_MASK >> TXBC_NDTB_SHIFT);

   DEV_DBG (cdev->dev)
      "sidf 0x%x %d xidf 0x%x %d rxf0 0x%x %d rxf1 0x%x %d RxB 0x%x %d Txe 0x%x %d TXB 0x%x %x %x %d\n"、
      cdev->mcfg[mRAM_sidf].off、cdev->mcfg[mRAM_sidf].num、
      cdev->mcfg[mRAM_XIDF].off、cdev->mcfg[mRAM_XIDF].num、
      cdev->mcfg[mRAM_RXF0].off、cdev->mcfg[MRAM_RXF0].num、
      cdev->mcfg[mRAM_RXF1].off、cdev->mcfg[MRAM_RXF1].num、
      cdev->mcfg[mRAM_RXB].off、cdev->mcfg[mRAM_RXB].num、
      cdev->mcfg[mRAM_TXe].off、cdev->mcfg[mRAM_TXe].num、
      cdev->mcfg[mRAM_TXB].off、cdev->mcfg[mRAM_TXB].num);


void m_can_init_ram (struct m_can_classdev *cdev)
{
   int end、i、start;

   /*初始化使用中的整个消息 RAM 以避免可能
   *读取未初始化缓冲区时出现 ECC/奇偶校验和错误
   */
   start = cdev->mcfg[mRAM_sidf].off;
   end = cdev->mcfg[mRAM_TXB].off +
      cdev->mcfg[mRAM_TXB].num * TXB_ELEMENT_SIZE;

   对于(i = START;i < END;i += 4)
      m_can_fifo_write_no_off (cdev、I、0x0);

export_symbol_GPL (m_can_init_ram);

int m_can_class_get_Clocks (struct m_can_classdev *m_can_dev)
{
   int ret = 0;

   m_can_dev->hclk = devm_clk_get (m_can_dev->dev、"hclk");
   m_can_dev->cclk = devm_clk_get (m_can_dev->dev、"cclk");

   if (is_ERR(m_can_dev->cclk){
      dev_err (m_can_dev->dev,"no clock found\n");
      REt =-ENODEV;
   }

   返回支架;

export_symbol_GPL (m_can_class_get_Clocks);

struct m_can_classdev *m_can_class_allocate_dev (struct 设备*dev)
{
   struct m_can_classdev *class_dev = NULL;
   u32 MRAM_CONFIG_VA值[MRAM_CFG_LEN];
   struct net_device * net_dev;
   u32 tx_fifo_size;
   Int ret;

   RET = fwnode_property_read_u32_array (dev_fwnode (dev)、
                   "Bosch、MRAM-cfg"、
                   MRAM_CONFIG_VAZ、
                   sizeof (MRAM_CONFIG_VAZ)/ 4);
   如果(ret){
      dev_err (dev、"Could not get Message RAM configuration.");
      转出;
   }

   /*获取 TX FIFO 大小
   *定义回送缓冲器的总数量
   */
   tx_fifo_size = MRAM_CONFIG_VAL[7];

   /*分配 m_can 设备*/
   net_dev = alloc_candev (sizeof (* class_dev)、tx_fifo_size);
   如果(!NET_DEV){
      dev_err (dev、"分配 CAN 设备失败");
      转出;
   }

   class_dev = netdev_priv (net_dev);
   如果(!CLASS_DEV){
      dev_err (dev、"failed to init netdev cdevate");
      转出;
   }

   class_dev->net = net_dev;
   class_dev->dev = dev;
   SET_NETDEV_DEV (NET_DEV、dev);

   m_can_of_parse_mRAM (class_dev、MRAM_CONFIG_vals);
输出:
   返回 class_dev;

export_symbol_GPL (m_can_class_alloc_dev);

void m_can_class_free_dev (struct net_device *net)
{
   free_candev (net);

export_symbol_GPL (m_can_class_free_dev);

int m_can_class_register (struct m_can_classdev *m_can_dev)
{
   Int ret;

   if (m_can_dev->pm_clock_support){
      PM_runtime_enable (m_can_dev->dev);
      REt = m_can_clk_start (m_can_dev);
      IF (RET)
         转至 PM_RUNTIME_FAIL;
   }

   REt = m_can_dev_setup (m_can_dev);
   IF (RET)
      转到 clk_disable;

   REt = REGISTER_m_CAN_DEV (m_can_dev->net);
   如果(ret){
      dev_err (m_can_dev->dev、"注册%s 失败(err=%d)\n"、
         m_can_dev->net->name,ret);
      转到 clk_disable;
   }

   devm_can_led_init (m_can_dev->net);

   of_can_receivator (m_can_dev->net);

   DEV_INFO (m_can_dev->dev)、"%s"设备已注册(IRQ=%d、版本=%d)\n"、
      KBUILD_ModName、m_can_dev->net->IRQ、m_can_dev->version);

   /*探头已完成
   *停止时钟。 它们将在 M_CAN 器件打开后重新激活
   */
CLK_DISABLE:
   m_can_clk_stop (m_can_dev);
PM_RUNTIME_FAIL:
   如果(ret){
      如果(m_can_dev->pm_clock_support)
         PM_RUNTIME_DISABLE (m_can_dev->dev);
      FREE_CANDEV (m_can_dev->net);
   }

   返回支架;

export_symbol_GPL (m_can_class_register);

int m_can_class_suspend (结构设备*dev)
{
   struct net_device * ndev = dev_get_drvdata (dev);
   struct m_can_classdev *cdev = netdev_priv (ndev);

   if (netif_running (ndev)){
      netif_stop_queue (ndev);
      netif_device_detach (ndev);
      m_can_stop (ndev);
      m_can_clk_stop (cdev);
   }

   pinctrl_pm_select_sleep_state (dev);

   cdev->can.state = CAN_State_Sleep;

   返回0;

export_symbol_GPL (m_can_class_SUSPEND);

int m_can_class_resume (结构设备*dev)
{
   struct net_device * ndev = dev_get_drvdata (dev);
   struct m_can_classdev *cdev = netdev_priv (ndev);

   pinctrl_pm_select_default_state (dev);

   cdev->can.state = CAN_STATE_ERROR_ACTIVE;

   if (netif_running (ndev)){
      Int ret;

      REt = m_can_clk_start (cdv);
      IF (RET)
         返回支架;

      m_can_init_ram (cdev);
      m_can_start (ndev);
      netif_device_attach (ndev);
      netif_start_queue (ndev);
   }

   返回0;

export_symbol_GPL (m_can_class_resume);

void m_can_class_unregister (struct m_can_classdev *m_can_dev)
{
   unregister_candev(m_can_dev->net);

   m_can_clk_stop (m_can_dev);

   FREE_CANDEV (m_can_dev->net);

export_symbol_GPL (m_can_class_unregister);

MODULE_PROPERTY ("董爱生") ");
模块作者("Dan Murphy ");
module_license ("GPL v2");
模块描述("用于 Bosch M_CAN 控制器的 CAN 总线驱动器");

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您提供的驱动程序代码不包含任何有关 TCAN4550配置方式的信息。  

    -您能否提供您的设备树绑定,特别是 MRAM 配置?

    -您使用的是传统 CAN 帧还是 CAN FD 帧?

    -什么是标称和数据比特率?

    -您提到您无法发送和接收扩展帧。  您是否收到任何类型的错误消息、您是否在监视错误计数器或总线关闭状态寄存器、还是通过示波器直接观察 CAN 总线等?

    此致、

    乔纳森

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    1.
    器件树:
    +&qupv3_SE14_SPI{
    +      STATUS ="正常";
    +
    +      tcan4x5x:tcan4x5x@0 {
    +              STATUS ="正常";
    +              compatible ="ti,tcan4x5x";
    +              reg =<0>;
    +              #address-Cells =<1>;
    +              #size-cells =<1>;
    +              SPI-max-frequency =<10000000>;
    +              Bosch、MRAM-cfg =<0x0 0 0 32 0 1 1>;
    +              interrupt-parent =<&tlmm>
    +              中断=<123 0x2008>;
    +              // DEVICE-STATE-GPIO =<&GPIO3 21 GPIO_ACTIVE_HIGH>;
    +              // DEVICE-WAKE-GPIO =<&GPIO1 62 GPIO_ACTIVE_HIGH>;
    +              tCAN-RESET =<&tlmm 62 GPIO_ACTIVE_LOW>;
    +      };
    +};
    2.
    tcan4550使用以下测试命令在 Ubuntu 系统上运行
    IP 链路设置 CAN0类型 CAN 比特率500000
    ifconfig CAN0 up

    标准框架测试:
    已发送命令:cansend CAN0 123#000102030405060708             测试结果:通过
    接收命令:candump CAN0                                                测试结果:PASS

    扩展帧:
    发送的命令:cansend CAN0 123456789#000102030405060708  测试结果:通过
    接收命令:candump CAN0                                                测试结果:失败

    可以发送扩展帧,但不能接收扩展帧。 当我们无法接收扩展帧时、不会产生中断。 不生成错误日志。如何调试、它是否与哪些寄存器有关?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    没有可启用或禁用标准 ID (SID)或扩展 ID (XID)的寄存器。  而是通过标识符扩展位(IDE)在报文头本身中设置该位。   

    SID (11位)= IDE 位为显性(0)

    XID (29位)= IDE 位为隐性(1)

    在帧起始位(第一个位)之后会发送11位 ID。 当 IDE 位为隐性时、剩余的18个位将在 IDE 位之后发送、总共产生29个 ID 位。

    我不熟悉所使用的测试结果通过/失败标准。  我的专业知识是在 TCAN4550的器件级别上、我不是 Linux 专家。  我还没有看到 使用 cansend 或 candump 返回通过或失败的测试结果。  它只是检查是否已接收到一条消息、而不用考虑 ID 和数据内容、还是检查是否已接收到与唯一 ID 和/或数据内容匹配的特定消息?

    我注意到的一点是、您使用的消息 ID 包含超过29位。  我不知道该实用程序将如何处理此问题、以及它将使用哪个29位来创建消息 ID、这可能导致无法获得结果、具体取决于测试是如何执行的。  

    0001 0010 0011 0100 0101 0110 0111 1000 1001

    您可以尝试使用小于29位的 XID 吗?

    此致、

    乔纳森

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    目前、设置 XIDFC 寄存器后、我们可以发送和接收扩展帧。 但是、当连接三个器件时、第三个器件无法发送。 您能帮助分析问题所在吗? 您是否仍需要设置其他寄存器?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    好的、看起来你正在使用消息 ID 过滤、并且 XIDFC 寄存器配置你正在使用多少滤波器元件以及针对第一个滤波器元件的 MRAM 起始地址。  您将此寄存器设置为什么?  您应该注意、启用的每个筛选器元素都必须配置一个筛选器、并且不能将其留空。  这是因为当无错误接收消息时、MCAN 控制器将首先扫描从第一个元素开始的所有滤波器元件、并查看消息是否通过了其中一个滤波器。  如果是这样的话、它将被存储在 MRAM RX FIFO 或者 RX New Data 缓冲器元件中、按照特定滤波器的配置。  任何未使用的滤波器元素如果不包含有效数据、将导致此过程中出错。

    使用滤波器时、需要设置扩展 ID 和屏蔽(XIDAM)寄存器和全局滤波器配置(GFC)寄存器。  标准 ID 过滤器配置(SIDFC)寄存器同样也需要针对您拥有的任何 SID 过滤器进行配置。

    作为初始化和配置过程的一部分、您需要将滤波器元素实际写入前面提到的寄存器中分配的 MRAM 空间。  SID 和 XID 过滤器元素决定如何处理匹配的消息。

    更多详细信息、请参见 Bosch 针对 TCAN4550中包含的此控制器 IP 编写的 M_CAN 用户手册。  第2.3和2.4节介绍了不同类型的缓冲器和滤波器元件的寄存器和 MRAM 配置。  您可以在以下链接中找到它。

    https://www.bosch-semiconductors.com/media/ip_modules/pdf_2/m_can/mcan_users_manual_v331.pdf

    如果要接收所有与过滤器不匹配的消息、或者根本不想过滤消息、则应能够将器件配置为接受所有与过滤器不匹配的消息、使其进入两个 RX FIFO 中的一个。  通过这种方式、您仍将接收所有 RX 消息。  这可在全局滤波器配置(GFC)寄存器中进行配置。

    此致、

    乔纳森

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我想寄存器配置参考值、需要提供寄存器详细的配置数据、请帮助、谢谢!

    之前提供的信息没有参考值。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    全局滤波器配置(GFC)寄存器的地址为0x1080。  默认情况下、接受不匹配帧标准(ANFS)和接受不匹配帧扩展(ANFE)字段设置为接受所有不匹配帧进入 RX FIFO 0。  

    目前,设置 XIDFC 寄存器后,我们可以发送和接收扩展帧

    您给 XIDFC (0x1088)寄存器设置了什么值?  您也可以共享 SIDFC (0x1084)、GFC (0x1080)、扩展 ID 和掩码(0x1090)寄存器的值吗?

    但是,连接三个设备时,第三个设备无法发送。

    您能否提供有关测试设置的其他信息?  所有三个器件是否都在使用自己处理器的单独电路板上运行?  它们是否都发送具有唯一消息 ID 的消息?  

    当第三个电路板未能发送消息时、是否有任何错误消息?  

    您是使用范围来验证消息是否未发送、还是只监视从总线上的其他节点接收到的消息来确定消息是否已发送?

    此致、

    乔纳森