Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
raspberrypi-kernel
提交
cb2bad86
R
raspberrypi-kernel
项目概览
openeuler
/
raspberrypi-kernel
通知
13
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
raspberrypi-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
cb2bad86
编写于
6月 07, 2011
作者:
D
David S. Miller
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'can/at91-sam9x5' of
git://git.pengutronix.de/git/mkl/linux-2.6
上级
a6b7a407
b9e379bc
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
259 addition
and
112 deletion
+259
-112
drivers/net/can/Kconfig
drivers/net/can/Kconfig
+3
-2
drivers/net/can/at91_can.c
drivers/net/can/at91_can.c
+256
-110
未找到文件。
drivers/net/can/Kconfig
浏览文件 @
cb2bad86
...
...
@@ -58,9 +58,10 @@ config CAN_CALC_BITTIMING
config CAN_AT91
tristate "Atmel AT91 onchip CAN controller"
depends on CAN_DEV &&
ARCH_AT91SAM9263
depends on CAN_DEV &&
(ARCH_AT91SAM9263 || ARCH_AT91SAM9X5)
---help---
This is a driver for the SoC CAN controller in Atmel's AT91SAM9263.
This is a driver for the SoC CAN controller in Atmel's AT91SAM9263
and AT91SAM9X5 processors.
config CAN_TI_HECC
depends on CAN_DEV && ARCH_OMAP3
...
...
drivers/net/can/at91_can.c
浏览文件 @
cb2bad86
...
...
@@ -41,32 +41,7 @@
#include <mach/board.h>
#define AT91_NAPI_WEIGHT 11
/*
* RX/TX Mailbox split
* don't dare to touch
*/
#define AT91_MB_RX_NUM 11
#define AT91_MB_TX_SHIFT 2
#define AT91_MB_RX_FIRST 1
#define AT91_MB_RX_LAST (AT91_MB_RX_FIRST + AT91_MB_RX_NUM - 1)
#define AT91_MB_RX_MASK(i) ((1 << (i)) - 1)
#define AT91_MB_RX_SPLIT 8
#define AT91_MB_RX_LOW_LAST (AT91_MB_RX_SPLIT - 1)
#define AT91_MB_RX_LOW_MASK (AT91_MB_RX_MASK(AT91_MB_RX_SPLIT) & \
~AT91_MB_RX_MASK(AT91_MB_RX_FIRST))
#define AT91_MB_TX_NUM (1 << AT91_MB_TX_SHIFT)
#define AT91_MB_TX_FIRST (AT91_MB_RX_LAST + 1)
#define AT91_MB_TX_LAST (AT91_MB_TX_FIRST + AT91_MB_TX_NUM - 1)
#define AT91_NEXT_PRIO_SHIFT (AT91_MB_TX_SHIFT)
#define AT91_NEXT_PRIO_MASK (0xf << AT91_MB_TX_SHIFT)
#define AT91_NEXT_MB_MASK (AT91_MB_TX_NUM - 1)
#define AT91_NEXT_MASK ((AT91_MB_TX_NUM - 1) | AT91_NEXT_PRIO_MASK)
#define AT91_MB_MASK(i) ((1 << (i)) - 1)
/* Common registers */
enum
at91_reg
{
...
...
@@ -128,12 +103,6 @@ enum at91_mb_mode {
};
/* Interrupt mask bits */
#define AT91_IRQ_MB_RX ((1 << (AT91_MB_RX_LAST + 1)) \
- (1 << AT91_MB_RX_FIRST))
#define AT91_IRQ_MB_TX ((1 << (AT91_MB_TX_LAST + 1)) \
- (1 << AT91_MB_TX_FIRST))
#define AT91_IRQ_MB_ALL (AT91_IRQ_MB_RX | AT91_IRQ_MB_TX)
#define AT91_IRQ_ERRA (1 << 16)
#define AT91_IRQ_WARN (1 << 17)
#define AT91_IRQ_ERRP (1 << 18)
...
...
@@ -156,22 +125,51 @@ enum at91_mb_mode {
#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
;
struct
can_priv
can
;
/* must be the first member! */
struct
net_device
*
dev
;
struct
napi_struct
napi
;
void
__iomem
*
reg_base
;
void
__iomem
*
reg_base
;
u32
reg_sr
;
unsigned
int
tx_next
;
unsigned
int
tx_echo
;
unsigned
int
rx_next
;
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
;
struct
clk
*
clk
;
struct
at91_can_data
*
pdata
;
canid_t
mb0_id
;
canid_t
mb0_id
;
};
static
const
struct
at91_devtype_data
at91_devtype_data
[]
__devinitconst
=
{
[
AT91_DEVTYPE_SAM9263
]
=
{
.
rx_first
=
1
,
.
rx_split
=
8
,
.
rx_last
=
11
,
.
tx_shift
=
2
,
},
[
AT91_DEVTYPE_SAM9X5
]
=
{
.
rx_first
=
0
,
.
rx_split
=
4
,
.
rx_last
=
5
,
.
tx_shift
=
1
,
},
};
static
struct
can_bittiming_const
at91_bittiming_const
=
{
...
...
@@ -186,19 +184,111 @@ static struct can_bittiming_const at91_bittiming_const = {
.
brp_inc
=
1
,
};
static
inline
int
get_tx_next_mb
(
const
struct
at91_priv
*
priv
)
#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
(
9
X5
);
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
(
priv
->
tx_next
&
AT91_NEXT_MB_MASK
)
+
AT91_MB_TX_FIRST
;
return
AT91_MB_MASK
(
get_mb_rx_last
(
priv
)
+
1
)
&
~
AT91_MB_MASK
(
get_mb_rx_first
(
priv
));
}
static
inline
int
get_tx_next_prio
(
const
struct
at91_priv
*
priv
)
static
inline
unsigned
int
get_irq_mb_tx
(
const
struct
at91_priv
*
priv
)
{
return
(
priv
->
tx_next
>>
AT91_NEXT_PRIO_SHIFT
)
&
0xf
;
return
AT91_MB_MASK
(
get_mb_tx_last
(
priv
)
+
1
)
&
~
AT91_MB_MASK
(
get_mb_tx_first
(
priv
));
}
static
inline
int
get_tx_echo
_mb
(
const
struct
at91_priv
*
priv
)
static
inline
unsigned
int
get_tx_next
_mb
(
const
struct
at91_priv
*
priv
)
{
return
(
priv
->
tx_echo
&
AT91_NEXT_MB_MASK
)
+
AT91_MB_TX_FIRST
;
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
)
...
...
@@ -259,29 +349,29 @@ static void at91_setup_mailboxes(struct net_device *dev)
* overflow.
*/
reg_mid
=
at91_can_id_to_reg_mid
(
priv
->
mb0_id
);
for
(
i
=
0
;
i
<
AT91_MB_RX_FIRST
;
i
++
)
{
for
(
i
=
0
;
i
<
get_mb_rx_first
(
priv
)
;
i
++
)
{
set_mb_mode
(
priv
,
i
,
AT91_MB_MODE_DISABLED
);
at91_write
(
priv
,
AT91_MID
(
i
),
reg_mid
);
at91_write
(
priv
,
AT91_MCR
(
i
),
0x0
);
/* clear dlc */
}
for
(
i
=
AT91_MB_RX_FIRST
;
i
<
AT91_MB_RX_LAST
;
i
++
)
for
(
i
=
get_mb_rx_first
(
priv
);
i
<
get_mb_rx_last
(
priv
)
;
i
++
)
set_mb_mode
(
priv
,
i
,
AT91_MB_MODE_RX
);
set_mb_mode
(
priv
,
AT91_MB_RX_LAST
,
AT91_MB_MODE_RX_OVRWR
);
set_mb_mode
(
priv
,
get_mb_rx_last
(
priv
)
,
AT91_MB_MODE_RX_OVRWR
);
/* reset acceptance mask and id register */
for
(
i
=
AT91_MB_RX_FIRST
;
i
<=
AT91_MB_RX_LAST
;
i
++
)
{
at91_write
(
priv
,
AT91_MAM
(
i
),
0x0
);
for
(
i
=
get_mb_rx_first
(
priv
);
i
<=
get_mb_rx_last
(
priv
)
;
i
++
)
{
at91_write
(
priv
,
AT91_MAM
(
i
),
0x0
);
at91_write
(
priv
,
AT91_MID
(
i
),
AT91_MID_MIDE
);
}
/* The last 4 mailboxes are used for transmitting. */
for
(
i
=
AT91_MB_TX_FIRST
;
i
<=
AT91_MB_TX_LAST
;
i
++
)
for
(
i
=
get_mb_tx_first
(
priv
);
i
<=
get_mb_tx_last
(
priv
)
;
i
++
)
set_mb_mode_prio
(
priv
,
i
,
AT91_MB_MODE_TX
,
0
);
/* Reset tx and rx helper pointers */
priv
->
tx_next
=
priv
->
tx_echo
=
0
;
priv
->
rx_next
=
AT91_MB_RX_FIRST
;
priv
->
rx_next
=
get_mb_rx_first
(
priv
)
;
}
static
int
at91_set_bittiming
(
struct
net_device
*
dev
)
...
...
@@ -336,7 +426,7 @@ static void at91_chip_start(struct net_device *dev)
priv
->
can
.
state
=
CAN_STATE_ERROR_ACTIVE
;
/* Enable interrupts */
reg_ier
=
AT91_IRQ_MB_RX
|
AT91_IRQ_ERRP
|
AT91_IRQ_ERR_FRAME
;
reg_ier
=
get_irq_mb_rx
(
priv
)
|
AT91_IRQ_ERRP
|
AT91_IRQ_ERR_FRAME
;
at91_write
(
priv
,
AT91_IDR
,
AT91_IRQ_ALL
);
at91_write
(
priv
,
AT91_IER
,
reg_ier
);
}
...
...
@@ -375,8 +465,8 @@ static void at91_chip_stop(struct net_device *dev, enum can_state state)
* mailbox, but without the offset AT91_MB_TX_FIRST. The lower bits
* encode the mailbox number, the upper 4 bits the mailbox priority:
*
* priv->tx_next = (prio <<
AT91_NEXT_PRIO_SHIFT) |
|
* (mb -
AT91_MB_TX_FIRST
);
* priv->tx_next = (prio <<
get_next_prio_shift(priv))
|
* (mb -
get_mb_tx_first(priv)
);
*
*/
static
netdev_tx_t
at91_start_xmit
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
)
...
...
@@ -417,7 +507,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
stats
->
tx_bytes
+=
cf
->
can_dlc
;
/* _NOTE_: subtract AT91_MB_TX_FIRST offset from mb! */
can_put_echo_skb
(
skb
,
dev
,
mb
-
AT91_MB_TX_FIRST
);
can_put_echo_skb
(
skb
,
dev
,
mb
-
get_mb_tx_first
(
priv
)
);
/*
* we have to stop the queue and deliver all messages in case
...
...
@@ -430,7 +520,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
priv
->
tx_next
++
;
if
(
!
(
at91_read
(
priv
,
AT91_MSR
(
get_tx_next_mb
(
priv
)))
&
AT91_MSR_MRDY
)
||
(
priv
->
tx_next
&
AT91_NEXT_MASK
)
==
0
)
(
priv
->
tx_next
&
get_next_mask
(
priv
)
)
==
0
)
netif_stop_queue
(
dev
);
/* Enable interrupt for this mailbox */
...
...
@@ -447,7 +537,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
*/
static
inline
void
at91_activate_rx_low
(
const
struct
at91_priv
*
priv
)
{
u32
mask
=
AT91_MB_RX_LOW_MASK
;
u32
mask
=
get_mb_rx_low_mask
(
priv
)
;
at91_write
(
priv
,
AT91_TCR
,
mask
);
}
...
...
@@ -513,17 +603,19 @@ static void at91_read_mb(struct net_device *dev, unsigned int mb,
cf
->
can_id
=
(
reg_mid
>>
18
)
&
CAN_SFF_MASK
;
reg_msr
=
at91_read
(
priv
,
AT91_MSR
(
mb
));
if
(
reg_msr
&
AT91_MSR_MRTR
)
cf
->
can_id
|=
CAN_RTR_FLAG
;
cf
->
can_dlc
=
get_can_dlc
((
reg_msr
>>
16
)
&
0xf
);
*
(
u32
*
)(
cf
->
data
+
0
)
=
at91_read
(
priv
,
AT91_MDL
(
mb
));
*
(
u32
*
)(
cf
->
data
+
4
)
=
at91_read
(
priv
,
AT91_MDH
(
mb
));
if
(
reg_msr
&
AT91_MSR_MRTR
)
cf
->
can_id
|=
CAN_RTR_FLAG
;
else
{
*
(
u32
*
)(
cf
->
data
+
0
)
=
at91_read
(
priv
,
AT91_MDL
(
mb
));
*
(
u32
*
)(
cf
->
data
+
4
)
=
at91_read
(
priv
,
AT91_MDH
(
mb
));
}
/* allow RX of extended frames */
at91_write
(
priv
,
AT91_MID
(
mb
),
AT91_MID_MIDE
);
if
(
unlikely
(
mb
==
AT91_MB_RX_LAST
&&
reg_msr
&
AT91_MSR_MMI
))
if
(
unlikely
(
mb
==
get_mb_rx_last
(
priv
)
&&
reg_msr
&
AT91_MSR_MMI
))
at91_rx_overflow_err
(
dev
);
}
...
...
@@ -561,8 +653,9 @@ static void at91_read_msg(struct net_device *dev, unsigned int mb)
*
* Theory of Operation:
*
* 11 of the 16 mailboxes on the chip are reserved for RX. we split
* them into 2 groups. The lower group holds 7 and upper 4 mailboxes.
* About 3/4 of the mailboxes (get_mb_rx_first()...get_mb_rx_last())
* on the chip are reserved for RX. We split them into 2 groups. The
* lower group ranges from get_mb_rx_first() to get_mb_rx_low_last().
*
* Like it or not, but the chip always saves a received CAN message
* into the first free mailbox it finds (starting with the
...
...
@@ -610,23 +703,23 @@ static int at91_poll_rx(struct net_device *dev, int quota)
unsigned
int
mb
;
int
received
=
0
;
if
(
priv
->
rx_next
>
AT91_MB_RX_LOW_LAST
&&
reg_sr
&
AT91_MB_RX_LOW_MASK
)
if
(
priv
->
rx_next
>
get_mb_rx_low_last
(
priv
)
&&
reg_sr
&
get_mb_rx_low_mask
(
priv
)
)
netdev_info
(
dev
,
"order of incoming frames cannot be guaranteed
\n
"
);
again:
for
(
mb
=
find_next_bit
(
addr
,
AT91_MB_RX_LAST
+
1
,
priv
->
rx_next
);
mb
<
AT91_MB_RX_LAST
+
1
&&
quota
>
0
;
for
(
mb
=
find_next_bit
(
addr
,
get_mb_tx_first
(
priv
)
,
priv
->
rx_next
);
mb
<
get_mb_tx_first
(
priv
)
&&
quota
>
0
;
reg_sr
=
at91_read
(
priv
,
AT91_SR
),
mb
=
find_next_bit
(
addr
,
AT91_MB_RX_LAST
+
1
,
++
priv
->
rx_next
))
{
mb
=
find_next_bit
(
addr
,
get_mb_tx_first
(
priv
)
,
++
priv
->
rx_next
))
{
at91_read_msg
(
dev
,
mb
);
/* reactivate mailboxes */
if
(
mb
==
AT91_MB_RX_LOW_LAST
)
if
(
mb
==
get_mb_rx_low_last
(
priv
)
)
/* all lower mailboxed, if just finished it */
at91_activate_rx_low
(
priv
);
else
if
(
mb
>
AT91_MB_RX_LOW_LAST
)
else
if
(
mb
>
get_mb_rx_low_last
(
priv
)
)
/* only the mailbox we read */
at91_activate_rx_mb
(
priv
,
mb
);
...
...
@@ -635,9 +728,9 @@ static int at91_poll_rx(struct net_device *dev, int quota)
}
/* upper group completed, look again in lower */
if
(
priv
->
rx_next
>
AT91_MB_RX_LOW_LAST
&&
quota
>
0
&&
mb
>
AT91_MB_RX_LAST
)
{
priv
->
rx_next
=
AT91_MB_RX_FIRST
;
if
(
priv
->
rx_next
>
get_mb_rx_low_last
(
priv
)
&&
quota
>
0
&&
mb
>
get_mb_rx_last
(
priv
)
)
{
priv
->
rx_next
=
get_mb_rx_first
(
priv
)
;
goto
again
;
}
...
...
@@ -720,7 +813,7 @@ static int at91_poll(struct napi_struct *napi, int quota)
u32
reg_sr
=
at91_read
(
priv
,
AT91_SR
);
int
work_done
=
0
;
if
(
reg_sr
&
AT91_IRQ_MB_RX
)
if
(
reg_sr
&
get_irq_mb_rx
(
priv
)
)
work_done
+=
at91_poll_rx
(
dev
,
quota
-
work_done
);
/*
...
...
@@ -734,7 +827,7 @@ static int at91_poll(struct napi_struct *napi, int quota)
if
(
work_done
<
quota
)
{
/* enable IRQs for frame errors and all mailboxes >= rx_next */
u32
reg_ier
=
AT91_IRQ_ERR_FRAME
;
reg_ier
|=
AT91_IRQ_MB_RX
&
~
AT91_MB_RX
_MASK
(
priv
->
rx_next
);
reg_ier
|=
get_irq_mb_rx
(
priv
)
&
~
AT91_MB
_MASK
(
priv
->
rx_next
);
napi_complete
(
napi
);
at91_write
(
priv
,
AT91_IER
,
reg_ier
);
...
...
@@ -783,7 +876,7 @@ static void at91_irq_tx(struct net_device *dev, u32 reg_sr)
if
(
likely
(
reg_msr
&
AT91_MSR_MRDY
&&
~
reg_msr
&
AT91_MSR_MABT
))
{
/* _NOTE_: subtract AT91_MB_TX_FIRST offset from mb! */
can_get_echo_skb
(
dev
,
mb
-
AT91_MB_TX_FIRST
);
can_get_echo_skb
(
dev
,
mb
-
get_mb_tx_first
(
priv
)
);
dev
->
stats
.
tx_packets
++
;
}
}
...
...
@@ -793,8 +886,8 @@ static void at91_irq_tx(struct net_device *dev, u32 reg_sr)
* we get a TX int for the last can frame directly before a
* wrap around.
*/
if
((
priv
->
tx_next
&
AT91_NEXT_MASK
)
!=
0
||
(
priv
->
tx_echo
&
AT91_NEXT_MASK
)
==
0
)
if
((
priv
->
tx_next
&
get_next_mask
(
priv
)
)
!=
0
||
(
priv
->
tx_echo
&
get_next_mask
(
priv
)
)
==
0
)
netif_wake_queue
(
dev
);
}
...
...
@@ -906,6 +999,29 @@ static void at91_irq_err_state(struct net_device *dev,
at91_write
(
priv
,
AT91_IER
,
reg_ier
);
}
static
int
at91_get_state_by_bec
(
const
struct
net_device
*
dev
,
enum
can_state
*
state
)
{
struct
can_berr_counter
bec
;
int
err
;
err
=
at91_get_berr_counter
(
dev
,
&
bec
);
if
(
err
)
return
err
;
if
(
bec
.
txerr
<
96
&&
bec
.
rxerr
<
96
)
*
state
=
CAN_STATE_ERROR_ACTIVE
;
else
if
(
bec
.
txerr
<
128
&&
bec
.
rxerr
<
128
)
*
state
=
CAN_STATE_ERROR_WARNING
;
else
if
(
bec
.
txerr
<
256
&&
bec
.
rxerr
<
256
)
*
state
=
CAN_STATE_ERROR_PASSIVE
;
else
*
state
=
CAN_STATE_BUS_OFF
;
return
0
;
}
static
void
at91_irq_err
(
struct
net_device
*
dev
)
{
struct
at91_priv
*
priv
=
netdev_priv
(
dev
);
...
...
@@ -913,21 +1029,28 @@ static void at91_irq_err(struct net_device *dev)
struct
can_frame
*
cf
;
enum
can_state
new_state
;
u32
reg_sr
;
int
err
;
reg_sr
=
at91_read
(
priv
,
AT91_SR
);
/* we need to look at the unmasked reg_sr */
if
(
unlikely
(
reg_sr
&
AT91_IRQ_BOFF
))
new_state
=
CAN_STATE_BUS_OFF
;
else
if
(
unlikely
(
reg_sr
&
AT91_IRQ_ERRP
))
new_state
=
CAN_STATE_ERROR_PASSIVE
;
else
if
(
unlikely
(
reg_sr
&
AT91_IRQ_WARN
))
new_state
=
CAN_STATE_ERROR_WARNING
;
else
if
(
likely
(
reg_sr
&
AT91_IRQ_ERRA
))
new_state
=
CAN_STATE_ERROR_ACTIVE
;
else
{
netdev_err
(
dev
,
"BUG! hardware in undefined state
\n
"
);
return
;
if
(
at91_is_sam9263
(
priv
))
{
reg_sr
=
at91_read
(
priv
,
AT91_SR
);
/* we need to look at the unmasked reg_sr */
if
(
unlikely
(
reg_sr
&
AT91_IRQ_BOFF
))
new_state
=
CAN_STATE_BUS_OFF
;
else
if
(
unlikely
(
reg_sr
&
AT91_IRQ_ERRP
))
new_state
=
CAN_STATE_ERROR_PASSIVE
;
else
if
(
unlikely
(
reg_sr
&
AT91_IRQ_WARN
))
new_state
=
CAN_STATE_ERROR_WARNING
;
else
if
(
likely
(
reg_sr
&
AT91_IRQ_ERRA
))
new_state
=
CAN_STATE_ERROR_ACTIVE
;
else
{
netdev_err
(
dev
,
"BUG! hardware in undefined state
\n
"
);
return
;
}
}
else
{
err
=
at91_get_state_by_bec
(
dev
,
&
new_state
);
if
(
err
)
return
;
}
/* state hasn't changed */
...
...
@@ -968,19 +1091,19 @@ static irqreturn_t at91_irq(int irq, void *dev_id)
handled
=
IRQ_HANDLED
;
/* Receive or error interrupt? -> napi */
if
(
reg_sr
&
(
AT91_IRQ_MB_RX
|
AT91_IRQ_ERR_FRAME
))
{
if
(
reg_sr
&
(
get_irq_mb_rx
(
priv
)
|
AT91_IRQ_ERR_FRAME
))
{
/*
* The error bits are clear on read,
* save for later use.
*/
priv
->
reg_sr
=
reg_sr
;
at91_write
(
priv
,
AT91_IDR
,
AT91_IRQ_MB_RX
|
AT91_IRQ_ERR_FRAME
);
get_irq_mb_rx
(
priv
)
|
AT91_IRQ_ERR_FRAME
);
napi_schedule
(
&
priv
->
napi
);
}
/* Transmission complete interrupt */
if
(
reg_sr
&
AT91_IRQ_MB_TX
)
if
(
reg_sr
&
get_irq_mb_tx
(
priv
)
)
at91_irq_tx
(
dev
,
reg_sr
);
at91_irq_err
(
dev
);
...
...
@@ -1123,6 +1246,8 @@ static struct attribute_group at91_sysfs_attr_group = {
static
int
__devinit
at91_can_probe
(
struct
platform_device
*
pdev
)
{
const
struct
at91_devtype_data
*
devtype_data
;
enum
at91_devtype
devtype
;
struct
net_device
*
dev
;
struct
at91_priv
*
priv
;
struct
resource
*
res
;
...
...
@@ -1130,6 +1255,9 @@ static int __devinit at91_can_probe(struct platform_device *pdev)
void
__iomem
*
addr
;
int
err
,
irq
;
devtype
=
pdev
->
id_entry
->
driver_data
;
devtype_data
=
&
at91_devtype_data
[
devtype
];
clk
=
clk_get
(
&
pdev
->
dev
,
"can_clk"
);
if
(
IS_ERR
(
clk
))
{
dev_err
(
&
pdev
->
dev
,
"no clock defined
\n
"
);
...
...
@@ -1157,7 +1285,8 @@ static int __devinit at91_can_probe(struct platform_device *pdev)
goto
exit_release
;
}
dev
=
alloc_candev
(
sizeof
(
struct
at91_priv
),
AT91_MB_TX_NUM
);
dev
=
alloc_candev
(
sizeof
(
struct
at91_priv
),
1
<<
devtype_data
->
tx_shift
);
if
(
!
dev
)
{
err
=
-
ENOMEM
;
goto
exit_iounmap
;
...
...
@@ -1166,7 +1295,6 @@ static int __devinit at91_can_probe(struct platform_device *pdev)
dev
->
netdev_ops
=
&
at91_netdev_ops
;
dev
->
irq
=
irq
;
dev
->
flags
|=
IFF_ECHO
;
dev
->
sysfs_groups
[
0
]
=
&
at91_sysfs_attr_group
;
priv
=
netdev_priv
(
dev
);
priv
->
can
.
clock
.
freq
=
clk_get_rate
(
clk
);
...
...
@@ -1174,13 +1302,18 @@ static int __devinit at91_can_probe(struct platform_device *pdev)
priv
->
can
.
do_set_mode
=
at91_set_mode
;
priv
->
can
.
do_get_berr_counter
=
at91_get_berr_counter
;
priv
->
can
.
ctrlmode_supported
=
CAN_CTRLMODE_3_SAMPLES
;
priv
->
reg_base
=
addr
;
priv
->
dev
=
dev
;
priv
->
reg_base
=
addr
;
priv
->
devtype_data
=
*
devtype_data
;
priv
->
devtype_data
.
type
=
devtype
;
priv
->
clk
=
clk
;
priv
->
pdata
=
pdev
->
dev
.
platform_data
;
priv
->
mb0_id
=
0x7ff
;
netif_napi_add
(
dev
,
&
priv
->
napi
,
at91_poll
,
AT91_NAPI_WEIGHT
);
netif_napi_add
(
dev
,
&
priv
->
napi
,
at91_poll
,
get_mb_rx_num
(
priv
));
if
(
at91_is_sam9263
(
priv
))
dev
->
sysfs_groups
[
0
]
=
&
at91_sysfs_attr_group
;
dev_set_drvdata
(
&
pdev
->
dev
,
dev
);
SET_NETDEV_DEV
(
dev
,
&
pdev
->
dev
);
...
...
@@ -1230,13 +1363,26 @@ static int __devexit at91_can_remove(struct platform_device *pdev)
return
0
;
}
static
const
struct
platform_device_id
at91_can_id_table
[]
=
{
{
.
name
=
"at91_can"
,
.
driver_data
=
AT91_DEVTYPE_SAM9263
,
},
{
.
name
=
"at91sam9x5_can"
,
.
driver_data
=
AT91_DEVTYPE_SAM9X5
,
},
{
/* sentinel */
}
};
static
struct
platform_driver
at91_can_driver
=
{
.
probe
=
at91_can_probe
,
.
remove
=
__devexit_p
(
at91_can_remove
),
.
driver
=
{
.
name
=
KBUILD_MODNAME
,
.
owner
=
THIS_MODULE
,
.
probe
=
at91_can_probe
,
.
remove
=
__devexit_p
(
at91_can_remove
),
.
driver
=
{
.
name
=
KBUILD_MODNAME
,
.
owner
=
THIS_MODULE
,
},
.
id_table
=
at91_can_id_table
,
};
static
int
__init
at91_can_module_init
(
void
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录