diff options
Diffstat (limited to 'drivers/net/can/flexcan.c')
-rw-r--r-- | drivers/net/can/flexcan.c | 53 |
1 files changed, 44 insertions, 9 deletions
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 944aa5d3af6e..6586309329e6 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c | |||
@@ -62,7 +62,7 @@ | |||
62 | #define FLEXCAN_MCR_BCC BIT(16) | 62 | #define FLEXCAN_MCR_BCC BIT(16) |
63 | #define FLEXCAN_MCR_LPRIO_EN BIT(13) | 63 | #define FLEXCAN_MCR_LPRIO_EN BIT(13) |
64 | #define FLEXCAN_MCR_AEN BIT(12) | 64 | #define FLEXCAN_MCR_AEN BIT(12) |
65 | #define FLEXCAN_MCR_MAXMB(x) ((x) & 0x1f) | 65 | #define FLEXCAN_MCR_MAXMB(x) ((x) & 0x7f) |
66 | #define FLEXCAN_MCR_IDAM_A (0 << 8) | 66 | #define FLEXCAN_MCR_IDAM_A (0 << 8) |
67 | #define FLEXCAN_MCR_IDAM_B (1 << 8) | 67 | #define FLEXCAN_MCR_IDAM_B (1 << 8) |
68 | #define FLEXCAN_MCR_IDAM_C (2 << 8) | 68 | #define FLEXCAN_MCR_IDAM_C (2 << 8) |
@@ -125,7 +125,9 @@ | |||
125 | FLEXCAN_ESR_BOFF_INT | FLEXCAN_ESR_ERR_INT) | 125 | FLEXCAN_ESR_BOFF_INT | FLEXCAN_ESR_ERR_INT) |
126 | 126 | ||
127 | /* FLEXCAN interrupt flag register (IFLAG) bits */ | 127 | /* FLEXCAN interrupt flag register (IFLAG) bits */ |
128 | #define FLEXCAN_TX_BUF_ID 8 | 128 | /* Errata ERR005829 step7: Reserve first valid MB */ |
129 | #define FLEXCAN_TX_BUF_RESERVED 8 | ||
130 | #define FLEXCAN_TX_BUF_ID 9 | ||
129 | #define FLEXCAN_IFLAG_BUF(x) BIT(x) | 131 | #define FLEXCAN_IFLAG_BUF(x) BIT(x) |
130 | #define FLEXCAN_IFLAG_RX_FIFO_OVERFLOW BIT(7) | 132 | #define FLEXCAN_IFLAG_RX_FIFO_OVERFLOW BIT(7) |
131 | #define FLEXCAN_IFLAG_RX_FIFO_WARN BIT(6) | 133 | #define FLEXCAN_IFLAG_RX_FIFO_WARN BIT(6) |
@@ -136,6 +138,17 @@ | |||
136 | 138 | ||
137 | /* FLEXCAN message buffers */ | 139 | /* FLEXCAN message buffers */ |
138 | #define FLEXCAN_MB_CNT_CODE(x) (((x) & 0xf) << 24) | 140 | #define FLEXCAN_MB_CNT_CODE(x) (((x) & 0xf) << 24) |
141 | #define FLEXCAN_MB_CODE_RX_INACTIVE (0x0 << 24) | ||
142 | #define FLEXCAN_MB_CODE_RX_EMPTY (0x4 << 24) | ||
143 | #define FLEXCAN_MB_CODE_RX_FULL (0x2 << 24) | ||
144 | #define FLEXCAN_MB_CODE_RX_OVERRRUN (0x6 << 24) | ||
145 | #define FLEXCAN_MB_CODE_RX_RANSWER (0xa << 24) | ||
146 | |||
147 | #define FLEXCAN_MB_CODE_TX_INACTIVE (0x8 << 24) | ||
148 | #define FLEXCAN_MB_CODE_TX_ABORT (0x9 << 24) | ||
149 | #define FLEXCAN_MB_CODE_TX_DATA (0xc << 24) | ||
150 | #define FLEXCAN_MB_CODE_TX_TANSWER (0xe << 24) | ||
151 | |||
139 | #define FLEXCAN_MB_CNT_SRR BIT(22) | 152 | #define FLEXCAN_MB_CNT_SRR BIT(22) |
140 | #define FLEXCAN_MB_CNT_IDE BIT(21) | 153 | #define FLEXCAN_MB_CNT_IDE BIT(21) |
141 | #define FLEXCAN_MB_CNT_RTR BIT(20) | 154 | #define FLEXCAN_MB_CNT_RTR BIT(20) |
@@ -298,7 +311,7 @@ static int flexcan_chip_enable(struct flexcan_priv *priv) | |||
298 | flexcan_write(reg, ®s->mcr); | 311 | flexcan_write(reg, ®s->mcr); |
299 | 312 | ||
300 | while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)) | 313 | while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)) |
301 | usleep_range(10, 20); | 314 | udelay(10); |
302 | 315 | ||
303 | if (flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK) | 316 | if (flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK) |
304 | return -ETIMEDOUT; | 317 | return -ETIMEDOUT; |
@@ -317,7 +330,7 @@ static int flexcan_chip_disable(struct flexcan_priv *priv) | |||
317 | flexcan_write(reg, ®s->mcr); | 330 | flexcan_write(reg, ®s->mcr); |
318 | 331 | ||
319 | while (timeout-- && !(flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)) | 332 | while (timeout-- && !(flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)) |
320 | usleep_range(10, 20); | 333 | udelay(10); |
321 | 334 | ||
322 | if (!(flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)) | 335 | if (!(flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)) |
323 | return -ETIMEDOUT; | 336 | return -ETIMEDOUT; |
@@ -336,7 +349,7 @@ static int flexcan_chip_freeze(struct flexcan_priv *priv) | |||
336 | flexcan_write(reg, ®s->mcr); | 349 | flexcan_write(reg, ®s->mcr); |
337 | 350 | ||
338 | while (timeout-- && !(flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK)) | 351 | while (timeout-- && !(flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK)) |
339 | usleep_range(100, 200); | 352 | udelay(100); |
340 | 353 | ||
341 | if (!(flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK)) | 354 | if (!(flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK)) |
342 | return -ETIMEDOUT; | 355 | return -ETIMEDOUT; |
@@ -355,7 +368,7 @@ static int flexcan_chip_unfreeze(struct flexcan_priv *priv) | |||
355 | flexcan_write(reg, ®s->mcr); | 368 | flexcan_write(reg, ®s->mcr); |
356 | 369 | ||
357 | while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK)) | 370 | while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK)) |
358 | usleep_range(10, 20); | 371 | udelay(10); |
359 | 372 | ||
360 | if (flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK) | 373 | if (flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK) |
361 | return -ETIMEDOUT; | 374 | return -ETIMEDOUT; |
@@ -370,7 +383,7 @@ static int flexcan_chip_softreset(struct flexcan_priv *priv) | |||
370 | 383 | ||
371 | flexcan_write(FLEXCAN_MCR_SOFTRST, ®s->mcr); | 384 | flexcan_write(FLEXCAN_MCR_SOFTRST, ®s->mcr); |
372 | while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_SOFTRST)) | 385 | while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_SOFTRST)) |
373 | usleep_range(10, 20); | 386 | udelay(10); |
374 | 387 | ||
375 | if (flexcan_read(®s->mcr) & FLEXCAN_MCR_SOFTRST) | 388 | if (flexcan_read(®s->mcr) & FLEXCAN_MCR_SOFTRST) |
376 | return -ETIMEDOUT; | 389 | return -ETIMEDOUT; |
@@ -428,6 +441,14 @@ static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
428 | flexcan_write(can_id, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_id); | 441 | flexcan_write(can_id, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_id); |
429 | flexcan_write(ctrl, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl); | 442 | flexcan_write(ctrl, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl); |
430 | 443 | ||
444 | /* Errata ERR005829 step8: | ||
445 | * Write twice INACTIVE(0x8) code to first MB. | ||
446 | */ | ||
447 | flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, | ||
448 | ®s->cantxfg[FLEXCAN_TX_BUF_RESERVED].can_ctrl); | ||
449 | flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, | ||
450 | ®s->cantxfg[FLEXCAN_TX_BUF_RESERVED].can_ctrl); | ||
451 | |||
431 | return NETDEV_TX_OK; | 452 | return NETDEV_TX_OK; |
432 | } | 453 | } |
433 | 454 | ||
@@ -744,6 +765,9 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) | |||
744 | stats->tx_bytes += can_get_echo_skb(dev, 0); | 765 | stats->tx_bytes += can_get_echo_skb(dev, 0); |
745 | stats->tx_packets++; | 766 | stats->tx_packets++; |
746 | can_led_event(dev, CAN_LED_EVENT_TX); | 767 | can_led_event(dev, CAN_LED_EVENT_TX); |
768 | /* after sending a RTR frame mailbox is in RX mode */ | ||
769 | flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, | ||
770 | ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl); | ||
747 | flexcan_write((1 << FLEXCAN_TX_BUF_ID), ®s->iflag1); | 771 | flexcan_write((1 << FLEXCAN_TX_BUF_ID), ®s->iflag1); |
748 | netif_wake_queue(dev); | 772 | netif_wake_queue(dev); |
749 | } | 773 | } |
@@ -801,6 +825,7 @@ static int flexcan_chip_start(struct net_device *dev) | |||
801 | struct flexcan_regs __iomem *regs = priv->base; | 825 | struct flexcan_regs __iomem *regs = priv->base; |
802 | int err; | 826 | int err; |
803 | u32 reg_mcr, reg_ctrl; | 827 | u32 reg_mcr, reg_ctrl; |
828 | int i; | ||
804 | 829 | ||
805 | /* enable module */ | 830 | /* enable module */ |
806 | err = flexcan_chip_enable(priv); | 831 | err = flexcan_chip_enable(priv); |
@@ -867,8 +892,18 @@ static int flexcan_chip_start(struct net_device *dev) | |||
867 | netdev_dbg(dev, "%s: writing ctrl=0x%08x", __func__, reg_ctrl); | 892 | netdev_dbg(dev, "%s: writing ctrl=0x%08x", __func__, reg_ctrl); |
868 | flexcan_write(reg_ctrl, ®s->ctrl); | 893 | flexcan_write(reg_ctrl, ®s->ctrl); |
869 | 894 | ||
870 | /* Abort any pending TX, mark Mailbox as INACTIVE */ | 895 | /* clear and invalidate all mailboxes first */ |
871 | flexcan_write(FLEXCAN_MB_CNT_CODE(0x4), | 896 | for (i = FLEXCAN_TX_BUF_ID; i < ARRAY_SIZE(regs->cantxfg); i++) { |
897 | flexcan_write(FLEXCAN_MB_CODE_RX_INACTIVE, | ||
898 | ®s->cantxfg[i].can_ctrl); | ||
899 | } | ||
900 | |||
901 | /* Errata ERR005829: mark first TX mailbox as INACTIVE */ | ||
902 | flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, | ||
903 | ®s->cantxfg[FLEXCAN_TX_BUF_RESERVED].can_ctrl); | ||
904 | |||
905 | /* mark TX mailbox as INACTIVE */ | ||
906 | flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, | ||
872 | ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl); | 907 | ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl); |
873 | 908 | ||
874 | /* acceptance mask/acceptance code (accept everything) */ | 909 | /* acceptance mask/acceptance code (accept everything) */ |