Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
5955e752
K
Kernel
项目概览
openeuler
/
Kernel
1 年多 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
5955e752
编写于
1月 24, 2011
作者:
D
David S. Miller
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'can/at91_can-for-net-2.6' of
git://git.pengutronix.de/git/mkl/linux-2.6
上级
fd0273c5
3a5655a5
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
137 addition
and
26 deletion
+137
-26
Documentation/ABI/testing/sysfs-platform-at91
Documentation/ABI/testing/sysfs-platform-at91
+25
-0
drivers/net/can/at91_can.c
drivers/net/can/at91_can.c
+112
-26
未找到文件。
Documentation/ABI/testing/sysfs-platform-at91
0 → 100644
浏览文件 @
5955e752
What: /sys/devices/platform/at91_can/net/<iface>/mb0_id
Date: January 2011
KernelVersion: 2.6.38
Contact: Marc Kleine-Budde <kernel@pengutronix.de>
Description:
Value representing the can_id of mailbox 0.
Default: 0x7ff (standard frame)
Due to a chip bug (errata 50.2.6.3 & 50.3.5.3 in
"AT91SAM9263 Preliminary 6249H-ATARM-27-Jul-09") the
contents of mailbox 0 may be send under certain
conditions (even if disabled or in rx mode).
The workaround in the errata suggests not to use the
mailbox and load it with an unused identifier.
In order to use an extended can_id add the
CAN_EFF_FLAG (0x80000000U) to the can_id. Example:
- standard id 0x7ff:
echo 0x7ff > /sys/class/net/can0/mb0_id
- extended id 0x1fffffff:
echo 0x9fffffff > /sys/class/net/can0/mb0_id
drivers/net/can/at91_can.c
浏览文件 @
5955e752
...
...
@@ -2,7 +2,7 @@
* at91_can.c - CAN network driver for AT91 SoC CAN controller
*
* (C) 2007 by Hans J. Koch <hjk@hansjkoch.de>
* (C) 2008, 2009, 2010 by Marc Kleine-Budde <kernel@pengutronix.de>
* (C) 2008, 2009, 2010
, 2011
by Marc Kleine-Budde <kernel@pengutronix.de>
*
* This software may be distributed under the terms of the GNU General
* Public License ("GPL") version 2 as distributed in the 'COPYING'
...
...
@@ -30,6 +30,7 @@
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/platform_device.h>
#include <linux/rtnetlink.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/string.h>
...
...
@@ -40,22 +41,23 @@
#include <mach/board.h>
#define AT91_NAPI_WEIGHT 1
2
#define AT91_NAPI_WEIGHT 1
1
/*
* RX/TX Mailbox split
* don't dare to touch
*/
#define AT91_MB_RX_NUM 1
2
#define AT91_MB_RX_NUM 1
1
#define AT91_MB_TX_SHIFT 2
#define AT91_MB_RX_FIRST
0
#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))
#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)
...
...
@@ -168,6 +170,8 @@ struct at91_priv {
struct
clk
*
clk
;
struct
at91_can_data
*
pdata
;
canid_t
mb0_id
;
};
static
struct
can_bittiming_const
at91_bittiming_const
=
{
...
...
@@ -220,6 +224,18 @@ static inline void set_mb_mode(const struct at91_priv *priv, unsigned int mb,
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
&
CAN_SFF_MASK
)
<<
18
;
return
reg_mid
;
}
/*
* Swtich transceiver on or off
*/
...
...
@@ -233,12 +249,22 @@ static void at91_setup_mailboxes(struct net_device *dev)
{
struct
at91_priv
*
priv
=
netdev_priv
(
dev
);
unsigned
int
i
;
u32
reg_mid
;
/*
* The first 12 mailboxes are used as a reception FIFO. The
* last mailbox is configured with overwrite option. The
* overwrite flag indicates a FIFO overflow.
* Due to a chip bug (errata 50.2.6.3 & 50.3.5.3) the first
* mailbox is disabled. The next 11 mailboxes are used as a
* reception FIFO. The last mailbox is configured with
* overwrite option. The overwrite flag indicates a FIFO
* overflow.
*/
reg_mid
=
at91_can_id_to_reg_mid
(
priv
->
mb0_id
);
for
(
i
=
0
;
i
<
AT91_MB_RX_FIRST
;
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
++
)
set_mb_mode
(
priv
,
i
,
AT91_MB_MODE_RX
);
set_mb_mode
(
priv
,
AT91_MB_RX_LAST
,
AT91_MB_MODE_RX_OVRWR
);
...
...
@@ -254,7 +280,8 @@ static void at91_setup_mailboxes(struct net_device *dev)
set_mb_mode_prio
(
priv
,
i
,
AT91_MB_MODE_TX
,
0
);
/* Reset tx and rx helper pointers */
priv
->
tx_next
=
priv
->
tx_echo
=
priv
->
rx_next
=
0
;
priv
->
tx_next
=
priv
->
tx_echo
=
0
;
priv
->
rx_next
=
AT91_MB_RX_FIRST
;
}
static
int
at91_set_bittiming
(
struct
net_device
*
dev
)
...
...
@@ -372,12 +399,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
netdev_err
(
dev
,
"BUG! TX buffer full when queue awake!
\n
"
);
return
NETDEV_TX_BUSY
;
}
if
(
cf
->
can_id
&
CAN_EFF_FLAG
)
reg_mid
=
(
cf
->
can_id
&
CAN_EFF_MASK
)
|
AT91_MID_MIDE
;
else
reg_mid
=
(
cf
->
can_id
&
CAN_SFF_MASK
)
<<
18
;
reg_mid
=
at91_can_id_to_reg_mid
(
cf
->
can_id
);
reg_mcr
=
((
cf
->
can_id
&
CAN_RTR_FLAG
)
?
AT91_MCR_MRTR
:
0
)
|
(
cf
->
can_dlc
<<
16
)
|
AT91_MCR_MTCR
;
...
...
@@ -539,27 +561,31 @@ static void at91_read_msg(struct net_device *dev, unsigned int mb)
*
* Theory of Operation:
*
* 1
2
of the 16 mailboxes on the chip are reserved for RX. we split
* them into 2 groups. The lower group holds
8
and upper 4 mailboxes.
* 1
1
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.
*
* Like it or not, but the chip always saves a received CAN message
* into the first free mailbox it finds (starting with the
* lowest). This makes it very difficult to read the messages in the
* right order from the chip. This is how we work around that problem:
*
* The first message goes into mb nr.
0
and issues an interrupt. All
* The first message goes into mb nr.
1
and issues an interrupt. All
* rx ints are disabled in the interrupt handler and a napi poll is
* scheduled. We read the mailbox, but do _not_ reenable the mb (to
* receive another message).
*
* lower mbxs upper
*
__
____^______ __^__
*
/
\ / \
*
____^______ __^__
*
/
\ / \
* +-+-+-+-+-+-+-+-++-+-+-+-+
* |
x
|x|x|x|x|x|x|x|| | | | |
* |
|x|x|x|x|x|x|x|| | | | |
* +-+-+-+-+-+-+-+-++-+-+-+-+
* 0 0 0 0 0 0 0 0 0 0 1 1 \ mail
* 0 1 2 3 4 5 6 7 8 9 0 1 / box
* ^
* |
* \
* unused, due to chip bug
*
* The variable priv->rx_next points to the next mailbox to read a
* message from. As long we're in the lower mailboxes we just read the
...
...
@@ -590,10 +616,10 @@ static int at91_poll_rx(struct net_device *dev, int quota)
"order of incoming frames cannot be guaranteed
\n
"
);
again:
for
(
mb
=
find_next_bit
(
addr
,
AT91_MB_RX_
NUM
,
priv
->
rx_next
);
mb
<
AT91_MB_RX_
NUM
&&
quota
>
0
;
for
(
mb
=
find_next_bit
(
addr
,
AT91_MB_RX_
LAST
+
1
,
priv
->
rx_next
);
mb
<
AT91_MB_RX_
LAST
+
1
&&
quota
>
0
;
reg_sr
=
at91_read
(
priv
,
AT91_SR
),
mb
=
find_next_bit
(
addr
,
AT91_MB_RX_
NUM
,
++
priv
->
rx_next
))
{
mb
=
find_next_bit
(
addr
,
AT91_MB_RX_
LAST
+
1
,
++
priv
->
rx_next
))
{
at91_read_msg
(
dev
,
mb
);
/* reactivate mailboxes */
...
...
@@ -610,8 +636,8 @@ 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_NUM
)
{
priv
->
rx_next
=
0
;
quota
>
0
&&
mb
>
AT91_MB_RX_LAST
)
{
priv
->
rx_next
=
AT91_MB_RX_FIRST
;
goto
again
;
}
...
...
@@ -1037,6 +1063,64 @@ static const struct net_device_ops at91_netdev_ops = {
.
ndo_start_xmit
=
at91_start_xmit
,
};
static
ssize_t
at91_sysfs_show_mb0_id
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
at91_priv
*
priv
=
netdev_priv
(
to_net_dev
(
dev
));
if
(
priv
->
mb0_id
&
CAN_EFF_FLAG
)
return
snprintf
(
buf
,
PAGE_SIZE
,
"0x%08x
\n
"
,
priv
->
mb0_id
);
else
return
snprintf
(
buf
,
PAGE_SIZE
,
"0x%03x
\n
"
,
priv
->
mb0_id
);
}
static
ssize_t
at91_sysfs_set_mb0_id
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
struct
net_device
*
ndev
=
to_net_dev
(
dev
);
struct
at91_priv
*
priv
=
netdev_priv
(
ndev
);
unsigned
long
can_id
;
ssize_t
ret
;
int
err
;
rtnl_lock
();
if
(
ndev
->
flags
&
IFF_UP
)
{
ret
=
-
EBUSY
;
goto
out
;
}
err
=
strict_strtoul
(
buf
,
0
,
&
can_id
);
if
(
err
)
{
ret
=
err
;
goto
out
;
}
if
(
can_id
&
CAN_EFF_FLAG
)
can_id
&=
CAN_EFF_MASK
|
CAN_EFF_FLAG
;
else
can_id
&=
CAN_SFF_MASK
;
priv
->
mb0_id
=
can_id
;
ret
=
count
;
out:
rtnl_unlock
();
return
ret
;
}
static
DEVICE_ATTR
(
mb0_id
,
S_IWUGO
|
S_IRUGO
,
at91_sysfs_show_mb0_id
,
at91_sysfs_set_mb0_id
);
static
struct
attribute
*
at91_sysfs_attrs
[]
=
{
&
dev_attr_mb0_id
.
attr
,
NULL
,
};
static
struct
attribute_group
at91_sysfs_attr_group
=
{
.
attrs
=
at91_sysfs_attrs
,
};
static
int
__devinit
at91_can_probe
(
struct
platform_device
*
pdev
)
{
struct
net_device
*
dev
;
...
...
@@ -1082,6 +1166,7 @@ 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
);
...
...
@@ -1093,6 +1178,7 @@ static int __devinit at91_can_probe(struct platform_device *pdev)
priv
->
dev
=
dev
;
priv
->
clk
=
clk
;
priv
->
pdata
=
pdev
->
dev
.
platform_data
;
priv
->
mb0_id
=
0x7ff
;
netif_napi_add
(
dev
,
&
priv
->
napi
,
at91_poll
,
AT91_NAPI_WEIGHT
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录