aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/can/at91_can.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/can/at91_can.c')
-rw-r--r--drivers/net/can/at91_can.c69
1 files changed, 55 insertions, 14 deletions
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
index 2b972812b2d1..121ede663e20 100644
--- a/drivers/net/can/at91_can.c
+++ b/drivers/net/can/at91_can.c
@@ -127,6 +127,7 @@ enum at91_mb_mode {
127 127
128enum at91_devtype { 128enum at91_devtype {
129 AT91_DEVTYPE_SAM9263, 129 AT91_DEVTYPE_SAM9263,
130 AT91_DEVTYPE_SAM9X5,
130}; 131};
131 132
132struct at91_devtype_data { 133struct at91_devtype_data {
@@ -163,6 +164,12 @@ static const struct at91_devtype_data at91_devtype_data[] __devinitconst = {
163 .rx_last = 11, 164 .rx_last = 11,
164 .tx_shift = 2, 165 .tx_shift = 2,
165 }, 166 },
167 [AT91_DEVTYPE_SAM9X5] = {
168 .rx_first = 0,
169 .rx_split = 4,
170 .rx_last = 5,
171 .tx_shift = 1,
172 },
166}; 173};
167 174
168static struct can_bittiming_const at91_bittiming_const = { 175static struct can_bittiming_const at91_bittiming_const = {
@@ -184,6 +191,7 @@ static inline int at91_is_sam##_model(const struct at91_priv *priv) \
184} 191}
185 192
186AT91_IS(9263); 193AT91_IS(9263);
194AT91_IS(9X5);
187 195
188static inline unsigned int get_mb_rx_first(const struct at91_priv *priv) 196static inline unsigned int get_mb_rx_first(const struct at91_priv *priv)
189{ 197{
@@ -991,6 +999,29 @@ static void at91_irq_err_state(struct net_device *dev,
991 at91_write(priv, AT91_IER, reg_ier); 999 at91_write(priv, AT91_IER, reg_ier);
992} 1000}
993 1001
1002static int at91_get_state_by_bec(const struct net_device *dev,
1003 enum can_state *state)
1004{
1005 struct can_berr_counter bec;
1006 int err;
1007
1008 err = at91_get_berr_counter(dev, &bec);
1009 if (err)
1010 return err;
1011
1012 if (bec.txerr < 96 && bec.rxerr < 96)
1013 *state = CAN_STATE_ERROR_ACTIVE;
1014 else if (bec.txerr < 128 && bec.rxerr < 128)
1015 *state = CAN_STATE_ERROR_WARNING;
1016 else if (bec.txerr < 256 && bec.rxerr < 256)
1017 *state = CAN_STATE_ERROR_PASSIVE;
1018 else
1019 *state = CAN_STATE_BUS_OFF;
1020
1021 return 0;
1022}
1023
1024
994static void at91_irq_err(struct net_device *dev) 1025static void at91_irq_err(struct net_device *dev)
995{ 1026{
996 struct at91_priv *priv = netdev_priv(dev); 1027 struct at91_priv *priv = netdev_priv(dev);
@@ -998,21 +1029,28 @@ static void at91_irq_err(struct net_device *dev)
998 struct can_frame *cf; 1029 struct can_frame *cf;
999 enum can_state new_state; 1030 enum can_state new_state;
1000 u32 reg_sr; 1031 u32 reg_sr;
1032 int err;
1001 1033
1002 reg_sr = at91_read(priv, AT91_SR); 1034 if (at91_is_sam9263(priv)) {
1003 1035 reg_sr = at91_read(priv, AT91_SR);
1004 /* we need to look at the unmasked reg_sr */ 1036
1005 if (unlikely(reg_sr & AT91_IRQ_BOFF)) 1037 /* we need to look at the unmasked reg_sr */
1006 new_state = CAN_STATE_BUS_OFF; 1038 if (unlikely(reg_sr & AT91_IRQ_BOFF))
1007 else if (unlikely(reg_sr & AT91_IRQ_ERRP)) 1039 new_state = CAN_STATE_BUS_OFF;
1008 new_state = CAN_STATE_ERROR_PASSIVE; 1040 else if (unlikely(reg_sr & AT91_IRQ_ERRP))
1009 else if (unlikely(reg_sr & AT91_IRQ_WARN)) 1041 new_state = CAN_STATE_ERROR_PASSIVE;
1010 new_state = CAN_STATE_ERROR_WARNING; 1042 else if (unlikely(reg_sr & AT91_IRQ_WARN))
1011 else if (likely(reg_sr & AT91_IRQ_ERRA)) 1043 new_state = CAN_STATE_ERROR_WARNING;
1012 new_state = CAN_STATE_ERROR_ACTIVE; 1044 else if (likely(reg_sr & AT91_IRQ_ERRA))
1013 else { 1045 new_state = CAN_STATE_ERROR_ACTIVE;
1014 netdev_err(dev, "BUG! hardware in undefined state\n"); 1046 else {
1015 return; 1047 netdev_err(dev, "BUG! hardware in undefined state\n");
1048 return;
1049 }
1050 } else {
1051 err = at91_get_state_by_bec(dev, &new_state);
1052 if (err)
1053 return;
1016 } 1054 }
1017 1055
1018 /* state hasn't changed */ 1056 /* state hasn't changed */
@@ -1330,6 +1368,9 @@ static const struct platform_device_id at91_can_id_table[] = {
1330 .name = "at91_can", 1368 .name = "at91_can",
1331 .driver_data = AT91_DEVTYPE_SAM9263, 1369 .driver_data = AT91_DEVTYPE_SAM9263,
1332 }, { 1370 }, {
1371 .name = "at91sam9x5_can",
1372 .driver_data = AT91_DEVTYPE_SAM9X5,
1373 }, {
1333 /* sentinel */ 1374 /* sentinel */
1334 } 1375 }
1335}; 1376};