Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xiphi1978
linux
提交
a47d6056
L
linux
项目概览
xiphi1978
/
linux
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
L
linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
a47d6056
编写于
10月 18, 2010
作者:
D
David S. Miller
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'can/mcp251x-for-net-next' of
git://git.pengutronix.de/git/mkl/linux-2.6
上级
d8e62719
9c473fc3
变更
2
显示空白变更内容
内联
并排
Showing
2 changed file
with
70 addition
and
29 deletion
+70
-29
drivers/net/can/mcp251x.c
drivers/net/can/mcp251x.c
+70
-25
include/linux/can/platform/mcp251x.h
include/linux/can/platform/mcp251x.h
+0
-4
未找到文件。
drivers/net/can/mcp251x.c
浏览文件 @
a47d6056
...
...
@@ -38,14 +38,14 @@
* static struct mcp251x_platform_data mcp251x_info = {
* .oscillator_frequency = 8000000,
* .board_specific_setup = &mcp251x_setup,
* .model = CAN_MCP251X_MCP2510,
* .power_enable = mcp251x_power_enable,
* .transceiver_enable = NULL,
* };
*
* static struct spi_board_info spi_board_info[] = {
* {
* .modalias = "mcp251x",
* .modalias = "mcp2510",
* // or "mcp2515" depending on your controller
* .platform_data = &mcp251x_info,
* .irq = IRQ_EINT13,
* .max_speed_hz = 2*1000*1000,
...
...
@@ -125,6 +125,8 @@
# define CANINTF_TX0IF 0x04
# define CANINTF_RX1IF 0x02
# define CANINTF_RX0IF 0x01
# define CANINTF_ERR_TX \
(CANINTF_ERRIF | CANINTF_TX2IF | CANINTF_TX1IF | CANINTF_TX0IF)
#define EFLG 0x2d
# define EFLG_EWARN 0x01
# define EFLG_RXWAR 0x02
...
...
@@ -222,10 +224,16 @@ static struct can_bittiming_const mcp251x_bittiming_const = {
.
brp_inc
=
1
,
};
enum
mcp251x_model
{
CAN_MCP251X_MCP2510
=
0x2510
,
CAN_MCP251X_MCP2515
=
0x2515
,
};
struct
mcp251x_priv
{
struct
can_priv
can
;
struct
net_device
*
net
;
struct
spi_device
*
spi
;
enum
mcp251x_model
model
;
struct
mutex
mcp_lock
;
/* SPI device lock */
...
...
@@ -250,6 +258,16 @@ struct mcp251x_priv {
int
restart_tx
;
};
#define MCP251X_IS(_model) \
static inline int mcp251x_is_##_model(struct spi_device *spi) \
{ \
struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); \
return priv->model == CAN_MCP251X_MCP##_model; \
}
MCP251X_IS
(
2510
);
MCP251X_IS
(
2515
);
static
void
mcp251x_clean
(
struct
net_device
*
net
)
{
struct
mcp251x_priv
*
priv
=
netdev_priv
(
net
);
...
...
@@ -319,6 +337,20 @@ static u8 mcp251x_read_reg(struct spi_device *spi, uint8_t reg)
return
val
;
}
static
void
mcp251x_read_2regs
(
struct
spi_device
*
spi
,
uint8_t
reg
,
uint8_t
*
v1
,
uint8_t
*
v2
)
{
struct
mcp251x_priv
*
priv
=
dev_get_drvdata
(
&
spi
->
dev
);
priv
->
spi_tx_buf
[
0
]
=
INSTRUCTION_READ
;
priv
->
spi_tx_buf
[
1
]
=
reg
;
mcp251x_spi_trans
(
spi
,
4
);
*
v1
=
priv
->
spi_rx_buf
[
2
];
*
v2
=
priv
->
spi_rx_buf
[
3
];
}
static
void
mcp251x_write_reg
(
struct
spi_device
*
spi
,
u8
reg
,
uint8_t
val
)
{
struct
mcp251x_priv
*
priv
=
dev_get_drvdata
(
&
spi
->
dev
);
...
...
@@ -346,10 +378,9 @@ static void mcp251x_write_bits(struct spi_device *spi, u8 reg,
static
void
mcp251x_hw_tx_frame
(
struct
spi_device
*
spi
,
u8
*
buf
,
int
len
,
int
tx_buf_idx
)
{
struct
mcp251x_platform_data
*
pdata
=
spi
->
dev
.
platform_data
;
struct
mcp251x_priv
*
priv
=
dev_get_drvdata
(
&
spi
->
dev
);
if
(
pdata
->
model
==
CAN_MCP251X_MCP2510
)
{
if
(
mcp251x_is_2510
(
spi
)
)
{
int
i
;
for
(
i
=
1
;
i
<
TXBDAT_OFF
+
len
;
i
++
)
...
...
@@ -392,9 +423,8 @@ static void mcp251x_hw_rx_frame(struct spi_device *spi, u8 *buf,
int
buf_idx
)
{
struct
mcp251x_priv
*
priv
=
dev_get_drvdata
(
&
spi
->
dev
);
struct
mcp251x_platform_data
*
pdata
=
spi
->
dev
.
platform_data
;
if
(
pdata
->
model
==
CAN_MCP251X_MCP2510
)
{
if
(
mcp251x_is_2510
(
spi
)
)
{
int
i
,
len
;
for
(
i
=
1
;
i
<
RXBDAT_OFF
;
i
++
)
...
...
@@ -451,7 +481,7 @@ static void mcp251x_hw_rx(struct spi_device *spi, int buf_idx)
priv
->
net
->
stats
.
rx_packets
++
;
priv
->
net
->
stats
.
rx_bytes
+=
frame
->
can_dlc
;
netif_rx
(
skb
);
netif_rx
_ni
(
skb
);
}
static
void
mcp251x_hw_sleep
(
struct
spi_device
*
spi
)
...
...
@@ -676,7 +706,7 @@ static void mcp251x_error_skb(struct net_device *net, int can_id, int data1)
if
(
skb
)
{
frame
->
can_id
=
can_id
;
frame
->
data
[
1
]
=
data1
;
netif_rx
(
skb
);
netif_rx
_ni
(
skb
);
}
else
{
dev_err
(
&
net
->
dev
,
"cannot allocate error skb
\n
"
);
...
...
@@ -754,24 +784,39 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
mutex_lock
(
&
priv
->
mcp_lock
);
while
(
!
priv
->
force_quit
)
{
enum
can_state
new_state
;
u8
intf
=
mcp251x_read_reg
(
spi
,
CANINTF
)
;
u8
eflag
;
u8
intf
,
eflag
;
u8
clear_intf
=
0
;
int
can_id
=
0
,
data1
=
0
;
mcp251x_read_2regs
(
spi
,
CANINTF
,
&
intf
,
&
eflag
);
/* receive buffer 0 */
if
(
intf
&
CANINTF_RX0IF
)
{
mcp251x_hw_rx
(
spi
,
0
);
/* Free one buffer ASAP */
mcp251x_write_bits
(
spi
,
CANINTF
,
intf
&
CANINTF_RX0IF
,
0x00
);
/*
* Free one buffer ASAP
* (The MCP2515 does this automatically.)
*/
if
(
mcp251x_is_2510
(
spi
))
mcp251x_write_bits
(
spi
,
CANINTF
,
CANINTF_RX0IF
,
0x00
);
}
if
(
intf
&
CANINTF_RX1IF
)
/* receive buffer 1 */
if
(
intf
&
CANINTF_RX1IF
)
{
mcp251x_hw_rx
(
spi
,
1
);
/* the MCP2515 does this automatically */
if
(
mcp251x_is_2510
(
spi
))
clear_intf
|=
CANINTF_RX1IF
;
}
mcp251x_write_bits
(
spi
,
CANINTF
,
intf
,
0x00
);
/* any error or tx interrupt we need to clear? */
if
(
intf
&
CANINTF_ERR_TX
)
clear_intf
|=
intf
&
CANINTF_ERR_TX
;
if
(
clear_intf
)
mcp251x_write_bits
(
spi
,
CANINTF
,
clear_intf
,
0x00
);
eflag
=
mcp251x_read_reg
(
spi
,
EFLG
);
mcp251x_write_reg
(
spi
,
EFLG
,
0x00
);
if
(
eflag
)
mcp251x_write_bits
(
spi
,
EFLG
,
eflag
,
0x00
);
/* Update can state */
if
(
eflag
&
EFLG_TXBO
)
{
...
...
@@ -816,10 +861,14 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
if
(
intf
&
CANINTF_ERRIF
)
{
/* Handle overflow counters */
if
(
eflag
&
(
EFLG_RX0OVR
|
EFLG_RX1OVR
))
{
if
(
eflag
&
EFLG_RX0OVR
)
if
(
eflag
&
EFLG_RX0OVR
)
{
net
->
stats
.
rx_over_errors
++
;
if
(
eflag
&
EFLG_RX1OVR
)
net
->
stats
.
rx_errors
++
;
}
if
(
eflag
&
EFLG_RX1OVR
)
{
net
->
stats
.
rx_over_errors
++
;
net
->
stats
.
rx_errors
++
;
}
can_id
|=
CAN_ERR_CRTL
;
data1
|=
CAN_ERR_CRTL_RX_OVERFLOW
;
}
...
...
@@ -921,16 +970,12 @@ static int __devinit mcp251x_can_probe(struct spi_device *spi)
struct
net_device
*
net
;
struct
mcp251x_priv
*
priv
;
struct
mcp251x_platform_data
*
pdata
=
spi
->
dev
.
platform_data
;
int
model
=
spi_get_device_id
(
spi
)
->
driver_data
;
int
ret
=
-
ENODEV
;
if
(
!
pdata
)
/* Platform data is required for osc freq */
goto
error_out
;
if
(
model
)
pdata
->
model
=
model
;
/* Allocate can/net device */
net
=
alloc_candev
(
sizeof
(
struct
mcp251x_priv
),
TX_ECHO_SKB_MAX
);
if
(
!
net
)
{
...
...
@@ -947,6 +992,7 @@ static int __devinit mcp251x_can_probe(struct spi_device *spi)
priv
->
can
.
clock
.
freq
=
pdata
->
oscillator_frequency
/
2
;
priv
->
can
.
ctrlmode_supported
=
CAN_CTRLMODE_3_SAMPLES
|
CAN_CTRLMODE_LOOPBACK
|
CAN_CTRLMODE_LISTENONLY
;
priv
->
model
=
spi_get_device_id
(
spi
)
->
driver_data
;
priv
->
net
=
net
;
dev_set_drvdata
(
&
spi
->
dev
,
priv
);
...
...
@@ -1120,8 +1166,7 @@ static int mcp251x_can_resume(struct spi_device *spi)
#define mcp251x_can_resume NULL
#endif
static
struct
spi_device_id
mcp251x_id_table
[]
=
{
{
"mcp251x"
,
0
/* Use pdata.model */
},
static
const
struct
spi_device_id
mcp251x_id_table
[]
=
{
{
"mcp2510"
,
CAN_MCP251X_MCP2510
},
{
"mcp2515"
,
CAN_MCP251X_MCP2515
},
{
},
...
...
include/linux/can/platform/mcp251x.h
浏览文件 @
a47d6056
...
...
@@ -12,7 +12,6 @@
/**
* struct mcp251x_platform_data - MCP251X SPI CAN controller platform data
* @oscillator_frequency: - oscillator frequency in Hz
* @model: - actual type of chip
* @board_specific_setup: - called before probing the chip (power,reset)
* @transceiver_enable: - called to power on/off the transceiver
* @power_enable: - called to power on/off the mcp *and* the
...
...
@@ -25,9 +24,6 @@
struct
mcp251x_platform_data
{
unsigned
long
oscillator_frequency
;
int
model
;
#define CAN_MCP251X_MCP2510 0x2510
#define CAN_MCP251X_MCP2515 0x2515
int
(
*
board_specific_setup
)(
struct
spi_device
*
spi
);
int
(
*
transceiver_enable
)(
int
enable
);
int
(
*
power_enable
)
(
int
enable
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录