diff options
Diffstat (limited to 'drivers/net/can/at91_can.c')
-rw-r--r-- | drivers/net/can/at91_can.c | 69 |
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 | ||
128 | enum at91_devtype { | 128 | enum at91_devtype { |
129 | AT91_DEVTYPE_SAM9263, | 129 | AT91_DEVTYPE_SAM9263, |
130 | AT91_DEVTYPE_SAM9X5, | ||
130 | }; | 131 | }; |
131 | 132 | ||
132 | struct at91_devtype_data { | 133 | struct 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 | ||
168 | static struct can_bittiming_const at91_bittiming_const = { | 175 | static 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 | ||
186 | AT91_IS(9263); | 193 | AT91_IS(9263); |
194 | AT91_IS(9X5); | ||
187 | 195 | ||
188 | static inline unsigned int get_mb_rx_first(const struct at91_priv *priv) | 196 | static 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 | ||
1002 | static 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 | |||
994 | static void at91_irq_err(struct net_device *dev) | 1025 | static 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 | }; |