.. | .. |
---|
214 | 214 | #define CAN_RXFRD_OFFSET(n) (CAN_RXFRD + CAN_RF_SIZE * (n)) |
---|
215 | 215 | |
---|
216 | 216 | #define CAN_RX_FILTER_MASK 0x1fffffff |
---|
| 217 | +#define NOACK_ERR_FLAG 0xc200800 |
---|
| 218 | +#define CAN_BUSOFF_FLAG 0x20 |
---|
217 | 219 | |
---|
218 | 220 | #define DRV_NAME "rockchip_canfd" |
---|
219 | 221 | |
---|
.. | .. |
---|
234 | 236 | bool txtorx; |
---|
235 | 237 | u32 tx_invalid[4]; |
---|
236 | 238 | struct delayed_work tx_err_work; |
---|
| 239 | + u32 delay_time_ms; |
---|
237 | 240 | }; |
---|
238 | 241 | |
---|
239 | 242 | static inline u32 rockchip_canfd_read(const struct rockchip_canfd *priv, |
---|
.. | .. |
---|
357 | 360 | |
---|
358 | 361 | rockchip_canfd_write(rcan, CAN_DBTP, reg_btp); |
---|
359 | 362 | } |
---|
| 363 | + if (bt->bitrate > 200000) |
---|
| 364 | + rcan->delay_time_ms = 1; |
---|
| 365 | + else if (bt->bitrate > 50000) |
---|
| 366 | + rcan->delay_time_ms = 5; |
---|
| 367 | + else |
---|
| 368 | + rcan->delay_time_ms = 20; |
---|
360 | 369 | |
---|
361 | 370 | netdev_dbg(ndev, "%s NBTP=0x%08x, DBTP=0x%08x, TDCR=0x%08x\n", __func__, |
---|
362 | 371 | rockchip_canfd_read(rcan, CAN_NBTP), |
---|
.. | .. |
---|
428 | 437 | if (rcan->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) |
---|
429 | 438 | val |= MODE_SELF_TEST | MODE_LBACK; |
---|
430 | 439 | |
---|
| 440 | + /* Listen-only mode */ |
---|
| 441 | + if (rcan->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) |
---|
| 442 | + val |= MODE_SILENT; |
---|
| 443 | + |
---|
431 | 444 | rockchip_canfd_write(rcan, CAN_MODE, val); |
---|
432 | 445 | |
---|
433 | 446 | rockchip_canfd_set_bittiming(ndev); |
---|
.. | .. |
---|
487 | 500 | { |
---|
488 | 501 | struct rockchip_canfd *rcan = |
---|
489 | 502 | container_of(work, struct rockchip_canfd, tx_err_work.work); |
---|
490 | | - u32 mode; |
---|
| 503 | + u32 mode, err_code; |
---|
491 | 504 | |
---|
492 | 505 | mode = rockchip_canfd_read(rcan, CAN_MODE); |
---|
493 | | - rockchip_canfd_write(rcan, CAN_MODE, 0); |
---|
494 | | - rockchip_canfd_write(rcan, CAN_MODE, mode); |
---|
495 | | - rockchip_canfd_write(rcan, CAN_CMD, CAN_TX0_REQ); |
---|
496 | | - schedule_delayed_work(&rcan->tx_err_work, 1); |
---|
| 506 | + err_code = rockchip_canfd_read(rcan, CAN_ERR_CODE); |
---|
| 507 | + if ((err_code & NOACK_ERR_FLAG) == NOACK_ERR_FLAG) { |
---|
| 508 | + rockchip_canfd_write(rcan, CAN_MODE, |
---|
| 509 | + rockchip_canfd_read(rcan, CAN_MODE) | MODE_SPACE_RX); |
---|
| 510 | + rockchip_canfd_write(rcan, CAN_CMD, CAN_TX0_REQ); |
---|
| 511 | + rockchip_canfd_write(rcan, CAN_MODE, |
---|
| 512 | + rockchip_canfd_read(rcan, CAN_MODE) & (~MODE_SPACE_RX)); |
---|
| 513 | + schedule_delayed_work(&rcan->tx_err_work, msecs_to_jiffies(rcan->delay_time_ms)); |
---|
| 514 | + } else { |
---|
| 515 | + rockchip_canfd_write(rcan, CAN_MODE, 0); |
---|
| 516 | + rockchip_canfd_write(rcan, CAN_MODE, mode); |
---|
| 517 | + rockchip_canfd_write(rcan, CAN_MODE, |
---|
| 518 | + rockchip_canfd_read(rcan, CAN_MODE) | MODE_SPACE_RX); |
---|
| 519 | + rockchip_canfd_write(rcan, CAN_CMD, CAN_TX0_REQ); |
---|
| 520 | + rockchip_canfd_write(rcan, CAN_MODE, |
---|
| 521 | + rockchip_canfd_read(rcan, CAN_MODE) & (~MODE_SPACE_RX)); |
---|
| 522 | + schedule_delayed_work(&rcan->tx_err_work, msecs_to_jiffies(rcan->delay_time_ms)); |
---|
| 523 | + } |
---|
497 | 524 | } |
---|
498 | 525 | |
---|
499 | 526 | /* transmit a CAN message |
---|
.. | .. |
---|
569 | 596 | for (i = 0; i < cf->len; i += 4) |
---|
570 | 597 | rockchip_canfd_write(rcan, CAN_TXDAT0 + i, |
---|
571 | 598 | *(u32 *)(cf->data + i)); |
---|
| 599 | + can_put_echo_skb(skb, ndev, 0); |
---|
572 | 600 | rockchip_canfd_write(rcan, CAN_CMD, CAN_TX1_REQ); |
---|
573 | 601 | local_irq_restore(flags); |
---|
574 | | - can_put_echo_skb(skb, ndev, 0); |
---|
575 | | - |
---|
576 | 602 | return NETDEV_TX_OK; |
---|
577 | 603 | } |
---|
578 | 604 | |
---|
.. | .. |
---|
583 | 609 | rockchip_canfd_write(rcan, CAN_TXDAT0 + i, |
---|
584 | 610 | *(u32 *)(cf->data + i)); |
---|
585 | 611 | |
---|
586 | | - rockchip_canfd_write(rcan, CAN_CMD, cmd); |
---|
587 | | - |
---|
588 | | - schedule_delayed_work(&rcan->tx_err_work, 1); |
---|
589 | | - |
---|
590 | 612 | can_put_echo_skb(skb, ndev, 0); |
---|
591 | | - |
---|
| 613 | + rockchip_canfd_write(rcan, CAN_MODE, |
---|
| 614 | + rockchip_canfd_read(rcan, CAN_MODE) | MODE_SPACE_RX); |
---|
| 615 | + rockchip_canfd_write(rcan, CAN_CMD, cmd); |
---|
| 616 | + rockchip_canfd_write(rcan, CAN_MODE, |
---|
| 617 | + rockchip_canfd_read(rcan, CAN_MODE) & (~MODE_SPACE_RX)); |
---|
| 618 | + schedule_delayed_work(&rcan->tx_err_work, msecs_to_jiffies(rcan->delay_time_ms)); |
---|
592 | 619 | return NETDEV_TX_OK; |
---|
593 | 620 | } |
---|
594 | 621 | |
---|
.. | .. |
---|
740 | 767 | cf->data[7] = rxerr; |
---|
741 | 768 | } |
---|
742 | 769 | |
---|
743 | | - if (isr & TX_LOSTARB_INT) |
---|
744 | | - schedule_delayed_work(&rcan->tx_err_work, 1); |
---|
745 | | - |
---|
746 | 770 | if (isr & BUS_OFF_INT) { |
---|
747 | 771 | rcan->can.state = CAN_STATE_BUS_OFF; |
---|
748 | 772 | rcan->can.can_stats.bus_off++; |
---|
.. | .. |
---|
772 | 796 | } |
---|
773 | 797 | |
---|
774 | 798 | if (rcan->can.state >= CAN_STATE_BUS_OFF || |
---|
775 | | - ((sta_reg & 0x20) == 0x20)) |
---|
776 | | - can_bus_off(ndev); |
---|
| 799 | + ((sta_reg & CAN_BUSOFF_FLAG) == CAN_BUSOFF_FLAG)) { |
---|
| 800 | + cancel_delayed_work(&rcan->tx_err_work); |
---|
| 801 | + netif_stop_queue(ndev); |
---|
| 802 | + rockchip_canfd_stop(ndev); |
---|
| 803 | + can_free_echo_skb(ndev, 0); |
---|
| 804 | + rockchip_canfd_start(ndev); |
---|
| 805 | + netif_start_queue(ndev); |
---|
| 806 | + } |
---|
777 | 807 | |
---|
778 | 808 | stats->rx_packets++; |
---|
779 | 809 | stats->rx_bytes += cf->can_dlc; |
---|
.. | .. |
---|
788 | 818 | struct rockchip_canfd *rcan = netdev_priv(ndev); |
---|
789 | 819 | struct net_device_stats *stats = &ndev->stats; |
---|
790 | 820 | u32 err_int = ERR_WARN_INT | RX_BUF_OV_INT | PASSIVE_ERR_INT | |
---|
791 | | - TX_LOSTARB_INT | BUS_ERR_INT | BUS_OFF_INT; |
---|
| 821 | + BUS_ERR_INT | BUS_OFF_INT; |
---|
792 | 822 | u32 isr; |
---|
793 | 823 | u32 dlc = 0; |
---|
794 | 824 | u32 quota, work_done = 0; |
---|
795 | 825 | |
---|
796 | 826 | isr = rockchip_canfd_read(rcan, CAN_INT); |
---|
797 | 827 | if (isr & TX_FINISH_INT) { |
---|
| 828 | + cancel_delayed_work(&rcan->tx_err_work); |
---|
798 | 829 | dlc = rockchip_canfd_read(rcan, CAN_TXFIC); |
---|
799 | 830 | /* transmission complete interrupt */ |
---|
800 | 831 | if (dlc & FDF_MASK) |
---|
.. | .. |
---|
802 | 833 | else |
---|
803 | 834 | stats->tx_bytes += (dlc & DLC_MASK); |
---|
804 | 835 | stats->tx_packets++; |
---|
805 | | - cancel_delayed_work(&rcan->tx_err_work); |
---|
806 | 836 | if (rcan->txtorx && rcan->mode <= ROCKCHIP_RK3568_CAN_MODE && dlc & FORMAT_MASK) { |
---|
807 | 837 | rockchip_canfd_write(rcan, CAN_TX_CHECK_FIC, FORMAT_MASK); |
---|
808 | 838 | quota = rockchip_canfd_get_rx_fifo_cnt(ndev); |
---|
.. | .. |
---|
814 | 844 | rockchip_canfd_write(rcan, CAN_CMD, CAN_TX1_REQ); |
---|
815 | 845 | rockchip_canfd_write(rcan, CAN_TX_CHECK_FIC, 0); |
---|
816 | 846 | } |
---|
| 847 | + if (read_poll_timeout_atomic(rockchip_canfd_read, quota, |
---|
| 848 | + !(quota & 0x3), |
---|
| 849 | + 0, 5000000, false, rcan, CAN_CMD)) |
---|
| 850 | + netdev_err(ndev, "Warning: wait tx req timeout!\n"); |
---|
817 | 851 | rockchip_canfd_write(rcan, CAN_CMD, 0); |
---|
818 | 852 | can_get_echo_skb(ndev, 0); |
---|
819 | 853 | netif_wake_queue(ndev); |
---|
.. | .. |
---|
825 | 859 | rockchip_canfd_write(rcan, CAN_INT_MASK, 0x1); |
---|
826 | 860 | napi_schedule(&rcan->napi); |
---|
827 | 861 | } else { |
---|
828 | | - quota = rockchip_canfd_get_rx_fifo_cnt(ndev); |
---|
| 862 | + work_done = 0; |
---|
| 863 | + quota = (rockchip_canfd_read(rcan, CAN_RXFC) & |
---|
| 864 | + rcan->rx_fifo_mask) >> |
---|
| 865 | + rcan->rx_fifo_shift; |
---|
829 | 866 | if (quota) { |
---|
830 | 867 | while (work_done < quota) |
---|
831 | 868 | work_done += rockchip_canfd_rx(ndev); |
---|