Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
a47d6056
Commit
a47d6056
authored
Oct 18, 2010
by
David S. Miller
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'can/mcp251x-for-net-next' of
git://git.pengutronix.de/git/mkl/linux-2.6
parents
d8e62719
9c473fc3
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
70 additions
and
29 deletions
+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
No files found.
drivers/net/can/mcp251x.c
View file @
a47d6056
...
@@ -38,14 +38,14 @@
...
@@ -38,14 +38,14 @@
* static struct mcp251x_platform_data mcp251x_info = {
* static struct mcp251x_platform_data mcp251x_info = {
* .oscillator_frequency = 8000000,
* .oscillator_frequency = 8000000,
* .board_specific_setup = &mcp251x_setup,
* .board_specific_setup = &mcp251x_setup,
* .model = CAN_MCP251X_MCP2510,
* .power_enable = mcp251x_power_enable,
* .power_enable = mcp251x_power_enable,
* .transceiver_enable = NULL,
* .transceiver_enable = NULL,
* };
* };
*
*
* static struct spi_board_info spi_board_info[] = {
* static struct spi_board_info spi_board_info[] = {
* {
* {
* .modalias = "mcp251x",
* .modalias = "mcp2510",
* // or "mcp2515" depending on your controller
* .platform_data = &mcp251x_info,
* .platform_data = &mcp251x_info,
* .irq = IRQ_EINT13,
* .irq = IRQ_EINT13,
* .max_speed_hz = 2*1000*1000,
* .max_speed_hz = 2*1000*1000,
...
@@ -125,6 +125,8 @@
...
@@ -125,6 +125,8 @@
# define CANINTF_TX0IF 0x04
# define CANINTF_TX0IF 0x04
# define CANINTF_RX1IF 0x02
# define CANINTF_RX1IF 0x02
# define CANINTF_RX0IF 0x01
# define CANINTF_RX0IF 0x01
# define CANINTF_ERR_TX \
(CANINTF_ERRIF | CANINTF_TX2IF | CANINTF_TX1IF | CANINTF_TX0IF)
#define EFLG 0x2d
#define EFLG 0x2d
# define EFLG_EWARN 0x01
# define EFLG_EWARN 0x01
# define EFLG_RXWAR 0x02
# define EFLG_RXWAR 0x02
...
@@ -222,10 +224,16 @@ static struct can_bittiming_const mcp251x_bittiming_const = {
...
@@ -222,10 +224,16 @@ static struct can_bittiming_const mcp251x_bittiming_const = {
.
brp_inc
=
1
,
.
brp_inc
=
1
,
};
};
enum
mcp251x_model
{
CAN_MCP251X_MCP2510
=
0x2510
,
CAN_MCP251X_MCP2515
=
0x2515
,
};
struct
mcp251x_priv
{
struct
mcp251x_priv
{
struct
can_priv
can
;
struct
can_priv
can
;
struct
net_device
*
net
;
struct
net_device
*
net
;
struct
spi_device
*
spi
;
struct
spi_device
*
spi
;
enum
mcp251x_model
model
;
struct
mutex
mcp_lock
;
/* SPI device lock */
struct
mutex
mcp_lock
;
/* SPI device lock */
...
@@ -250,6 +258,16 @@ struct mcp251x_priv {
...
@@ -250,6 +258,16 @@ struct mcp251x_priv {
int
restart_tx
;
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
)
static
void
mcp251x_clean
(
struct
net_device
*
net
)
{
{
struct
mcp251x_priv
*
priv
=
netdev_priv
(
net
);
struct
mcp251x_priv
*
priv
=
netdev_priv
(
net
);
...
@@ -319,6 +337,20 @@ static u8 mcp251x_read_reg(struct spi_device *spi, uint8_t reg)
...
@@ -319,6 +337,20 @@ static u8 mcp251x_read_reg(struct spi_device *spi, uint8_t reg)
return
val
;
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
)
static
void
mcp251x_write_reg
(
struct
spi_device
*
spi
,
u8
reg
,
uint8_t
val
)
{
{
struct
mcp251x_priv
*
priv
=
dev_get_drvdata
(
&
spi
->
dev
);
struct
mcp251x_priv
*
priv
=
dev_get_drvdata
(
&
spi
->
dev
);
...
@@ -346,10 +378,9 @@ static void mcp251x_write_bits(struct spi_device *spi, u8 reg,
...
@@ -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
,
static
void
mcp251x_hw_tx_frame
(
struct
spi_device
*
spi
,
u8
*
buf
,
int
len
,
int
tx_buf_idx
)
int
len
,
int
tx_buf_idx
)
{
{
struct
mcp251x_platform_data
*
pdata
=
spi
->
dev
.
platform_data
;
struct
mcp251x_priv
*
priv
=
dev_get_drvdata
(
&
spi
->
dev
);
struct
mcp251x_priv
*
priv
=
dev_get_drvdata
(
&
spi
->
dev
);
if
(
pdata
->
model
==
CAN_MCP251X_MCP2510
)
{
if
(
mcp251x_is_2510
(
spi
)
)
{
int
i
;
int
i
;
for
(
i
=
1
;
i
<
TXBDAT_OFF
+
len
;
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,
...
@@ -392,9 +423,8 @@ static void mcp251x_hw_rx_frame(struct spi_device *spi, u8 *buf,
int
buf_idx
)
int
buf_idx
)
{
{
struct
mcp251x_priv
*
priv
=
dev_get_drvdata
(
&
spi
->
dev
);
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
;
int
i
,
len
;
for
(
i
=
1
;
i
<
RXBDAT_OFF
;
i
++
)
for
(
i
=
1
;
i
<
RXBDAT_OFF
;
i
++
)
...
@@ -451,7 +481,7 @@ static void mcp251x_hw_rx(struct spi_device *spi, int buf_idx)
...
@@ -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_packets
++
;
priv
->
net
->
stats
.
rx_bytes
+=
frame
->
can_dlc
;
priv
->
net
->
stats
.
rx_bytes
+=
frame
->
can_dlc
;
netif_rx
(
skb
);
netif_rx
_ni
(
skb
);
}
}
static
void
mcp251x_hw_sleep
(
struct
spi_device
*
spi
)
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)
...
@@ -676,7 +706,7 @@ static void mcp251x_error_skb(struct net_device *net, int can_id, int data1)
if
(
skb
)
{
if
(
skb
)
{
frame
->
can_id
=
can_id
;
frame
->
can_id
=
can_id
;
frame
->
data
[
1
]
=
data1
;
frame
->
data
[
1
]
=
data1
;
netif_rx
(
skb
);
netif_rx
_ni
(
skb
);
}
else
{
}
else
{
dev_err
(
&
net
->
dev
,
dev_err
(
&
net
->
dev
,
"cannot allocate error skb
\n
"
);
"cannot allocate error skb
\n
"
);
...
@@ -754,24 +784,39 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
...
@@ -754,24 +784,39 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
mutex_lock
(
&
priv
->
mcp_lock
);
mutex_lock
(
&
priv
->
mcp_lock
);
while
(
!
priv
->
force_quit
)
{
while
(
!
priv
->
force_quit
)
{
enum
can_state
new_state
;
enum
can_state
new_state
;
u8
intf
=
mcp251x_read_reg
(
spi
,
CANINTF
)
;
u8
intf
,
eflag
;
u8
eflag
;
u8
clear_intf
=
0
;
int
can_id
=
0
,
data1
=
0
;
int
can_id
=
0
,
data1
=
0
;
mcp251x_read_2regs
(
spi
,
CANINTF
,
&
intf
,
&
eflag
);
/* receive buffer 0 */
if
(
intf
&
CANINTF_RX0IF
)
{
if
(
intf
&
CANINTF_RX0IF
)
{
mcp251x_hw_rx
(
spi
,
0
);
mcp251x_hw_rx
(
spi
,
0
);
/* Free one buffer ASAP */
/*
mcp251x_write_bits
(
spi
,
CANINTF
,
intf
&
CANINTF_RX0IF
,
* Free one buffer ASAP
0x00
);
* (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
);
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
);
if
(
eflag
)
mcp251x_write_reg
(
spi
,
EFLG
,
0x00
);
mcp251x_write_bits
(
spi
,
EFLG
,
eflag
,
0x00
);
/* Update can state */
/* Update can state */
if
(
eflag
&
EFLG_TXBO
)
{
if
(
eflag
&
EFLG_TXBO
)
{
...
@@ -816,10 +861,14 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
...
@@ -816,10 +861,14 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
if
(
intf
&
CANINTF_ERRIF
)
{
if
(
intf
&
CANINTF_ERRIF
)
{
/* Handle overflow counters */
/* Handle overflow counters */
if
(
eflag
&
(
EFLG_RX0OVR
|
EFLG_RX1OVR
))
{
if
(
eflag
&
(
EFLG_RX0OVR
|
EFLG_RX1OVR
))
{
if
(
eflag
&
EFLG_RX0OVR
)
if
(
eflag
&
EFLG_RX0OVR
)
{
net
->
stats
.
rx_over_errors
++
;
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_over_errors
++
;
net
->
stats
.
rx_errors
++
;
}
can_id
|=
CAN_ERR_CRTL
;
can_id
|=
CAN_ERR_CRTL
;
data1
|=
CAN_ERR_CRTL_RX_OVERFLOW
;
data1
|=
CAN_ERR_CRTL_RX_OVERFLOW
;
}
}
...
@@ -921,16 +970,12 @@ static int __devinit mcp251x_can_probe(struct spi_device *spi)
...
@@ -921,16 +970,12 @@ static int __devinit mcp251x_can_probe(struct spi_device *spi)
struct
net_device
*
net
;
struct
net_device
*
net
;
struct
mcp251x_priv
*
priv
;
struct
mcp251x_priv
*
priv
;
struct
mcp251x_platform_data
*
pdata
=
spi
->
dev
.
platform_data
;
struct
mcp251x_platform_data
*
pdata
=
spi
->
dev
.
platform_data
;
int
model
=
spi_get_device_id
(
spi
)
->
driver_data
;
int
ret
=
-
ENODEV
;
int
ret
=
-
ENODEV
;
if
(
!
pdata
)
if
(
!
pdata
)
/* Platform data is required for osc freq */
/* Platform data is required for osc freq */
goto
error_out
;
goto
error_out
;
if
(
model
)
pdata
->
model
=
model
;
/* Allocate can/net device */
/* Allocate can/net device */
net
=
alloc_candev
(
sizeof
(
struct
mcp251x_priv
),
TX_ECHO_SKB_MAX
);
net
=
alloc_candev
(
sizeof
(
struct
mcp251x_priv
),
TX_ECHO_SKB_MAX
);
if
(
!
net
)
{
if
(
!
net
)
{
...
@@ -947,6 +992,7 @@ static int __devinit mcp251x_can_probe(struct spi_device *spi)
...
@@ -947,6 +992,7 @@ static int __devinit mcp251x_can_probe(struct spi_device *spi)
priv
->
can
.
clock
.
freq
=
pdata
->
oscillator_frequency
/
2
;
priv
->
can
.
clock
.
freq
=
pdata
->
oscillator_frequency
/
2
;
priv
->
can
.
ctrlmode_supported
=
CAN_CTRLMODE_3_SAMPLES
|
priv
->
can
.
ctrlmode_supported
=
CAN_CTRLMODE_3_SAMPLES
|
CAN_CTRLMODE_LOOPBACK
|
CAN_CTRLMODE_LISTENONLY
;
CAN_CTRLMODE_LOOPBACK
|
CAN_CTRLMODE_LISTENONLY
;
priv
->
model
=
spi_get_device_id
(
spi
)
->
driver_data
;
priv
->
net
=
net
;
priv
->
net
=
net
;
dev_set_drvdata
(
&
spi
->
dev
,
priv
);
dev_set_drvdata
(
&
spi
->
dev
,
priv
);
...
@@ -1120,8 +1166,7 @@ static int mcp251x_can_resume(struct spi_device *spi)
...
@@ -1120,8 +1166,7 @@ static int mcp251x_can_resume(struct spi_device *spi)
#define mcp251x_can_resume NULL
#define mcp251x_can_resume NULL
#endif
#endif
static
struct
spi_device_id
mcp251x_id_table
[]
=
{
static
const
struct
spi_device_id
mcp251x_id_table
[]
=
{
{
"mcp251x"
,
0
/* Use pdata.model */
},
{
"mcp2510"
,
CAN_MCP251X_MCP2510
},
{
"mcp2510"
,
CAN_MCP251X_MCP2510
},
{
"mcp2515"
,
CAN_MCP251X_MCP2515
},
{
"mcp2515"
,
CAN_MCP251X_MCP2515
},
{
},
{
},
...
...
include/linux/can/platform/mcp251x.h
View file @
a47d6056
...
@@ -12,7 +12,6 @@
...
@@ -12,7 +12,6 @@
/**
/**
* struct mcp251x_platform_data - MCP251X SPI CAN controller platform data
* struct mcp251x_platform_data - MCP251X SPI CAN controller platform data
* @oscillator_frequency: - oscillator frequency in Hz
* @oscillator_frequency: - oscillator frequency in Hz
* @model: - actual type of chip
* @board_specific_setup: - called before probing the chip (power,reset)
* @board_specific_setup: - called before probing the chip (power,reset)
* @transceiver_enable: - called to power on/off the transceiver
* @transceiver_enable: - called to power on/off the transceiver
* @power_enable: - called to power on/off the mcp *and* the
* @power_enable: - called to power on/off the mcp *and* the
...
@@ -25,9 +24,6 @@
...
@@ -25,9 +24,6 @@
struct
mcp251x_platform_data
{
struct
mcp251x_platform_data
{
unsigned
long
oscillator_frequency
;
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
(
*
board_specific_setup
)(
struct
spi_device
*
spi
);
int
(
*
transceiver_enable
)(
int
enable
);
int
(
*
transceiver_enable
)(
int
enable
);
int
(
*
power_enable
)
(
int
enable
);
int
(
*
power_enable
)
(
int
enable
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment