.. | .. |
---|
27 | 27 | #include <linux/can/led.h> |
---|
28 | 28 | #include <linux/reset.h> |
---|
29 | 29 | #include <linux/pm_runtime.h> |
---|
| 30 | +#include <linux/rockchip/cpu.h> |
---|
30 | 31 | |
---|
31 | 32 | /* registers definition */ |
---|
32 | 33 | enum rockchip_canfd_reg { |
---|
.. | .. |
---|
105 | 106 | ROCKCHIP_CANFD_MODE = 0, |
---|
106 | 107 | ROCKCHIP_CAN_MODE, |
---|
107 | 108 | ROCKCHIP_RK3568_CAN_MODE, |
---|
| 109 | + ROCKCHIP_RK3568_CAN_MODE_V2, |
---|
108 | 110 | }; |
---|
109 | 111 | |
---|
110 | 112 | #define DATE_LENGTH_12_BYTE (0x9) |
---|
.. | .. |
---|
212 | 214 | #define CAN_RXFRD_OFFSET(n) (CAN_RXFRD + CAN_RF_SIZE * (n)) |
---|
213 | 215 | |
---|
214 | 216 | #define CAN_RX_FILTER_MASK 0x1fffffff |
---|
| 217 | +#define NOACK_ERR_FLAG 0xc200800 |
---|
| 218 | +#define CAN_BUSOFF_FLAG 0x20 |
---|
215 | 219 | |
---|
216 | 220 | #define DRV_NAME "rockchip_canfd" |
---|
217 | 221 | |
---|
.. | .. |
---|
220 | 224 | struct rockchip_canfd { |
---|
221 | 225 | struct can_priv can; |
---|
222 | 226 | struct device *dev; |
---|
| 227 | + struct napi_struct napi; |
---|
223 | 228 | struct clk_bulk_data *clks; |
---|
224 | 229 | int num_clks; |
---|
225 | 230 | struct reset_control *reset; |
---|
.. | .. |
---|
231 | 236 | bool txtorx; |
---|
232 | 237 | u32 tx_invalid[4]; |
---|
233 | 238 | struct delayed_work tx_err_work; |
---|
| 239 | + u32 delay_time_ms; |
---|
234 | 240 | }; |
---|
235 | 241 | |
---|
236 | 242 | static inline u32 rockchip_canfd_read(const struct rockchip_canfd *priv, |
---|
.. | .. |
---|
292 | 298 | |
---|
293 | 299 | val = rockchip_canfd_read(rcan, CAN_MODE); |
---|
294 | 300 | val |= WORK_MODE; |
---|
295 | | - if (rcan->mode >= ROCKCHIP_CAN_MODE && rcan->txtorx) |
---|
296 | | - val |= MODE_RXSTX; |
---|
297 | 301 | rockchip_canfd_write(rcan, CAN_MODE, val); |
---|
298 | 302 | |
---|
299 | 303 | netdev_dbg(ndev, "%s MODE=0x%08x\n", __func__, |
---|
.. | .. |
---|
356 | 360 | |
---|
357 | 361 | rockchip_canfd_write(rcan, CAN_DBTP, reg_btp); |
---|
358 | 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; |
---|
359 | 369 | |
---|
360 | 370 | netdev_dbg(ndev, "%s NBTP=0x%08x, DBTP=0x%08x, TDCR=0x%08x\n", __func__, |
---|
361 | 371 | rockchip_canfd_read(rcan, CAN_NBTP), |
---|
.. | .. |
---|
427 | 437 | if (rcan->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) |
---|
428 | 438 | val |= MODE_SELF_TEST | MODE_LBACK; |
---|
429 | 439 | |
---|
430 | | - val |= MODE_AUTO_RETX; |
---|
| 440 | + /* Listen-only mode */ |
---|
| 441 | + if (rcan->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) |
---|
| 442 | + val |= MODE_SILENT; |
---|
431 | 443 | |
---|
432 | 444 | rockchip_canfd_write(rcan, CAN_MODE, val); |
---|
433 | 445 | |
---|
.. | .. |
---|
488 | 500 | { |
---|
489 | 501 | struct rockchip_canfd *rcan = |
---|
490 | 502 | container_of(work, struct rockchip_canfd, tx_err_work.work); |
---|
491 | | - u32 mode, err_code, id; |
---|
| 503 | + u32 mode, err_code; |
---|
492 | 504 | |
---|
493 | | - id = rockchip_canfd_read(rcan, CAN_TXID); |
---|
| 505 | + mode = rockchip_canfd_read(rcan, CAN_MODE); |
---|
494 | 506 | err_code = rockchip_canfd_read(rcan, CAN_ERR_CODE); |
---|
495 | | - if (err_code & 0x1fe0000) { |
---|
496 | | - mode = rockchip_canfd_read(rcan, CAN_MODE); |
---|
| 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 { |
---|
497 | 515 | rockchip_canfd_write(rcan, CAN_MODE, 0); |
---|
498 | 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); |
---|
499 | 519 | rockchip_canfd_write(rcan, CAN_CMD, CAN_TX0_REQ); |
---|
500 | | - schedule_delayed_work(&rcan->tx_err_work, 1); |
---|
501 | | - } else if (rcan->txtorx && rcan->mode >= ROCKCHIP_CAN_MODE && id & CAN_EFF_FLAG) { |
---|
502 | | - schedule_delayed_work(&rcan->tx_err_work, 1); |
---|
| 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)); |
---|
503 | 523 | } |
---|
504 | 524 | } |
---|
505 | 525 | |
---|
.. | .. |
---|
552 | 572 | dlc |= TX_FD_BRS_ENABLE; |
---|
553 | 573 | } |
---|
554 | 574 | |
---|
555 | | - if (!rcan->txtorx && rcan->mode >= ROCKCHIP_CAN_MODE && cf->can_id & CAN_EFF_FLAG) { |
---|
| 575 | + if (rcan->txtorx && rcan->mode <= ROCKCHIP_RK3568_CAN_MODE && cf->can_id & CAN_EFF_FLAG) |
---|
| 576 | + rockchip_canfd_write(rcan, CAN_MODE, |
---|
| 577 | + rockchip_canfd_read(rcan, CAN_MODE) | MODE_RXSTX); |
---|
| 578 | + else |
---|
| 579 | + rockchip_canfd_write(rcan, CAN_MODE, |
---|
| 580 | + rockchip_canfd_read(rcan, CAN_MODE) & (~MODE_RXSTX)); |
---|
| 581 | + |
---|
| 582 | + if (!rcan->txtorx && rcan->mode <= ROCKCHIP_RK3568_CAN_MODE && cf->can_id & CAN_EFF_FLAG) { |
---|
556 | 583 | /* Two frames are sent consecutively. |
---|
557 | 584 | * Before the first frame is tx finished, |
---|
558 | 585 | * the register of the second frame is configured. |
---|
.. | .. |
---|
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, CAN_TX1_REQ); |
---|
587 | | - |
---|
588 | | - if (rcan->txtorx && rcan->mode >= ROCKCHIP_CAN_MODE && cf->can_id & CAN_EFF_FLAG) |
---|
589 | | - schedule_delayed_work(&rcan->tx_err_work, 1); |
---|
590 | | - |
---|
591 | 612 | can_put_echo_skb(skb, ndev, 0); |
---|
592 | | - |
---|
| 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)); |
---|
593 | 619 | return NETDEV_TX_OK; |
---|
594 | 620 | } |
---|
595 | 621 | |
---|
.. | .. |
---|
602 | 628 | u32 id_rockchip_canfd, dlc; |
---|
603 | 629 | int i = 0; |
---|
604 | 630 | u32 __maybe_unused ts, ret; |
---|
605 | | - u32 data[16] = {0}; |
---|
| 631 | + u32 data[16]; |
---|
606 | 632 | |
---|
607 | 633 | dlc = rockchip_canfd_read(rcan, CAN_RXFRD); |
---|
608 | 634 | id_rockchip_canfd = rockchip_canfd_read(rcan, CAN_RXFRD); |
---|
609 | 635 | ts = rockchip_canfd_read(rcan, CAN_RXFRD); |
---|
610 | | - for (i = 0; i < 16; i++) |
---|
| 636 | + for (i = 0; i < ARRAY_SIZE(data); i++) |
---|
611 | 637 | data[i] = rockchip_canfd_read(rcan, CAN_RXFRD); |
---|
612 | 638 | |
---|
613 | | - if (rcan->mode >= ROCKCHIP_CAN_MODE) { |
---|
| 639 | + if (rcan->mode <= ROCKCHIP_RK3568_CAN_MODE) { |
---|
614 | 640 | /* may be an empty frame */ |
---|
615 | 641 | if (!dlc && !id_rockchip_canfd) |
---|
616 | 642 | return 1; |
---|
.. | .. |
---|
618 | 644 | if (rcan->txtorx) { |
---|
619 | 645 | if (rockchip_canfd_read(rcan, CAN_TX_CHECK_FIC) & FORMAT_MASK) { |
---|
620 | 646 | ret = rockchip_canfd_read(rcan, CAN_TXID) & CAN_SFF_MASK; |
---|
621 | | - if (id_rockchip_canfd == ret) { |
---|
| 647 | + if ((id_rockchip_canfd == ret) && !(dlc & FORMAT_MASK)) |
---|
622 | 648 | rockchip_canfd_write(rcan, CAN_TX_CHECK_FIC, |
---|
623 | 649 | ts | CAN_TX0_REQ); |
---|
624 | | - return 1; |
---|
625 | | - } |
---|
| 650 | + return 1; |
---|
626 | 651 | } |
---|
627 | 652 | } |
---|
628 | 653 | } |
---|
.. | .. |
---|
675 | 700 | return 1; |
---|
676 | 701 | } |
---|
677 | 702 | |
---|
| 703 | +static int rockchip_canfd_get_rx_fifo_cnt(struct net_device *ndev) |
---|
| 704 | +{ |
---|
| 705 | + struct rockchip_canfd *rcan = netdev_priv(ndev); |
---|
| 706 | + int quota = 0; |
---|
| 707 | + |
---|
| 708 | + if (read_poll_timeout_atomic(rockchip_canfd_read, quota, |
---|
| 709 | + (quota & rcan->rx_fifo_mask) >> rcan->rx_fifo_shift, |
---|
| 710 | + 0, 500000, false, rcan, CAN_RXFC)) |
---|
| 711 | + netdev_dbg(ndev, "Warning: get fifo cnt failed\n"); |
---|
| 712 | + |
---|
| 713 | + quota = (quota & rcan->rx_fifo_mask) >> rcan->rx_fifo_shift; |
---|
| 714 | + |
---|
| 715 | + return quota; |
---|
| 716 | +} |
---|
| 717 | + |
---|
| 718 | +/* rockchip_canfd_rx_poll - Poll routine for rx packets (NAPI) |
---|
| 719 | + * @napi: napi structure pointer |
---|
| 720 | + * @quota: Max number of rx packets to be processed. |
---|
| 721 | + * |
---|
| 722 | + * This is the poll routine for rx part. |
---|
| 723 | + * It will process the packets maximux quota value. |
---|
| 724 | + * |
---|
| 725 | + * Return: number of packets received |
---|
| 726 | + */ |
---|
| 727 | +static int rockchip_canfd_rx_poll(struct napi_struct *napi, int quota) |
---|
| 728 | +{ |
---|
| 729 | + struct net_device *ndev = napi->dev; |
---|
| 730 | + struct rockchip_canfd *rcan = netdev_priv(ndev); |
---|
| 731 | + int work_done = 0; |
---|
| 732 | + |
---|
| 733 | + quota = rockchip_canfd_get_rx_fifo_cnt(ndev); |
---|
| 734 | + if (quota) { |
---|
| 735 | + while (work_done < quota) |
---|
| 736 | + work_done += rockchip_canfd_rx(ndev); |
---|
| 737 | + } |
---|
| 738 | + |
---|
| 739 | + if (work_done) |
---|
| 740 | + can_led_event(ndev, CAN_LED_EVENT_RX); |
---|
| 741 | + |
---|
| 742 | + if (work_done < 6) { |
---|
| 743 | + napi_complete_done(napi, work_done); |
---|
| 744 | + rockchip_canfd_write(rcan, CAN_INT_MASK, 0); |
---|
| 745 | + } |
---|
| 746 | + |
---|
| 747 | + return work_done; |
---|
| 748 | +} |
---|
| 749 | + |
---|
678 | 750 | static int rockchip_canfd_err(struct net_device *ndev, u32 isr) |
---|
679 | 751 | { |
---|
680 | 752 | struct rockchip_canfd *rcan = netdev_priv(ndev); |
---|
.. | .. |
---|
724 | 796 | } |
---|
725 | 797 | |
---|
726 | 798 | if (rcan->can.state >= CAN_STATE_BUS_OFF || |
---|
727 | | - ((sta_reg & 0x20) == 0x20)) |
---|
728 | | - 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 | + } |
---|
729 | 807 | |
---|
730 | 808 | stats->rx_packets++; |
---|
731 | 809 | stats->rx_bytes += cf->can_dlc; |
---|
.. | .. |
---|
740 | 818 | struct rockchip_canfd *rcan = netdev_priv(ndev); |
---|
741 | 819 | struct net_device_stats *stats = &ndev->stats; |
---|
742 | 820 | u32 err_int = ERR_WARN_INT | RX_BUF_OV_INT | PASSIVE_ERR_INT | |
---|
743 | | - TX_LOSTARB_INT | BUS_ERR_INT | BUS_OFF_INT; |
---|
| 821 | + BUS_ERR_INT | BUS_OFF_INT; |
---|
744 | 822 | u32 isr; |
---|
745 | 823 | u32 dlc = 0; |
---|
746 | 824 | u32 quota, work_done = 0; |
---|
747 | 825 | |
---|
748 | 826 | isr = rockchip_canfd_read(rcan, CAN_INT); |
---|
749 | 827 | if (isr & TX_FINISH_INT) { |
---|
| 828 | + cancel_delayed_work(&rcan->tx_err_work); |
---|
750 | 829 | dlc = rockchip_canfd_read(rcan, CAN_TXFIC); |
---|
751 | 830 | /* transmission complete interrupt */ |
---|
752 | 831 | if (dlc & FDF_MASK) |
---|
.. | .. |
---|
754 | 833 | else |
---|
755 | 834 | stats->tx_bytes += (dlc & DLC_MASK); |
---|
756 | 835 | stats->tx_packets++; |
---|
757 | | - if (rcan->txtorx && rcan->mode >= ROCKCHIP_CAN_MODE && dlc & FORMAT_MASK) { |
---|
758 | | - cancel_delayed_work(&rcan->tx_err_work); |
---|
| 836 | + if (rcan->txtorx && rcan->mode <= ROCKCHIP_RK3568_CAN_MODE && dlc & FORMAT_MASK) { |
---|
759 | 837 | rockchip_canfd_write(rcan, CAN_TX_CHECK_FIC, FORMAT_MASK); |
---|
760 | | - quota = (rockchip_canfd_read(rcan, CAN_RXFC) & |
---|
761 | | - rcan->rx_fifo_mask) >> |
---|
762 | | - rcan->rx_fifo_shift; |
---|
| 838 | + quota = rockchip_canfd_get_rx_fifo_cnt(ndev); |
---|
763 | 839 | if (quota) { |
---|
764 | 840 | while (work_done < quota) |
---|
765 | 841 | work_done += rockchip_canfd_rx(ndev); |
---|
.. | .. |
---|
768 | 844 | rockchip_canfd_write(rcan, CAN_CMD, CAN_TX1_REQ); |
---|
769 | 845 | rockchip_canfd_write(rcan, CAN_TX_CHECK_FIC, 0); |
---|
770 | 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"); |
---|
771 | 851 | rockchip_canfd_write(rcan, CAN_CMD, 0); |
---|
772 | 852 | can_get_echo_skb(ndev, 0); |
---|
773 | 853 | netif_wake_queue(ndev); |
---|
.. | .. |
---|
775 | 855 | } |
---|
776 | 856 | |
---|
777 | 857 | if (isr & RX_FINISH_INT) { |
---|
778 | | - quota = (rockchip_canfd_read(rcan, CAN_RXFC) & rcan->rx_fifo_mask) >> |
---|
779 | | - rcan->rx_fifo_shift; |
---|
780 | | - if (quota) { |
---|
781 | | - while (work_done < quota) |
---|
782 | | - work_done += rockchip_canfd_rx(ndev); |
---|
| 858 | + if (rcan->mode == ROCKCHIP_RK3568_CAN_MODE_V2) { |
---|
| 859 | + rockchip_canfd_write(rcan, CAN_INT_MASK, 0x1); |
---|
| 860 | + napi_schedule(&rcan->napi); |
---|
| 861 | + } else { |
---|
| 862 | + work_done = 0; |
---|
| 863 | + quota = (rockchip_canfd_read(rcan, CAN_RXFC) & |
---|
| 864 | + rcan->rx_fifo_mask) >> |
---|
| 865 | + rcan->rx_fifo_shift; |
---|
| 866 | + if (quota) { |
---|
| 867 | + while (work_done < quota) |
---|
| 868 | + work_done += rockchip_canfd_rx(ndev); |
---|
| 869 | + } |
---|
783 | 870 | } |
---|
784 | 871 | } |
---|
785 | 872 | |
---|
.. | .. |
---|
817 | 904 | } |
---|
818 | 905 | |
---|
819 | 906 | can_led_event(ndev, CAN_LED_EVENT_OPEN); |
---|
| 907 | + if (rcan->mode == ROCKCHIP_RK3568_CAN_MODE_V2) |
---|
| 908 | + napi_enable(&rcan->napi); |
---|
820 | 909 | netif_start_queue(ndev); |
---|
821 | 910 | |
---|
822 | 911 | netdev_dbg(ndev, "%s\n", __func__); |
---|
.. | .. |
---|
834 | 923 | struct rockchip_canfd *rcan = netdev_priv(ndev); |
---|
835 | 924 | |
---|
836 | 925 | netif_stop_queue(ndev); |
---|
| 926 | + if (rcan->mode == ROCKCHIP_RK3568_CAN_MODE_V2) |
---|
| 927 | + napi_disable(&rcan->napi); |
---|
837 | 928 | rockchip_canfd_stop(ndev); |
---|
838 | 929 | close_candev(ndev); |
---|
839 | 930 | can_led_event(ndev, CAN_LED_EVENT_STOP); |
---|
.. | .. |
---|
1011 | 1102 | |
---|
1012 | 1103 | rcan->mode = (unsigned long)of_device_get_match_data(&pdev->dev); |
---|
1013 | 1104 | |
---|
| 1105 | + if ((cpu_is_rk3566() || cpu_is_rk3568()) && (rockchip_get_cpu_version() == 3)) |
---|
| 1106 | + rcan->mode = ROCKCHIP_RK3568_CAN_MODE_V2; |
---|
| 1107 | + |
---|
1014 | 1108 | rcan->base = addr; |
---|
1015 | 1109 | rcan->can.clock.freq = clk_get_rate(rcan->clks[0].clk); |
---|
1016 | 1110 | rcan->dev = &pdev->dev; |
---|
.. | .. |
---|
1032 | 1126 | break; |
---|
1033 | 1127 | case ROCKCHIP_CAN_MODE: |
---|
1034 | 1128 | case ROCKCHIP_RK3568_CAN_MODE: |
---|
| 1129 | + case ROCKCHIP_RK3568_CAN_MODE_V2: |
---|
1035 | 1130 | rcan->can.bittiming_const = &rockchip_canfd_bittiming_const; |
---|
1036 | 1131 | rcan->can.do_set_mode = rockchip_canfd_set_mode; |
---|
1037 | 1132 | rcan->can.do_get_berr_counter = rockchip_canfd_get_berr_counter; |
---|
.. | .. |
---|
1056 | 1151 | rcan->tx_invalid, 4)) |
---|
1057 | 1152 | rcan->txtorx = 1; |
---|
1058 | 1153 | |
---|
| 1154 | + if (rcan->mode == ROCKCHIP_RK3568_CAN_MODE_V2) { |
---|
| 1155 | + rcan->txtorx = 0; |
---|
| 1156 | + netif_napi_add(ndev, &rcan->napi, rockchip_canfd_rx_poll, 6); |
---|
| 1157 | + } |
---|
| 1158 | + |
---|
1059 | 1159 | ndev->netdev_ops = &rockchip_canfd_netdev_ops; |
---|
1060 | 1160 | ndev->irq = irq; |
---|
1061 | 1161 | ndev->flags |= IFF_ECHO; |
---|
1062 | 1162 | rcan->can.restart_ms = 1; |
---|
| 1163 | + |
---|
| 1164 | + irq_set_affinity_hint(irq, get_cpu_mask(num_online_cpus() - 1)); |
---|
1063 | 1165 | |
---|
1064 | 1166 | INIT_DELAYED_WORK(&rcan->tx_err_work, rockchip_canfd_tx_err_delay_work); |
---|
1065 | 1167 | |
---|
.. | .. |
---|
1097 | 1199 | static int rockchip_canfd_remove(struct platform_device *pdev) |
---|
1098 | 1200 | { |
---|
1099 | 1201 | struct net_device *ndev = platform_get_drvdata(pdev); |
---|
| 1202 | + struct rockchip_canfd *rcan = netdev_priv(ndev); |
---|
1100 | 1203 | |
---|
1101 | 1204 | unregister_netdev(ndev); |
---|
1102 | 1205 | pm_runtime_disable(&pdev->dev); |
---|
| 1206 | + if (rcan->mode == ROCKCHIP_RK3568_CAN_MODE_V2) |
---|
| 1207 | + netif_napi_del(&rcan->napi); |
---|
1103 | 1208 | free_candev(ndev); |
---|
1104 | 1209 | |
---|
1105 | 1210 | return 0; |
---|
.. | .. |
---|
1117 | 1222 | module_platform_driver(rockchip_canfd_driver); |
---|
1118 | 1223 | |
---|
1119 | 1224 | MODULE_AUTHOR("Elaine Zhang <zhangqing@rock-chips.com>"); |
---|
| 1225 | +MODULE_LICENSE("GPL"); |
---|
1120 | 1226 | MODULE_DESCRIPTION("Rockchip CANFD Drivers"); |
---|