Other Parts Discussed in Thread: 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 总线驱动器");
