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
nexedi
linux
Commits
cb2bad86
Commit
cb2bad86
authored
Jun 07, 2011
by
David S. Miller
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'can/at91-sam9x5' of
git://git.pengutronix.de/git/mkl/linux-2.6
parents
a6b7a407
b9e379bc
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
259 additions
and
112 deletions
+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
No files found.
drivers/net/can/Kconfig
View file @
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
View file @
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
)
...
...
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