diff options
author | David S. Miller <davem@davemloft.net> | 2010-10-18 10:11:44 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-10-18 10:11:44 -0400 |
commit | a47d60561e111f5009ad0964069cfff77f76dbaa (patch) | |
tree | 2e11d4cbc43759bb217263533e5e1539ac71df7e | |
parent | d8e62719ea63daf6afde2d2d09fb861c1559711e (diff) | |
parent | 9c473fc33915ddb14b71a4929c838c22b20a24ce (diff) |
Merge branch 'can/mcp251x-for-net-next' of git://git.pengutronix.de/git/mkl/linux-2.6
-rw-r--r-- | drivers/net/can/mcp251x.c | 95 | ||||
-rw-r--r-- | include/linux/can/platform/mcp251x.h | 4 |
2 files changed, 70 insertions, 29 deletions
diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c index b11a0cb5ed81..c664be261e98 100644 --- a/drivers/net/can/mcp251x.c +++ b/drivers/net/can/mcp251x.c | |||
@@ -38,14 +38,14 @@ | |||
38 | * static struct mcp251x_platform_data mcp251x_info = { | 38 | * static struct mcp251x_platform_data mcp251x_info = { |
39 | * .oscillator_frequency = 8000000, | 39 | * .oscillator_frequency = 8000000, |
40 | * .board_specific_setup = &mcp251x_setup, | 40 | * .board_specific_setup = &mcp251x_setup, |
41 | * .model = CAN_MCP251X_MCP2510, | ||
42 | * .power_enable = mcp251x_power_enable, | 41 | * .power_enable = mcp251x_power_enable, |
43 | * .transceiver_enable = NULL, | 42 | * .transceiver_enable = NULL, |
44 | * }; | 43 | * }; |
45 | * | 44 | * |
46 | * static struct spi_board_info spi_board_info[] = { | 45 | * static struct spi_board_info spi_board_info[] = { |
47 | * { | 46 | * { |
48 | * .modalias = "mcp251x", | 47 | * .modalias = "mcp2510", |
48 | * // or "mcp2515" depending on your controller | ||
49 | * .platform_data = &mcp251x_info, | 49 | * .platform_data = &mcp251x_info, |
50 | * .irq = IRQ_EINT13, | 50 | * .irq = IRQ_EINT13, |
51 | * .max_speed_hz = 2*1000*1000, | 51 | * .max_speed_hz = 2*1000*1000, |
@@ -125,6 +125,8 @@ | |||
125 | # define CANINTF_TX0IF 0x04 | 125 | # define CANINTF_TX0IF 0x04 |
126 | # define CANINTF_RX1IF 0x02 | 126 | # define CANINTF_RX1IF 0x02 |
127 | # define CANINTF_RX0IF 0x01 | 127 | # define CANINTF_RX0IF 0x01 |
128 | # define CANINTF_ERR_TX \ | ||
129 | (CANINTF_ERRIF | CANINTF_TX2IF | CANINTF_TX1IF | CANINTF_TX0IF) | ||
128 | #define EFLG 0x2d | 130 | #define EFLG 0x2d |
129 | # define EFLG_EWARN 0x01 | 131 | # define EFLG_EWARN 0x01 |
130 | # define EFLG_RXWAR 0x02 | 132 | # define EFLG_RXWAR 0x02 |
@@ -222,10 +224,16 @@ static struct can_bittiming_const mcp251x_bittiming_const = { | |||
222 | .brp_inc = 1, | 224 | .brp_inc = 1, |
223 | }; | 225 | }; |
224 | 226 | ||
227 | enum mcp251x_model { | ||
228 | CAN_MCP251X_MCP2510 = 0x2510, | ||
229 | CAN_MCP251X_MCP2515 = 0x2515, | ||
230 | }; | ||
231 | |||
225 | struct mcp251x_priv { | 232 | struct mcp251x_priv { |
226 | struct can_priv can; | 233 | struct can_priv can; |
227 | struct net_device *net; | 234 | struct net_device *net; |
228 | struct spi_device *spi; | 235 | struct spi_device *spi; |
236 | enum mcp251x_model model; | ||
229 | 237 | ||
230 | struct mutex mcp_lock; /* SPI device lock */ | 238 | struct mutex mcp_lock; /* SPI device lock */ |
231 | 239 | ||
@@ -250,6 +258,16 @@ struct mcp251x_priv { | |||
250 | int restart_tx; | 258 | int restart_tx; |
251 | }; | 259 | }; |
252 | 260 | ||
261 | #define MCP251X_IS(_model) \ | ||
262 | static inline int mcp251x_is_##_model(struct spi_device *spi) \ | ||
263 | { \ | ||
264 | struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); \ | ||
265 | return priv->model == CAN_MCP251X_MCP##_model; \ | ||
266 | } | ||
267 | |||
268 | MCP251X_IS(2510); | ||
269 | MCP251X_IS(2515); | ||
270 | |||
253 | static void mcp251x_clean(struct net_device *net) | 271 | static void mcp251x_clean(struct net_device *net) |
254 | { | 272 | { |
255 | struct mcp251x_priv *priv = netdev_priv(net); | 273 | struct mcp251x_priv *priv = netdev_priv(net); |
@@ -319,6 +337,20 @@ static u8 mcp251x_read_reg(struct spi_device *spi, uint8_t reg) | |||
319 | return val; | 337 | return val; |
320 | } | 338 | } |
321 | 339 | ||
340 | static void mcp251x_read_2regs(struct spi_device *spi, uint8_t reg, | ||
341 | uint8_t *v1, uint8_t *v2) | ||
342 | { | ||
343 | struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); | ||
344 | |||
345 | priv->spi_tx_buf[0] = INSTRUCTION_READ; | ||
346 | priv->spi_tx_buf[1] = reg; | ||
347 | |||
348 | mcp251x_spi_trans(spi, 4); | ||
349 | |||
350 | *v1 = priv->spi_rx_buf[2]; | ||
351 | *v2 = priv->spi_rx_buf[3]; | ||
352 | } | ||
353 | |||
322 | static void mcp251x_write_reg(struct spi_device *spi, u8 reg, uint8_t val) | 354 | static void mcp251x_write_reg(struct spi_device *spi, u8 reg, uint8_t val) |
323 | { | 355 | { |
324 | struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); | 356 | 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 | static void mcp251x_hw_tx_frame(struct spi_device *spi, u8 *buf, | 378 | static void mcp251x_hw_tx_frame(struct spi_device *spi, u8 *buf, |
347 | int len, int tx_buf_idx) | 379 | int len, int tx_buf_idx) |
348 | { | 380 | { |
349 | struct mcp251x_platform_data *pdata = spi->dev.platform_data; | ||
350 | struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); | 381 | struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); |
351 | 382 | ||
352 | if (pdata->model == CAN_MCP251X_MCP2510) { | 383 | if (mcp251x_is_2510(spi)) { |
353 | int i; | 384 | int i; |
354 | 385 | ||
355 | for (i = 1; i < TXBDAT_OFF + len; i++) | 386 | 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 | int buf_idx) | 423 | int buf_idx) |
393 | { | 424 | { |
394 | struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); | 425 | struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); |
395 | struct mcp251x_platform_data *pdata = spi->dev.platform_data; | ||
396 | 426 | ||
397 | if (pdata->model == CAN_MCP251X_MCP2510) { | 427 | if (mcp251x_is_2510(spi)) { |
398 | int i, len; | 428 | int i, len; |
399 | 429 | ||
400 | for (i = 1; i < RXBDAT_OFF; i++) | 430 | for (i = 1; i < RXBDAT_OFF; i++) |
@@ -451,7 +481,7 @@ static void mcp251x_hw_rx(struct spi_device *spi, int buf_idx) | |||
451 | 481 | ||
452 | priv->net->stats.rx_packets++; | 482 | priv->net->stats.rx_packets++; |
453 | priv->net->stats.rx_bytes += frame->can_dlc; | 483 | priv->net->stats.rx_bytes += frame->can_dlc; |
454 | netif_rx(skb); | 484 | netif_rx_ni(skb); |
455 | } | 485 | } |
456 | 486 | ||
457 | static void mcp251x_hw_sleep(struct spi_device *spi) | 487 | 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 | if (skb) { | 706 | if (skb) { |
677 | frame->can_id = can_id; | 707 | frame->can_id = can_id; |
678 | frame->data[1] = data1; | 708 | frame->data[1] = data1; |
679 | netif_rx(skb); | 709 | netif_rx_ni(skb); |
680 | } else { | 710 | } else { |
681 | dev_err(&net->dev, | 711 | dev_err(&net->dev, |
682 | "cannot allocate error skb\n"); | 712 | "cannot allocate error skb\n"); |
@@ -754,24 +784,39 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id) | |||
754 | mutex_lock(&priv->mcp_lock); | 784 | mutex_lock(&priv->mcp_lock); |
755 | while (!priv->force_quit) { | 785 | while (!priv->force_quit) { |
756 | enum can_state new_state; | 786 | enum can_state new_state; |
757 | u8 intf = mcp251x_read_reg(spi, CANINTF); | 787 | u8 intf, eflag; |
758 | u8 eflag; | 788 | u8 clear_intf = 0; |
759 | int can_id = 0, data1 = 0; | 789 | int can_id = 0, data1 = 0; |
760 | 790 | ||
791 | mcp251x_read_2regs(spi, CANINTF, &intf, &eflag); | ||
792 | |||
793 | /* receive buffer 0 */ | ||
761 | if (intf & CANINTF_RX0IF) { | 794 | if (intf & CANINTF_RX0IF) { |
762 | mcp251x_hw_rx(spi, 0); | 795 | mcp251x_hw_rx(spi, 0); |
763 | /* Free one buffer ASAP */ | 796 | /* |
764 | mcp251x_write_bits(spi, CANINTF, intf & CANINTF_RX0IF, | 797 | * Free one buffer ASAP |
765 | 0x00); | 798 | * (The MCP2515 does this automatically.) |
799 | */ | ||
800 | if (mcp251x_is_2510(spi)) | ||
801 | mcp251x_write_bits(spi, CANINTF, CANINTF_RX0IF, 0x00); | ||
766 | } | 802 | } |
767 | 803 | ||
768 | if (intf & CANINTF_RX1IF) | 804 | /* receive buffer 1 */ |
805 | if (intf & CANINTF_RX1IF) { | ||
769 | mcp251x_hw_rx(spi, 1); | 806 | mcp251x_hw_rx(spi, 1); |
807 | /* the MCP2515 does this automatically */ | ||
808 | if (mcp251x_is_2510(spi)) | ||
809 | clear_intf |= CANINTF_RX1IF; | ||
810 | } | ||
770 | 811 | ||
771 | mcp251x_write_bits(spi, CANINTF, intf, 0x00); | 812 | /* any error or tx interrupt we need to clear? */ |
813 | if (intf & CANINTF_ERR_TX) | ||
814 | clear_intf |= intf & CANINTF_ERR_TX; | ||
815 | if (clear_intf) | ||
816 | mcp251x_write_bits(spi, CANINTF, clear_intf, 0x00); | ||
772 | 817 | ||
773 | eflag = mcp251x_read_reg(spi, EFLG); | 818 | if (eflag) |
774 | mcp251x_write_reg(spi, EFLG, 0x00); | 819 | mcp251x_write_bits(spi, EFLG, eflag, 0x00); |
775 | 820 | ||
776 | /* Update can state */ | 821 | /* Update can state */ |
777 | if (eflag & EFLG_TXBO) { | 822 | if (eflag & EFLG_TXBO) { |
@@ -816,10 +861,14 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id) | |||
816 | if (intf & CANINTF_ERRIF) { | 861 | if (intf & CANINTF_ERRIF) { |
817 | /* Handle overflow counters */ | 862 | /* Handle overflow counters */ |
818 | if (eflag & (EFLG_RX0OVR | EFLG_RX1OVR)) { | 863 | if (eflag & (EFLG_RX0OVR | EFLG_RX1OVR)) { |
819 | if (eflag & EFLG_RX0OVR) | 864 | if (eflag & EFLG_RX0OVR) { |
820 | net->stats.rx_over_errors++; | 865 | net->stats.rx_over_errors++; |
821 | if (eflag & EFLG_RX1OVR) | 866 | net->stats.rx_errors++; |
867 | } | ||
868 | if (eflag & EFLG_RX1OVR) { | ||
822 | net->stats.rx_over_errors++; | 869 | net->stats.rx_over_errors++; |
870 | net->stats.rx_errors++; | ||
871 | } | ||
823 | can_id |= CAN_ERR_CRTL; | 872 | can_id |= CAN_ERR_CRTL; |
824 | data1 |= CAN_ERR_CRTL_RX_OVERFLOW; | 873 | data1 |= CAN_ERR_CRTL_RX_OVERFLOW; |
825 | } | 874 | } |
@@ -921,16 +970,12 @@ static int __devinit mcp251x_can_probe(struct spi_device *spi) | |||
921 | struct net_device *net; | 970 | struct net_device *net; |
922 | struct mcp251x_priv *priv; | 971 | struct mcp251x_priv *priv; |
923 | struct mcp251x_platform_data *pdata = spi->dev.platform_data; | 972 | struct mcp251x_platform_data *pdata = spi->dev.platform_data; |
924 | int model = spi_get_device_id(spi)->driver_data; | ||
925 | int ret = -ENODEV; | 973 | int ret = -ENODEV; |
926 | 974 | ||
927 | if (!pdata) | 975 | if (!pdata) |
928 | /* Platform data is required for osc freq */ | 976 | /* Platform data is required for osc freq */ |
929 | goto error_out; | 977 | goto error_out; |
930 | 978 | ||
931 | if (model) | ||
932 | pdata->model = model; | ||
933 | |||
934 | /* Allocate can/net device */ | 979 | /* Allocate can/net device */ |
935 | net = alloc_candev(sizeof(struct mcp251x_priv), TX_ECHO_SKB_MAX); | 980 | net = alloc_candev(sizeof(struct mcp251x_priv), TX_ECHO_SKB_MAX); |
936 | if (!net) { | 981 | if (!net) { |
@@ -947,6 +992,7 @@ static int __devinit mcp251x_can_probe(struct spi_device *spi) | |||
947 | priv->can.clock.freq = pdata->oscillator_frequency / 2; | 992 | priv->can.clock.freq = pdata->oscillator_frequency / 2; |
948 | priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | | 993 | priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | |
949 | CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY; | 994 | CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY; |
995 | priv->model = spi_get_device_id(spi)->driver_data; | ||
950 | priv->net = net; | 996 | priv->net = net; |
951 | dev_set_drvdata(&spi->dev, priv); | 997 | dev_set_drvdata(&spi->dev, priv); |
952 | 998 | ||
@@ -1120,8 +1166,7 @@ static int mcp251x_can_resume(struct spi_device *spi) | |||
1120 | #define mcp251x_can_resume NULL | 1166 | #define mcp251x_can_resume NULL |
1121 | #endif | 1167 | #endif |
1122 | 1168 | ||
1123 | static struct spi_device_id mcp251x_id_table[] = { | 1169 | static const struct spi_device_id mcp251x_id_table[] = { |
1124 | { "mcp251x", 0 /* Use pdata.model */ }, | ||
1125 | { "mcp2510", CAN_MCP251X_MCP2510 }, | 1170 | { "mcp2510", CAN_MCP251X_MCP2510 }, |
1126 | { "mcp2515", CAN_MCP251X_MCP2515 }, | 1171 | { "mcp2515", CAN_MCP251X_MCP2515 }, |
1127 | { }, | 1172 | { }, |
diff --git a/include/linux/can/platform/mcp251x.h b/include/linux/can/platform/mcp251x.h index dba28268e651..8e20540043f5 100644 --- a/include/linux/can/platform/mcp251x.h +++ b/include/linux/can/platform/mcp251x.h | |||
@@ -12,7 +12,6 @@ | |||
12 | /** | 12 | /** |
13 | * struct mcp251x_platform_data - MCP251X SPI CAN controller platform data | 13 | * struct mcp251x_platform_data - MCP251X SPI CAN controller platform data |
14 | * @oscillator_frequency: - oscillator frequency in Hz | 14 | * @oscillator_frequency: - oscillator frequency in Hz |
15 | * @model: - actual type of chip | ||
16 | * @board_specific_setup: - called before probing the chip (power,reset) | 15 | * @board_specific_setup: - called before probing the chip (power,reset) |
17 | * @transceiver_enable: - called to power on/off the transceiver | 16 | * @transceiver_enable: - called to power on/off the transceiver |
18 | * @power_enable: - called to power on/off the mcp *and* the | 17 | * @power_enable: - called to power on/off the mcp *and* the |
@@ -25,9 +24,6 @@ | |||
25 | 24 | ||
26 | struct mcp251x_platform_data { | 25 | struct mcp251x_platform_data { |
27 | unsigned long oscillator_frequency; | 26 | unsigned long oscillator_frequency; |
28 | int model; | ||
29 | #define CAN_MCP251X_MCP2510 0x2510 | ||
30 | #define CAN_MCP251X_MCP2515 0x2515 | ||
31 | int (*board_specific_setup)(struct spi_device *spi); | 27 | int (*board_specific_setup)(struct spi_device *spi); |
32 | int (*transceiver_enable)(int enable); | 28 | int (*transceiver_enable)(int enable); |
33 | int (*power_enable) (int enable); | 29 | int (*power_enable) (int enable); |