/*
* at91_can.c - CAN network driver for AT91 SoC CAN controller
*
* (C) 2007 by Hans J. Koch <[email protected]>
* (C) 2008, 2009, 2010, 2011 by Marc Kleine-Budde <[email protected]>
*
* This software may be distributed under the terms of the GNU General
* Public License ("GPL") version 2 as distributed in the 'COPYING'
* file from the main directory of the linux kernel source.
*
*
* Your platform definition file should specify something like:
*
* static struct at91_can_data ek_can_data = {
* transceiver_switch = sam9263ek_transceiver_switch,
* };
*
* at91_add_device_can(&ek_can_data);
*
*/
#include <linux/clk.h>
#include <linux/errno.h>
#include <linux/if_arp.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/rtnetlink.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/platform_data/atmel.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>
#include <linux/can/led.h>
#define AT91_MB_MASK(i) ((1 << (i)) - 1)
/* Common registers */
enum at91_reg {
AT91_MR = 0x000,
AT91_IER = 0x004,
AT91_IDR = 0x008,
AT91_IMR = 0x00C,
AT91_SR = 0x010,
AT91_BR = 0x014,
AT91_TIM = 0x018,
AT91_TIMESTP = 0x01C,
AT91_ECR = 0x020,
AT91_TCR = 0x024,
AT91_ACR = 0x028,
};
/* Mailbox registers (0 <= i <= 15) */
#define AT91_MMR(i) (enum at91_reg)(0x200 + ((i) * 0x20))
#define AT91_MAM(i) (enum at91_reg)(0x204 + ((i) * 0x20))
#define AT91_MID(i) (enum at91_reg)(0x208 + ((i) * 0x20))
#define AT91_MFID(i) (enum at91_reg)(0x20C + ((i) * 0x20))
#define AT91_MSR(i) (enum at91_reg)(0x210 + ((i) * 0x20))
#define AT91_MDL(i) (enum at91_reg)(0x214 + ((i) * 0x20))
#define AT91_MDH(i) (enum at91_reg)(0x218 + ((i) * 0x20))
#define AT91_MCR(i) (enum at91_reg)(0x21C + ((i) * 0x20))
/* Register bits */
#define AT91_MR_CANEN BIT(0)
#define AT91_MR_LPM BIT(1)
#define AT91_MR_ABM BIT(2)
#define AT91_MR_OVL BIT(3)
#define AT91_MR_TEOF BIT(4)
#define AT91_MR_TTM BIT(5)
#define AT91_MR_TIMFRZ BIT(6)
#define AT91_MR_DRPT BIT(7)
#define AT91_SR_RBSY BIT(29)
#define AT91_MMR_PRIO_SHIFT (16)
#define AT91_MID_MIDE BIT(29)
#define AT91_MSR_MRTR BIT(20)
#define AT91_MSR_MABT BIT(22)
#define AT91_MSR_MRDY BIT(23)
#define AT91_MSR_MMI BIT(24)
#define AT91_MCR_MRTR BIT(20)
#define AT91_MCR_MTCR BIT(23)
/* Mailbox Modes */
enum at91_mb_mode {
AT91_MB_MODE_DISABLED = 0,
AT91_MB_MODE_RX = 1,
AT91_MB_MODE_RX_OVRWR = 2,
AT91_MB_MODE_TX = 3,
AT91_MB_MODE_CONSUMER = 4,
AT91_MB_MODE_PRODUCER = 5,
};
/* Interrupt mask bits */
#define AT91_IRQ_ERRA (1 << 16)
#define AT91_IRQ_WARN (1 << 17)
#define AT91_IRQ_ERRP (1 << 18)
#define AT91_IRQ_BOFF (1 << 19)
#define AT91_IRQ_SLEEP (1 << 20)
#define AT91_IRQ_WAKEUP (1 << 21)
#define AT91_IRQ_TOVF (1 << 22)
#define AT91_IRQ_TSTP (1 << 23)
#define AT91_IRQ_CERR (1 << 24)
#define AT91_IRQ_SERR (1 << 25)
#define AT91_IRQ_AERR (1 << 26)
#define AT91_IRQ_FERR (1 << 27)
#define AT91_IRQ_BERR (1 << 28)
#define AT91_IRQ_ERR_ALL (0x1fff0000)
#define AT91_IRQ_ERR_FRAME (AT91_IRQ_CERR | AT91_IRQ_SERR | \
AT91_IRQ_AERR | AT91_IRQ_FERR | AT91_IRQ_BERR)
#define AT91_IRQ_ERR_LINE (AT91_IRQ_ERRA | AT91_IRQ_WARN | \
AT91_IRQ_ERRP | AT91_IRQ_BOFF)
#define AT91_IRQ_ALL (0x1fffffff)
enum at91_devtype {
AT91_DEVTYPE_SAM9263,
AT91_DEVTYPE_SAM9X5,
};
struct at91_devtype_data {
unsigned int rx_first;
unsigned int rx_split;
unsigned int rx_last;
unsigned int tx_shift;
enum at91_devtype type;
};
struct at91_priv {
struct can_priv can; /* must be the first member! */
struct net_device *dev;
struct napi_struct napi;
void __iomem *reg_base;
u32 reg_sr;
unsigned int tx_next;
unsigned int tx_echo;
unsigned int rx_next;
struct at91_devtype_data devtype_data;
struct clk *clk;
struct at91_can_data *pdata;
canid_t mb0_id;
};
static const struct at91_devtype_data at91_at91sam9263_data = {
.rx_first = 1,
.rx_split = 8,
.rx_last = 11,
.tx_shift = 2,
.type = AT91_DEVTYPE_SAM9263,
};
static const struct at91_devtype_data at91_at91sam9x5_data = {
.rx_first = 0,
.rx_split = 4,
.rx_last = 5,
.tx_shift = 1,
.type = AT91_DEVTYPE_SAM9X5,
};
static const struct can_bittiming_const at91_bittiming_const = {
.name = KBUILD_MODNAME,
.tseg1_min = 4,
.tseg1_max = 16,
.tseg2_min = 2,
.tseg2_max = 8,
.sjw_max = 4,
.brp_min = 2,
.brp_max = 128,
.brp_inc = 1,
};
#define AT91_IS(_model) \
static inline int at91_is_sam##_model(const struct at91_priv *priv) \
{ \
return priv->devtype_data.type == AT91_DEVTYPE_SAM##_model; \
}
AT91_IS(9263);
AT91_IS(9X5);
static inline unsigned int get_mb_rx_first(const struct at91_priv *priv)
{
return priv->devtype_data.rx_first;
}
static inline unsigned int get_mb_rx_last(const struct at91_priv *priv)
{
return priv->devtype_data.rx_last;
}
static inline unsigned int get_mb_rx_split(const struct at91_priv *priv)
{
return priv->devtype_data.rx_split;
}
static inline unsigned int get_mb_rx_num(const struct at91_priv *priv)
{
return get_mb_rx_last(priv) - get_mb_rx_first(priv) + 1;
}
static inline unsigned int get_mb_rx_low_last(const struct at91_priv *priv)
{
return get_mb_rx_split(priv) - 1;
}
static inline unsigned int get_mb_rx_low_mask(const struct at91_priv *priv)
{
return AT91_MB_MASK(get_mb_rx_split(priv)) &
~AT91_MB_MASK(get_mb_rx_first(priv));
}
static inline unsigned int get_mb_tx_shift(const struct at91_priv *priv)
{
return priv->devtype_data.tx_shift;
}
static inline unsigned int get_mb_tx_num(const struct at91_priv *priv)
{
return 1 << get_mb_tx_shift(priv);
}
static inline unsigned int get_mb_tx_first(const struct at91_priv *priv)
{
return get_mb_rx_last(priv) + 1;
}
static inline unsigned int get_mb_tx_last(const struct at91_priv *priv)
{
return get_mb_tx_first(priv) + get_mb_tx_num(priv) - 1;
}
static inline unsigned int get_next_prio_shift(const struct at91_priv *priv)
{
return get_mb_tx_shift(priv);
}
static inline unsigned int get_next_prio_mask(const struct at91_priv *priv)
{
return 0xf << get_mb_tx_shift(priv);
}
static inline unsigned int get_next_mb_mask(const struct at91_priv *priv)
{
return AT91_MB_MASK(get_mb_tx_shift(priv));
}
static inline unsigned int get_next_mask(const struct at91_priv *priv)
{
return get_next_mb_mask(priv) | get_next_prio_mask(priv);
}
static inline unsigned int get_irq_mb_rx(const struct at91_priv *priv)
{
return AT91_MB_MASK(get_mb_rx_last(priv) + 1) &
~AT91_MB_MASK(get_mb_rx_first(priv));
}
static inline unsigned int get_irq_mb_tx(const struct at91_priv *priv)
{
return AT91_MB_MASK(get_mb_tx_last(priv) + 1) &
~AT91_MB_MASK(get_mb_tx_first(priv));
}
static inline unsigned int get_tx_next_mb(const struct at91_priv *priv)
{
return (priv->tx_next & get_next_mb_mask(priv)) + get_mb_tx_first(priv);
}
static inline unsigned int get_tx_next_prio(const struct at91_priv *priv)
{
return (priv->tx_next >> get_next_prio_shift(priv)) & 0xf;
}
static inline unsigned int get_tx_echo_mb(const struct at91_priv *priv)
{
return (priv->tx_echo & get_next_mb_mask(priv)) + get_mb_tx_first(priv);
}
static inline u32 at91_read(const struct at91_priv *priv, enum at91_reg reg)
{
return __raw_readl(priv->reg_base + reg);
}
static inline void at91_write(const struct at91_priv *priv, enum at91_reg reg,
u32 value)
{
__raw_writel(value, priv->reg_base + reg);
}
static inline void set_mb_mode_prio(const struct at91_priv *priv,
unsigned int mb, enum at91_mb_mode mode, int prio)
{
at91_write(priv, AT91_MMR(mb), (mode << 24) | (prio << 16));
}
static inline void set_mb_mode(const struct at91_priv *priv, unsigned int mb,
enum at91_mb_mode mode)
{
set_mb_mode_prio(priv, mb, mode, 0);
}
static inline u32 at91_can_id_to_reg_mid(canid_t can_id)
{
u32 reg_mid;
if (can_id & CAN_EFF_FLAG)
reg_mid = (can_id & CAN_EFF_MASK) | AT91_MID_MIDE;
else
reg_mid = (can_id
exynos-combiner.rar_SOC
版权申诉
144 浏览量
2022-09-21
19:26:44
上传
评论
收藏 11KB RAR 举报
weixin_42653672
- 粉丝: 93
- 资源: 1万+
最新资源
- ModStartCMS v8.4.0 框架稳定性持续迭代,修复部分已知问题
- bleder 教室学校学生教育室办公室考试
- 人脸检测-使用OpenCV实现的动漫+漫画人脸检测算法-附项目源码-优质项目实战.zip
- 道路贴图,材质材料免费
- 人脸检测-基于OpenCV+Node.js+WebSockets实现的实时人脸检测应用-附项目源码-优质项目实战.zip
- 一些常见的MySQL死锁案例-mysql-deadlocks-master(源代码+案例+图解说明)
- UE4动画烘焙器-ue4.27
- 新建文件夹.zip
- 1103a2a791bbd96ea98021062e327495b1c422e32fb27e0c2d6404b1bd74b692.gif
- 同城相亲交友php小程序
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈