126ad340eSHenning Colliander // SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause 226ad340eSHenning Colliander /* Copyright (C) 2018 KVASER AB, Sweden. All rights reserved. 326ad340eSHenning Colliander * Parts of this driver are based on the following: 4f33ad677SJimmy Assarsson * - Kvaser linux pciefd driver (version 5.42) 526ad340eSHenning Colliander * - PEAK linux canfd driver 626ad340eSHenning Colliander */ 726ad340eSHenning Colliander 8954fb212SJimmy Assarsson #include <linux/bitfield.h> 91b83d0baSJimmy Assarsson #include <linux/can/dev.h> 101b83d0baSJimmy Assarsson #include <linux/device.h> 111b83d0baSJimmy Assarsson #include <linux/ethtool.h> 121b83d0baSJimmy Assarsson #include <linux/iopoll.h> 1326ad340eSHenning Colliander #include <linux/kernel.h> 14c496adafSJimmy Assarsson #include <linux/minmax.h> 1526ad340eSHenning Colliander #include <linux/module.h> 1626ad340eSHenning Colliander #include <linux/netdevice.h> 171b83d0baSJimmy Assarsson #include <linux/pci.h> 181b83d0baSJimmy Assarsson #include <linux/timer.h> 1926ad340eSHenning Colliander 2026ad340eSHenning Colliander MODULE_LICENSE("Dual BSD/GPL"); 2126ad340eSHenning Colliander MODULE_AUTHOR("Kvaser AB <support@kvaser.com>"); 2226ad340eSHenning Colliander MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices"); 2326ad340eSHenning Colliander 2426ad340eSHenning Colliander #define KVASER_PCIEFD_DRV_NAME "kvaser_pciefd" 2526ad340eSHenning Colliander 2626ad340eSHenning Colliander #define KVASER_PCIEFD_WAIT_TIMEOUT msecs_to_jiffies(1000) 2726ad340eSHenning Colliander #define KVASER_PCIEFD_BEC_POLL_FREQ (jiffies + msecs_to_jiffies(200)) 282c470dbbSJimmy Assarsson #define KVASER_PCIEFD_MAX_ERR_REP 256U 292c470dbbSJimmy Assarsson #define KVASER_PCIEFD_CAN_TX_MAX_COUNT 17U 30954fb212SJimmy Assarsson #define KVASER_PCIEFD_MAX_CAN_CHANNELS 4UL 312c470dbbSJimmy Assarsson #define KVASER_PCIEFD_DMA_COUNT 2U 3226ad340eSHenning Colliander 332c470dbbSJimmy Assarsson #define KVASER_PCIEFD_DMA_SIZE (4U * 1024U) 3426ad340eSHenning Colliander 3526ad340eSHenning Colliander #define KVASER_PCIEFD_VENDOR 0x1a07 36c2ad8129SJimmy Assarsson /* Altera based devices */ 37488c07b4SJimmy Assarsson #define KVASER_PCIEFD_4HS_DEVICE_ID 0x000d 38488c07b4SJimmy Assarsson #define KVASER_PCIEFD_2HS_V2_DEVICE_ID 0x000e 39488c07b4SJimmy Assarsson #define KVASER_PCIEFD_HS_V2_DEVICE_ID 0x000f 40488c07b4SJimmy Assarsson #define KVASER_PCIEFD_MINIPCIE_HS_V2_DEVICE_ID 0x0010 41488c07b4SJimmy Assarsson #define KVASER_PCIEFD_MINIPCIE_2HS_V2_DEVICE_ID 0x0011 4226ad340eSHenning Colliander 43f33ad677SJimmy Assarsson /* SmartFusion2 based devices */ 44f33ad677SJimmy Assarsson #define KVASER_PCIEFD_2CAN_V3_DEVICE_ID 0x0012 45f33ad677SJimmy Assarsson #define KVASER_PCIEFD_1CAN_V3_DEVICE_ID 0x0013 46f33ad677SJimmy Assarsson #define KVASER_PCIEFD_4CAN_V2_DEVICE_ID 0x0014 47f33ad677SJimmy Assarsson #define KVASER_PCIEFD_MINIPCIE_2CAN_V3_DEVICE_ID 0x0015 48f33ad677SJimmy Assarsson #define KVASER_PCIEFD_MINIPCIE_1CAN_V3_DEVICE_ID 0x0016 49f33ad677SJimmy Assarsson 50c2ad8129SJimmy Assarsson /* Altera SerDes Enable 64-bit DMA address translation */ 51c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_ALTERA_DMA_64BIT BIT(0) 52c2ad8129SJimmy Assarsson 53f33ad677SJimmy Assarsson /* SmartFusion2 SerDes LSB address translation mask */ 54f33ad677SJimmy Assarsson #define KVASER_PCIEFD_SF2_DMA_LSB_MASK GENMASK(31, 12) 55f33ad677SJimmy Assarsson 5669335013SJimmy Assarsson /* Kvaser KCAN CAN controller registers */ 5769335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_FIFO_REG 0x100 5869335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_FIFO_LAST_REG 0x180 5969335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CTRL_REG 0x2c0 6069335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CMD_REG 0x400 6169335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IEN_REG 0x408 6269335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IRQ_REG 0x410 63f4845741SJimmy Assarsson #define KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG 0x414 6469335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_STAT_REG 0x418 6569335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_MODE_REG 0x41c 6669335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_BTRN_REG 0x420 6769335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_BUS_LOAD_REG 0x424 6869335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_BTRD_REG 0x428 6969335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_PWM_REG 0x430 70c2ad8129SJimmy Assarsson /* System identification and information registers */ 71c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SYSID_VERSION_REG 0x8 72c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SYSID_CANFREQ_REG 0xc 73c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SYSID_BUSFREQ_REG 0x10 74c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SYSID_BUILD_REG 0x14 75c2ad8129SJimmy Assarsson /* Shared receive buffer FIFO registers */ 76c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SRB_FIFO_LAST_REG 0x1f4 77c2ad8129SJimmy Assarsson /* Shared receive buffer registers */ 78c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SRB_CMD_REG 0x0 79c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SRB_IEN_REG 0x04 80c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SRB_IRQ_REG 0x0c 81c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SRB_STAT_REG 0x10 82c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG 0x14 83c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SRB_CTRL_REG 0x18 8469335013SJimmy Assarsson 8569335013SJimmy Assarsson /* System build information fields */ 86954fb212SJimmy Assarsson #define KVASER_PCIEFD_SYSID_VERSION_NR_CHAN_MASK GENMASK(31, 24) 87954fb212SJimmy Assarsson #define KVASER_PCIEFD_SYSID_VERSION_MAJOR_MASK GENMASK(23, 16) 88954fb212SJimmy Assarsson #define KVASER_PCIEFD_SYSID_VERSION_MINOR_MASK GENMASK(7, 0) 89954fb212SJimmy Assarsson #define KVASER_PCIEFD_SYSID_BUILD_SEQ_MASK GENMASK(15, 1) 9026ad340eSHenning Colliander 9126ad340eSHenning Colliander /* Reset DMA buffer 0, 1 and FIFO offset */ 9226ad340eSHenning Colliander #define KVASER_PCIEFD_SRB_CMD_RDB1 BIT(5) 9369335013SJimmy Assarsson #define KVASER_PCIEFD_SRB_CMD_RDB0 BIT(4) 9426ad340eSHenning Colliander #define KVASER_PCIEFD_SRB_CMD_FOR BIT(0) 9526ad340eSHenning Colliander 9626ad340eSHenning Colliander /* DMA underflow, buffer 0 and 1 */ 9726ad340eSHenning Colliander #define KVASER_PCIEFD_SRB_IRQ_DUF1 BIT(13) 9869335013SJimmy Assarsson #define KVASER_PCIEFD_SRB_IRQ_DUF0 BIT(12) 9969335013SJimmy Assarsson /* DMA overflow, buffer 0 and 1 */ 10069335013SJimmy Assarsson #define KVASER_PCIEFD_SRB_IRQ_DOF1 BIT(11) 10169335013SJimmy Assarsson #define KVASER_PCIEFD_SRB_IRQ_DOF0 BIT(10) 10269335013SJimmy Assarsson /* DMA packet done, buffer 0 and 1 */ 10369335013SJimmy Assarsson #define KVASER_PCIEFD_SRB_IRQ_DPD1 BIT(9) 10469335013SJimmy Assarsson #define KVASER_PCIEFD_SRB_IRQ_DPD0 BIT(8) 10526ad340eSHenning Colliander 10669335013SJimmy Assarsson /* Got DMA support */ 10769335013SJimmy Assarsson #define KVASER_PCIEFD_SRB_STAT_DMA BIT(24) 10826ad340eSHenning Colliander /* DMA idle */ 10926ad340eSHenning Colliander #define KVASER_PCIEFD_SRB_STAT_DI BIT(15) 11026ad340eSHenning Colliander 111c589557dSJimmy Assarsson /* SRB current packet level */ 112954fb212SJimmy Assarsson #define KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK GENMASK(7, 0) 113c589557dSJimmy Assarsson 11426ad340eSHenning Colliander /* DMA Enable */ 11526ad340eSHenning Colliander #define KVASER_PCIEFD_SRB_CTRL_DMA_ENABLE BIT(0) 11626ad340eSHenning Colliander 11769335013SJimmy Assarsson /* KCAN CTRL packet types */ 118954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CTRL_TYPE_MASK GENMASK(31, 29) 119954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CTRL_TYPE_EFLUSH 0x4 120954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CTRL_TYPE_EFRAME 0x5 12126ad340eSHenning Colliander 12269335013SJimmy Assarsson /* Command sequence number */ 123954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CMD_SEQ_MASK GENMASK(23, 16) 124f4845741SJimmy Assarsson /* Command bits */ 125f4845741SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CMD_MASK GENMASK(5, 0) 12626ad340eSHenning Colliander /* Abort, flush and reset */ 12726ad340eSHenning Colliander #define KVASER_PCIEFD_KCAN_CMD_AT BIT(1) 12869335013SJimmy Assarsson /* Request status packet */ 12969335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CMD_SRQ BIT(0) 13026ad340eSHenning Colliander 13126ad340eSHenning Colliander /* Transmitter unaligned */ 13226ad340eSHenning Colliander #define KVASER_PCIEFD_KCAN_IRQ_TAL BIT(17) 13369335013SJimmy Assarsson /* Tx FIFO empty */ 13469335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IRQ_TE BIT(16) 13569335013SJimmy Assarsson /* Tx FIFO overflow */ 13669335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IRQ_TOF BIT(15) 13769335013SJimmy Assarsson /* Tx buffer flush done */ 13869335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IRQ_TFD BIT(14) 13969335013SJimmy Assarsson /* Abort done */ 14069335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IRQ_ABD BIT(13) 14169335013SJimmy Assarsson /* Rx FIFO overflow */ 14269335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IRQ_ROF BIT(5) 14369335013SJimmy Assarsson /* FDF bit when controller is in classic CAN mode */ 14469335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IRQ_FDIC BIT(3) 14569335013SJimmy Assarsson /* Bus parameter protection error */ 14669335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IRQ_BPP BIT(2) 14769335013SJimmy Assarsson /* Tx FIFO unaligned end */ 14869335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IRQ_TAE BIT(1) 14969335013SJimmy Assarsson /* Tx FIFO unaligned read */ 15069335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_IRQ_TAR BIT(0) 15126ad340eSHenning Colliander 15269335013SJimmy Assarsson /* Tx FIFO size */ 153954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_TX_NR_PACKETS_MAX_MASK GENMASK(23, 16) 154954fb212SJimmy Assarsson /* Tx FIFO current packet level */ 155954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_TX_NR_PACKETS_CURRENT_MASK GENMASK(7, 0) 15626ad340eSHenning Colliander 15769335013SJimmy Assarsson /* Current status packet sequence number */ 158954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_STAT_SEQNO_MASK GENMASK(31, 24) 15926ad340eSHenning Colliander /* Controller got CAN FD capability */ 16026ad340eSHenning Colliander #define KVASER_PCIEFD_KCAN_STAT_FD BIT(19) 16169335013SJimmy Assarsson /* Controller got one-shot capability */ 16269335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_STAT_CAP BIT(16) 16369335013SJimmy Assarsson /* Controller in reset mode */ 16469335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_STAT_IRM BIT(15) 16569335013SJimmy Assarsson /* Reset mode request */ 16669335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_STAT_RMR BIT(14) 16769335013SJimmy Assarsson /* Bus off */ 16869335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_STAT_BOFF BIT(11) 16969335013SJimmy Assarsson /* Idle state. Controller in reset mode and no abort or flush pending */ 17069335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_STAT_IDLE BIT(10) 17169335013SJimmy Assarsson /* Abort request */ 17269335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_STAT_AR BIT(7) 17369335013SJimmy Assarsson /* Controller is bus off */ 174f4845741SJimmy Assarsson #define KVASER_PCIEFD_KCAN_STAT_BUS_OFF_MASK \ 175f4845741SJimmy Assarsson (KVASER_PCIEFD_KCAN_STAT_AR | KVASER_PCIEFD_KCAN_STAT_BOFF | \ 176f4845741SJimmy Assarsson KVASER_PCIEFD_KCAN_STAT_RMR | KVASER_PCIEFD_KCAN_STAT_IRM) 17726ad340eSHenning Colliander 17826ad340eSHenning Colliander /* Classic CAN mode */ 17926ad340eSHenning Colliander #define KVASER_PCIEFD_KCAN_MODE_CCM BIT(31) 18069335013SJimmy Assarsson /* Active error flag enable. Clear to force error passive */ 18169335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_MODE_EEN BIT(23) 18269335013SJimmy Assarsson /* Acknowledgment packet type */ 18369335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_MODE_APT BIT(20) 18469335013SJimmy Assarsson /* CAN FD non-ISO */ 18569335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_MODE_NIFDEN BIT(15) 18669335013SJimmy Assarsson /* Error packet enable */ 18769335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_MODE_EPEN BIT(12) 18869335013SJimmy Assarsson /* Listen only mode */ 18969335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_MODE_LOM BIT(9) 19069335013SJimmy Assarsson /* Reset mode */ 19169335013SJimmy Assarsson #define KVASER_PCIEFD_KCAN_MODE_RM BIT(8) 19226ad340eSHenning Colliander 19369335013SJimmy Assarsson /* BTRN and BTRD fields */ 194954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_BTRN_TSEG2_MASK GENMASK(30, 26) 195954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_BTRN_TSEG1_MASK GENMASK(25, 17) 196954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_BTRN_SJW_MASK GENMASK(16, 13) 197954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_BTRN_BRP_MASK GENMASK(12, 0) 19826ad340eSHenning Colliander 19969335013SJimmy Assarsson /* PWM Control fields */ 200954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_PWM_TOP_MASK GENMASK(23, 16) 201954fb212SJimmy Assarsson #define KVASER_PCIEFD_KCAN_PWM_TRIGGER_MASK GENMASK(7, 0) 20226ad340eSHenning Colliander 20369335013SJimmy Assarsson /* KCAN packet type IDs */ 204f4845741SJimmy Assarsson #define KVASER_PCIEFD_PACK_TYPE_DATA 0x0 205f4845741SJimmy Assarsson #define KVASER_PCIEFD_PACK_TYPE_ACK 0x1 206f4845741SJimmy Assarsson #define KVASER_PCIEFD_PACK_TYPE_TXRQ 0x2 207f4845741SJimmy Assarsson #define KVASER_PCIEFD_PACK_TYPE_ERROR 0x3 208f4845741SJimmy Assarsson #define KVASER_PCIEFD_PACK_TYPE_EFLUSH_ACK 0x4 209f4845741SJimmy Assarsson #define KVASER_PCIEFD_PACK_TYPE_EFRAME_ACK 0x5 210f4845741SJimmy Assarsson #define KVASER_PCIEFD_PACK_TYPE_ACK_DATA 0x6 211f4845741SJimmy Assarsson #define KVASER_PCIEFD_PACK_TYPE_STATUS 0x8 212f4845741SJimmy Assarsson #define KVASER_PCIEFD_PACK_TYPE_BUS_LOAD 0x9 21326ad340eSHenning Colliander 21469335013SJimmy Assarsson /* Common KCAN packet definitions, second word */ 215954fb212SJimmy Assarsson #define KVASER_PCIEFD_PACKET_TYPE_MASK GENMASK(31, 28) 216954fb212SJimmy Assarsson #define KVASER_PCIEFD_PACKET_CHID_MASK GENMASK(27, 25) 217954fb212SJimmy Assarsson #define KVASER_PCIEFD_PACKET_SEQ_MASK GENMASK(7, 0) 21826ad340eSHenning Colliander 21969335013SJimmy Assarsson /* KCAN Transmit/Receive data packet, first word */ 22026ad340eSHenning Colliander #define KVASER_PCIEFD_RPACKET_IDE BIT(30) 22126ad340eSHenning Colliander #define KVASER_PCIEFD_RPACKET_RTR BIT(29) 222954fb212SJimmy Assarsson #define KVASER_PCIEFD_RPACKET_ID_MASK GENMASK(28, 0) 22369335013SJimmy Assarsson /* KCAN Transmit data packet, second word */ 22426ad340eSHenning Colliander #define KVASER_PCIEFD_TPACKET_AREQ BIT(31) 22569335013SJimmy Assarsson #define KVASER_PCIEFD_TPACKET_SMS BIT(16) 22669335013SJimmy Assarsson /* KCAN Transmit/Receive data packet, second word */ 22769335013SJimmy Assarsson #define KVASER_PCIEFD_RPACKET_FDF BIT(15) 22869335013SJimmy Assarsson #define KVASER_PCIEFD_RPACKET_BRS BIT(14) 22969335013SJimmy Assarsson #define KVASER_PCIEFD_RPACKET_ESI BIT(13) 230954fb212SJimmy Assarsson #define KVASER_PCIEFD_RPACKET_DLC_MASK GENMASK(11, 8) 23126ad340eSHenning Colliander 23269335013SJimmy Assarsson /* KCAN Transmit acknowledge packet, first word */ 23326ad340eSHenning Colliander #define KVASER_PCIEFD_APACKET_NACK BIT(11) 23469335013SJimmy Assarsson #define KVASER_PCIEFD_APACKET_ABL BIT(10) 23569335013SJimmy Assarsson #define KVASER_PCIEFD_APACKET_CT BIT(9) 23669335013SJimmy Assarsson #define KVASER_PCIEFD_APACKET_FLU BIT(8) 23726ad340eSHenning Colliander 23869335013SJimmy Assarsson /* KCAN Status packet, first word */ 23926ad340eSHenning Colliander #define KVASER_PCIEFD_SPACK_RMCD BIT(22) 24069335013SJimmy Assarsson #define KVASER_PCIEFD_SPACK_IRM BIT(21) 24169335013SJimmy Assarsson #define KVASER_PCIEFD_SPACK_IDET BIT(20) 24269335013SJimmy Assarsson #define KVASER_PCIEFD_SPACK_BOFF BIT(16) 243954fb212SJimmy Assarsson #define KVASER_PCIEFD_SPACK_RXERR_MASK GENMASK(15, 8) 244954fb212SJimmy Assarsson #define KVASER_PCIEFD_SPACK_TXERR_MASK GENMASK(7, 0) 24569335013SJimmy Assarsson /* KCAN Status packet, second word */ 24626ad340eSHenning Colliander #define KVASER_PCIEFD_SPACK_EPLR BIT(24) 24769335013SJimmy Assarsson #define KVASER_PCIEFD_SPACK_EWLR BIT(23) 24869335013SJimmy Assarsson #define KVASER_PCIEFD_SPACK_AUTO BIT(21) 24926ad340eSHenning Colliander 25069335013SJimmy Assarsson /* KCAN Error detected packet, second word */ 25136aea60fSJimmy Assarsson #define KVASER_PCIEFD_EPACK_DIR_TX BIT(0) 25236aea60fSJimmy Assarsson 253c2ad8129SJimmy Assarsson /* Macros for calculating addresses of registers */ 254c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_GET_BLOCK_ADDR(pcie, block) \ 255c2ad8129SJimmy Assarsson ((pcie)->reg_base + (pcie)->driver_data->address_offset->block) 256c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_PCI_IEN_ADDR(pcie) \ 257c2ad8129SJimmy Assarsson (KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), pci_ien)) 258c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_PCI_IRQ_ADDR(pcie) \ 259c2ad8129SJimmy Assarsson (KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), pci_irq)) 260c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SERDES_ADDR(pcie) \ 261c2ad8129SJimmy Assarsson (KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), serdes)) 262c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SYSID_ADDR(pcie) \ 263c2ad8129SJimmy Assarsson (KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), sysid)) 264c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_LOOPBACK_ADDR(pcie) \ 265c2ad8129SJimmy Assarsson (KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), loopback)) 266c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SRB_FIFO_ADDR(pcie) \ 267c2ad8129SJimmy Assarsson (KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), kcan_srb_fifo)) 268c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_SRB_ADDR(pcie) \ 269c2ad8129SJimmy Assarsson (KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), kcan_srb)) 270c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CH0_ADDR(pcie) \ 271c2ad8129SJimmy Assarsson (KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), kcan_ch0)) 272c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CH1_ADDR(pcie) \ 273c2ad8129SJimmy Assarsson (KVASER_PCIEFD_GET_BLOCK_ADDR((pcie), kcan_ch1)) 274c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CHANNEL_SPAN(pcie) \ 275c2ad8129SJimmy Assarsson (KVASER_PCIEFD_KCAN_CH1_ADDR((pcie)) - KVASER_PCIEFD_KCAN_CH0_ADDR((pcie))) 276c2ad8129SJimmy Assarsson #define KVASER_PCIEFD_KCAN_CHX_ADDR(pcie, i) \ 277c2ad8129SJimmy Assarsson (KVASER_PCIEFD_KCAN_CH0_ADDR((pcie)) + (i) * KVASER_PCIEFD_KCAN_CHANNEL_SPAN((pcie))) 278c2ad8129SJimmy Assarsson 27926ad340eSHenning Colliander struct kvaser_pciefd; 280c2ad8129SJimmy Assarsson static void kvaser_pciefd_write_dma_map_altera(struct kvaser_pciefd *pcie, 281c2ad8129SJimmy Assarsson dma_addr_t addr, int index); 282f33ad677SJimmy Assarsson static void kvaser_pciefd_write_dma_map_sf2(struct kvaser_pciefd *pcie, 283f33ad677SJimmy Assarsson dma_addr_t addr, int index); 284c2ad8129SJimmy Assarsson 285c2ad8129SJimmy Assarsson struct kvaser_pciefd_address_offset { 286c2ad8129SJimmy Assarsson u32 serdes; 287c2ad8129SJimmy Assarsson u32 pci_ien; 288c2ad8129SJimmy Assarsson u32 pci_irq; 289c2ad8129SJimmy Assarsson u32 sysid; 290c2ad8129SJimmy Assarsson u32 loopback; 291c2ad8129SJimmy Assarsson u32 kcan_srb_fifo; 292c2ad8129SJimmy Assarsson u32 kcan_srb; 293c2ad8129SJimmy Assarsson u32 kcan_ch0; 294c2ad8129SJimmy Assarsson u32 kcan_ch1; 295c2ad8129SJimmy Assarsson }; 296c2ad8129SJimmy Assarsson 297c2ad8129SJimmy Assarsson struct kvaser_pciefd_dev_ops { 298c2ad8129SJimmy Assarsson void (*kvaser_pciefd_write_dma_map)(struct kvaser_pciefd *pcie, 299c2ad8129SJimmy Assarsson dma_addr_t addr, int index); 300c2ad8129SJimmy Assarsson }; 301c2ad8129SJimmy Assarsson 302c2ad8129SJimmy Assarsson struct kvaser_pciefd_irq_mask { 303c2ad8129SJimmy Assarsson u32 kcan_rx0; 304c2ad8129SJimmy Assarsson u32 kcan_tx[KVASER_PCIEFD_MAX_CAN_CHANNELS]; 305c2ad8129SJimmy Assarsson u32 all; 306c2ad8129SJimmy Assarsson }; 307c2ad8129SJimmy Assarsson 308c2ad8129SJimmy Assarsson struct kvaser_pciefd_driver_data { 309c2ad8129SJimmy Assarsson const struct kvaser_pciefd_address_offset *address_offset; 310c2ad8129SJimmy Assarsson const struct kvaser_pciefd_irq_mask *irq_mask; 311c2ad8129SJimmy Assarsson const struct kvaser_pciefd_dev_ops *ops; 312c2ad8129SJimmy Assarsson }; 313c2ad8129SJimmy Assarsson 314c2ad8129SJimmy Assarsson static const struct kvaser_pciefd_address_offset kvaser_pciefd_altera_address_offset = { 315c2ad8129SJimmy Assarsson .serdes = 0x1000, 316c2ad8129SJimmy Assarsson .pci_ien = 0x50, 317c2ad8129SJimmy Assarsson .pci_irq = 0x40, 318c2ad8129SJimmy Assarsson .sysid = 0x1f020, 319c2ad8129SJimmy Assarsson .loopback = 0x1f000, 320c2ad8129SJimmy Assarsson .kcan_srb_fifo = 0x1f200, 321c2ad8129SJimmy Assarsson .kcan_srb = 0x1f400, 322c2ad8129SJimmy Assarsson .kcan_ch0 = 0x10000, 323c2ad8129SJimmy Assarsson .kcan_ch1 = 0x11000, 324c2ad8129SJimmy Assarsson }; 325c2ad8129SJimmy Assarsson 326f33ad677SJimmy Assarsson static const struct kvaser_pciefd_address_offset kvaser_pciefd_sf2_address_offset = { 327f33ad677SJimmy Assarsson .serdes = 0x280c8, 328f33ad677SJimmy Assarsson .pci_ien = 0x102004, 329f33ad677SJimmy Assarsson .pci_irq = 0x102008, 330f33ad677SJimmy Assarsson .sysid = 0x100000, 331f33ad677SJimmy Assarsson .loopback = 0x103000, 332f33ad677SJimmy Assarsson .kcan_srb_fifo = 0x120000, 333f33ad677SJimmy Assarsson .kcan_srb = 0x121000, 334f33ad677SJimmy Assarsson .kcan_ch0 = 0x140000, 335f33ad677SJimmy Assarsson .kcan_ch1 = 0x142000, 336f33ad677SJimmy Assarsson }; 337f33ad677SJimmy Assarsson 338c2ad8129SJimmy Assarsson static const struct kvaser_pciefd_irq_mask kvaser_pciefd_altera_irq_mask = { 339c2ad8129SJimmy Assarsson .kcan_rx0 = BIT(4), 340c2ad8129SJimmy Assarsson .kcan_tx = { BIT(0), BIT(1), BIT(2), BIT(3) }, 341c2ad8129SJimmy Assarsson .all = GENMASK(4, 0), 342c2ad8129SJimmy Assarsson }; 343c2ad8129SJimmy Assarsson 344f33ad677SJimmy Assarsson static const struct kvaser_pciefd_irq_mask kvaser_pciefd_sf2_irq_mask = { 345f33ad677SJimmy Assarsson .kcan_rx0 = BIT(4), 346f33ad677SJimmy Assarsson .kcan_tx = { BIT(16), BIT(17), BIT(18), BIT(19) }, 347f33ad677SJimmy Assarsson .all = GENMASK(19, 16) | BIT(4), 348f33ad677SJimmy Assarsson }; 349f33ad677SJimmy Assarsson 350c2ad8129SJimmy Assarsson static const struct kvaser_pciefd_dev_ops kvaser_pciefd_altera_dev_ops = { 351c2ad8129SJimmy Assarsson .kvaser_pciefd_write_dma_map = kvaser_pciefd_write_dma_map_altera, 352c2ad8129SJimmy Assarsson }; 353c2ad8129SJimmy Assarsson 354f33ad677SJimmy Assarsson static const struct kvaser_pciefd_dev_ops kvaser_pciefd_sf2_dev_ops = { 355f33ad677SJimmy Assarsson .kvaser_pciefd_write_dma_map = kvaser_pciefd_write_dma_map_sf2, 356f33ad677SJimmy Assarsson }; 357f33ad677SJimmy Assarsson 358c2ad8129SJimmy Assarsson static const struct kvaser_pciefd_driver_data kvaser_pciefd_altera_driver_data = { 359c2ad8129SJimmy Assarsson .address_offset = &kvaser_pciefd_altera_address_offset, 360c2ad8129SJimmy Assarsson .irq_mask = &kvaser_pciefd_altera_irq_mask, 361c2ad8129SJimmy Assarsson .ops = &kvaser_pciefd_altera_dev_ops, 362c2ad8129SJimmy Assarsson }; 36326ad340eSHenning Colliander 364f33ad677SJimmy Assarsson static const struct kvaser_pciefd_driver_data kvaser_pciefd_sf2_driver_data = { 365f33ad677SJimmy Assarsson .address_offset = &kvaser_pciefd_sf2_address_offset, 366f33ad677SJimmy Assarsson .irq_mask = &kvaser_pciefd_sf2_irq_mask, 367f33ad677SJimmy Assarsson .ops = &kvaser_pciefd_sf2_dev_ops, 368f33ad677SJimmy Assarsson }; 369f33ad677SJimmy Assarsson 37026ad340eSHenning Colliander struct kvaser_pciefd_can { 37126ad340eSHenning Colliander struct can_priv can; 37226ad340eSHenning Colliander struct kvaser_pciefd *kv_pcie; 37326ad340eSHenning Colliander void __iomem *reg_base; 37426ad340eSHenning Colliander struct can_berr_counter bec; 37526ad340eSHenning Colliander u8 cmd_seq; 37626ad340eSHenning Colliander int err_rep_cnt; 37726ad340eSHenning Colliander int echo_idx; 37826ad340eSHenning Colliander spinlock_t lock; /* Locks sensitive registers (e.g. MODE) */ 37926ad340eSHenning Colliander spinlock_t echo_lock; /* Locks the message echo buffer */ 38026ad340eSHenning Colliander struct timer_list bec_poll_timer; 38126ad340eSHenning Colliander struct completion start_comp, flush_comp; 38226ad340eSHenning Colliander }; 38326ad340eSHenning Colliander 38426ad340eSHenning Colliander struct kvaser_pciefd { 38526ad340eSHenning Colliander struct pci_dev *pci; 38626ad340eSHenning Colliander void __iomem *reg_base; 38726ad340eSHenning Colliander struct kvaser_pciefd_can *can[KVASER_PCIEFD_MAX_CAN_CHANNELS]; 388c2ad8129SJimmy Assarsson const struct kvaser_pciefd_driver_data *driver_data; 38926ad340eSHenning Colliander void *dma_data[KVASER_PCIEFD_DMA_COUNT]; 39026ad340eSHenning Colliander u8 nr_channels; 391ec44dd57SChrister Beskow u32 bus_freq; 39226ad340eSHenning Colliander u32 freq; 39326ad340eSHenning Colliander u32 freq_to_ticks_div; 39426ad340eSHenning Colliander }; 39526ad340eSHenning Colliander 39626ad340eSHenning Colliander struct kvaser_pciefd_rx_packet { 39726ad340eSHenning Colliander u32 header[2]; 39826ad340eSHenning Colliander u64 timestamp; 39926ad340eSHenning Colliander }; 40026ad340eSHenning Colliander 40126ad340eSHenning Colliander struct kvaser_pciefd_tx_packet { 40226ad340eSHenning Colliander u32 header[2]; 40326ad340eSHenning Colliander u8 data[64]; 40426ad340eSHenning Colliander }; 40526ad340eSHenning Colliander 40626ad340eSHenning Colliander static const struct can_bittiming_const kvaser_pciefd_bittiming_const = { 40726ad340eSHenning Colliander .name = KVASER_PCIEFD_DRV_NAME, 40826ad340eSHenning Colliander .tseg1_min = 1, 409470e14c0SJimmy Assarsson .tseg1_max = 512, 41026ad340eSHenning Colliander .tseg2_min = 1, 41126ad340eSHenning Colliander .tseg2_max = 32, 41226ad340eSHenning Colliander .sjw_max = 16, 41326ad340eSHenning Colliander .brp_min = 1, 414470e14c0SJimmy Assarsson .brp_max = 8192, 41526ad340eSHenning Colliander .brp_inc = 1, 41626ad340eSHenning Colliander }; 41726ad340eSHenning Colliander 41826ad340eSHenning Colliander static struct pci_device_id kvaser_pciefd_id_table[] = { 419488c07b4SJimmy Assarsson { 420488c07b4SJimmy Assarsson PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_4HS_DEVICE_ID), 421c2ad8129SJimmy Assarsson .driver_data = (kernel_ulong_t)&kvaser_pciefd_altera_driver_data, 422488c07b4SJimmy Assarsson }, 423488c07b4SJimmy Assarsson { 424488c07b4SJimmy Assarsson PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_2HS_V2_DEVICE_ID), 425c2ad8129SJimmy Assarsson .driver_data = (kernel_ulong_t)&kvaser_pciefd_altera_driver_data, 426488c07b4SJimmy Assarsson }, 427488c07b4SJimmy Assarsson { 428488c07b4SJimmy Assarsson PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_HS_V2_DEVICE_ID), 429c2ad8129SJimmy Assarsson .driver_data = (kernel_ulong_t)&kvaser_pciefd_altera_driver_data, 430488c07b4SJimmy Assarsson }, 431488c07b4SJimmy Assarsson { 432488c07b4SJimmy Assarsson PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_HS_V2_DEVICE_ID), 433c2ad8129SJimmy Assarsson .driver_data = (kernel_ulong_t)&kvaser_pciefd_altera_driver_data, 434488c07b4SJimmy Assarsson }, 435488c07b4SJimmy Assarsson { 436488c07b4SJimmy Assarsson PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_2HS_V2_DEVICE_ID), 437c2ad8129SJimmy Assarsson .driver_data = (kernel_ulong_t)&kvaser_pciefd_altera_driver_data, 438488c07b4SJimmy Assarsson }, 439488c07b4SJimmy Assarsson { 440f33ad677SJimmy Assarsson PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_2CAN_V3_DEVICE_ID), 441f33ad677SJimmy Assarsson .driver_data = (kernel_ulong_t)&kvaser_pciefd_sf2_driver_data, 442f33ad677SJimmy Assarsson }, 443f33ad677SJimmy Assarsson { 444f33ad677SJimmy Assarsson PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_1CAN_V3_DEVICE_ID), 445f33ad677SJimmy Assarsson .driver_data = (kernel_ulong_t)&kvaser_pciefd_sf2_driver_data, 446f33ad677SJimmy Assarsson }, 447f33ad677SJimmy Assarsson { 448f33ad677SJimmy Assarsson PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_4CAN_V2_DEVICE_ID), 449f33ad677SJimmy Assarsson .driver_data = (kernel_ulong_t)&kvaser_pciefd_sf2_driver_data, 450f33ad677SJimmy Assarsson }, 451f33ad677SJimmy Assarsson { 452f33ad677SJimmy Assarsson PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_2CAN_V3_DEVICE_ID), 453f33ad677SJimmy Assarsson .driver_data = (kernel_ulong_t)&kvaser_pciefd_sf2_driver_data, 454f33ad677SJimmy Assarsson }, 455f33ad677SJimmy Assarsson { 456f33ad677SJimmy Assarsson PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_1CAN_V3_DEVICE_ID), 457f33ad677SJimmy Assarsson .driver_data = (kernel_ulong_t)&kvaser_pciefd_sf2_driver_data, 458f33ad677SJimmy Assarsson }, 459f33ad677SJimmy Assarsson { 460488c07b4SJimmy Assarsson 0, 461488c07b4SJimmy Assarsson }, 46226ad340eSHenning Colliander }; 46326ad340eSHenning Colliander MODULE_DEVICE_TABLE(pci, kvaser_pciefd_id_table); 46426ad340eSHenning Colliander 465f4845741SJimmy Assarsson static inline void kvaser_pciefd_send_kcan_cmd(struct kvaser_pciefd_can *can, u32 cmd) 46626ad340eSHenning Colliander { 467f4845741SJimmy Assarsson iowrite32(FIELD_PREP(KVASER_PCIEFD_KCAN_CMD_MASK, cmd) | 468f4845741SJimmy Assarsson FIELD_PREP(KVASER_PCIEFD_KCAN_CMD_SEQ_MASK, ++can->cmd_seq), 469f4845741SJimmy Assarsson can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG); 470f4845741SJimmy Assarsson } 47126ad340eSHenning Colliander 472f4845741SJimmy Assarsson static inline void kvaser_pciefd_request_status(struct kvaser_pciefd_can *can) 473f4845741SJimmy Assarsson { 474f4845741SJimmy Assarsson kvaser_pciefd_send_kcan_cmd(can, KVASER_PCIEFD_KCAN_CMD_SRQ); 475f4845741SJimmy Assarsson } 476f4845741SJimmy Assarsson 477f4845741SJimmy Assarsson static inline void kvaser_pciefd_abort_flush_reset(struct kvaser_pciefd_can *can) 478f4845741SJimmy Assarsson { 479f4845741SJimmy Assarsson kvaser_pciefd_send_kcan_cmd(can, KVASER_PCIEFD_KCAN_CMD_AT); 48026ad340eSHenning Colliander } 48126ad340eSHenning Colliander 48226ad340eSHenning Colliander static void kvaser_pciefd_enable_err_gen(struct kvaser_pciefd_can *can) 48326ad340eSHenning Colliander { 48426ad340eSHenning Colliander u32 mode; 48526ad340eSHenning Colliander unsigned long irq; 48626ad340eSHenning Colliander 48726ad340eSHenning Colliander spin_lock_irqsave(&can->lock, irq); 48826ad340eSHenning Colliander mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); 48926ad340eSHenning Colliander if (!(mode & KVASER_PCIEFD_KCAN_MODE_EPEN)) { 49026ad340eSHenning Colliander mode |= KVASER_PCIEFD_KCAN_MODE_EPEN; 49126ad340eSHenning Colliander iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); 49226ad340eSHenning Colliander } 49326ad340eSHenning Colliander spin_unlock_irqrestore(&can->lock, irq); 49426ad340eSHenning Colliander } 49526ad340eSHenning Colliander 49626ad340eSHenning Colliander static void kvaser_pciefd_disable_err_gen(struct kvaser_pciefd_can *can) 49726ad340eSHenning Colliander { 49826ad340eSHenning Colliander u32 mode; 49926ad340eSHenning Colliander unsigned long irq; 50026ad340eSHenning Colliander 50126ad340eSHenning Colliander spin_lock_irqsave(&can->lock, irq); 50226ad340eSHenning Colliander mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); 50326ad340eSHenning Colliander mode &= ~KVASER_PCIEFD_KCAN_MODE_EPEN; 50426ad340eSHenning Colliander iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); 50526ad340eSHenning Colliander spin_unlock_irqrestore(&can->lock, irq); 50626ad340eSHenning Colliander } 50726ad340eSHenning Colliander 50824aecf55SJimmy Assarsson static void kvaser_pciefd_set_tx_irq(struct kvaser_pciefd_can *can) 50926ad340eSHenning Colliander { 51026ad340eSHenning Colliander u32 msk; 51126ad340eSHenning Colliander 51226ad340eSHenning Colliander msk = KVASER_PCIEFD_KCAN_IRQ_TE | KVASER_PCIEFD_KCAN_IRQ_ROF | 51326ad340eSHenning Colliander KVASER_PCIEFD_KCAN_IRQ_TOF | KVASER_PCIEFD_KCAN_IRQ_ABD | 51426ad340eSHenning Colliander KVASER_PCIEFD_KCAN_IRQ_TAE | KVASER_PCIEFD_KCAN_IRQ_TAL | 51526ad340eSHenning Colliander KVASER_PCIEFD_KCAN_IRQ_FDIC | KVASER_PCIEFD_KCAN_IRQ_BPP | 516262d7a52SJimmy Assarsson KVASER_PCIEFD_KCAN_IRQ_TAR; 51726ad340eSHenning Colliander 51826ad340eSHenning Colliander iowrite32(msk, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); 51926ad340eSHenning Colliander } 52026ad340eSHenning Colliander 5212d55e9f9SJimmy Assarsson static inline void kvaser_pciefd_set_skb_timestamp(const struct kvaser_pciefd *pcie, 5222d55e9f9SJimmy Assarsson struct sk_buff *skb, u64 timestamp) 5232d55e9f9SJimmy Assarsson { 5242d55e9f9SJimmy Assarsson skb_hwtstamps(skb)->hwtstamp = 5252d55e9f9SJimmy Assarsson ns_to_ktime(div_u64(timestamp * 1000, pcie->freq_to_ticks_div)); 5262d55e9f9SJimmy Assarsson } 5272d55e9f9SJimmy Assarsson 52826ad340eSHenning Colliander static void kvaser_pciefd_setup_controller(struct kvaser_pciefd_can *can) 52926ad340eSHenning Colliander { 53026ad340eSHenning Colliander u32 mode; 53126ad340eSHenning Colliander unsigned long irq; 53226ad340eSHenning Colliander 53326ad340eSHenning Colliander spin_lock_irqsave(&can->lock, irq); 53426ad340eSHenning Colliander mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); 53526ad340eSHenning Colliander if (can->can.ctrlmode & CAN_CTRLMODE_FD) { 53626ad340eSHenning Colliander mode &= ~KVASER_PCIEFD_KCAN_MODE_CCM; 53726ad340eSHenning Colliander if (can->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO) 53826ad340eSHenning Colliander mode |= KVASER_PCIEFD_KCAN_MODE_NIFDEN; 53926ad340eSHenning Colliander else 54026ad340eSHenning Colliander mode &= ~KVASER_PCIEFD_KCAN_MODE_NIFDEN; 54126ad340eSHenning Colliander } else { 54226ad340eSHenning Colliander mode |= KVASER_PCIEFD_KCAN_MODE_CCM; 54326ad340eSHenning Colliander mode &= ~KVASER_PCIEFD_KCAN_MODE_NIFDEN; 54426ad340eSHenning Colliander } 54526ad340eSHenning Colliander 54626ad340eSHenning Colliander if (can->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) 54726ad340eSHenning Colliander mode |= KVASER_PCIEFD_KCAN_MODE_LOM; 548bf7ac55eSJimmy Assarsson else 549bf7ac55eSJimmy Assarsson mode &= ~KVASER_PCIEFD_KCAN_MODE_LOM; 55026ad340eSHenning Colliander mode |= KVASER_PCIEFD_KCAN_MODE_EEN; 55126ad340eSHenning Colliander mode |= KVASER_PCIEFD_KCAN_MODE_EPEN; 55226ad340eSHenning Colliander /* Use ACK packet type */ 55326ad340eSHenning Colliander mode &= ~KVASER_PCIEFD_KCAN_MODE_APT; 55426ad340eSHenning Colliander mode &= ~KVASER_PCIEFD_KCAN_MODE_RM; 55526ad340eSHenning Colliander iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); 55626ad340eSHenning Colliander 55726ad340eSHenning Colliander spin_unlock_irqrestore(&can->lock, irq); 55826ad340eSHenning Colliander } 55926ad340eSHenning Colliander 56026ad340eSHenning Colliander static void kvaser_pciefd_start_controller_flush(struct kvaser_pciefd_can *can) 56126ad340eSHenning Colliander { 56226ad340eSHenning Colliander u32 status; 56326ad340eSHenning Colliander unsigned long irq; 56426ad340eSHenning Colliander 56526ad340eSHenning Colliander spin_lock_irqsave(&can->lock, irq); 566f4845741SJimmy Assarsson iowrite32(GENMASK(31, 0), can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); 567262d7a52SJimmy Assarsson iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD, 56826ad340eSHenning Colliander can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); 56926ad340eSHenning Colliander status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG); 57026ad340eSHenning Colliander if (status & KVASER_PCIEFD_KCAN_STAT_IDLE) { 57126ad340eSHenning Colliander /* If controller is already idle, run abort, flush and reset */ 572f4845741SJimmy Assarsson kvaser_pciefd_abort_flush_reset(can); 57326ad340eSHenning Colliander } else if (!(status & KVASER_PCIEFD_KCAN_STAT_RMR)) { 57426ad340eSHenning Colliander u32 mode; 57526ad340eSHenning Colliander 57626ad340eSHenning Colliander /* Put controller in reset mode */ 57726ad340eSHenning Colliander mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); 57826ad340eSHenning Colliander mode |= KVASER_PCIEFD_KCAN_MODE_RM; 57926ad340eSHenning Colliander iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); 58026ad340eSHenning Colliander } 58126ad340eSHenning Colliander spin_unlock_irqrestore(&can->lock, irq); 58226ad340eSHenning Colliander } 58326ad340eSHenning Colliander 58426ad340eSHenning Colliander static int kvaser_pciefd_bus_on(struct kvaser_pciefd_can *can) 58526ad340eSHenning Colliander { 58626ad340eSHenning Colliander u32 mode; 58726ad340eSHenning Colliander unsigned long irq; 58826ad340eSHenning Colliander 58926ad340eSHenning Colliander del_timer(&can->bec_poll_timer); 59026ad340eSHenning Colliander if (!completion_done(&can->flush_comp)) 59126ad340eSHenning Colliander kvaser_pciefd_start_controller_flush(can); 59226ad340eSHenning Colliander 59326ad340eSHenning Colliander if (!wait_for_completion_timeout(&can->flush_comp, 59426ad340eSHenning Colliander KVASER_PCIEFD_WAIT_TIMEOUT)) { 59526ad340eSHenning Colliander netdev_err(can->can.dev, "Timeout during bus on flush\n"); 59626ad340eSHenning Colliander return -ETIMEDOUT; 59726ad340eSHenning Colliander } 59826ad340eSHenning Colliander 59926ad340eSHenning Colliander spin_lock_irqsave(&can->lock, irq); 60026ad340eSHenning Colliander iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); 601f4845741SJimmy Assarsson iowrite32(GENMASK(31, 0), can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); 602262d7a52SJimmy Assarsson iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD, 60326ad340eSHenning Colliander can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); 60426ad340eSHenning Colliander mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); 60526ad340eSHenning Colliander mode &= ~KVASER_PCIEFD_KCAN_MODE_RM; 60626ad340eSHenning Colliander iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); 60726ad340eSHenning Colliander spin_unlock_irqrestore(&can->lock, irq); 60826ad340eSHenning Colliander 60926ad340eSHenning Colliander if (!wait_for_completion_timeout(&can->start_comp, 61026ad340eSHenning Colliander KVASER_PCIEFD_WAIT_TIMEOUT)) { 61126ad340eSHenning Colliander netdev_err(can->can.dev, "Timeout during bus on reset\n"); 61226ad340eSHenning Colliander return -ETIMEDOUT; 61326ad340eSHenning Colliander } 61426ad340eSHenning Colliander /* Reset interrupt handling */ 61526ad340eSHenning Colliander iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); 616f4845741SJimmy Assarsson iowrite32(GENMASK(31, 0), can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); 61726ad340eSHenning Colliander 61826ad340eSHenning Colliander kvaser_pciefd_set_tx_irq(can); 61926ad340eSHenning Colliander kvaser_pciefd_setup_controller(can); 62026ad340eSHenning Colliander can->can.state = CAN_STATE_ERROR_ACTIVE; 62126ad340eSHenning Colliander netif_wake_queue(can->can.dev); 62226ad340eSHenning Colliander can->bec.txerr = 0; 62326ad340eSHenning Colliander can->bec.rxerr = 0; 62426ad340eSHenning Colliander can->err_rep_cnt = 0; 62526ad340eSHenning Colliander 62626ad340eSHenning Colliander return 0; 62726ad340eSHenning Colliander } 62826ad340eSHenning Colliander 62926ad340eSHenning Colliander static void kvaser_pciefd_pwm_stop(struct kvaser_pciefd_can *can) 63026ad340eSHenning Colliander { 6311910cd88SChrister Beskow u8 top; 63226ad340eSHenning Colliander u32 pwm_ctrl; 63326ad340eSHenning Colliander unsigned long irq; 63426ad340eSHenning Colliander 63526ad340eSHenning Colliander spin_lock_irqsave(&can->lock, irq); 63626ad340eSHenning Colliander pwm_ctrl = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG); 637954fb212SJimmy Assarsson top = FIELD_GET(KVASER_PCIEFD_KCAN_PWM_TOP_MASK, pwm_ctrl); 6381910cd88SChrister Beskow /* Set duty cycle to zero */ 639954fb212SJimmy Assarsson pwm_ctrl |= FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TRIGGER_MASK, top); 64026ad340eSHenning Colliander iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG); 64126ad340eSHenning Colliander spin_unlock_irqrestore(&can->lock, irq); 64226ad340eSHenning Colliander } 64326ad340eSHenning Colliander 64426ad340eSHenning Colliander static void kvaser_pciefd_pwm_start(struct kvaser_pciefd_can *can) 64526ad340eSHenning Colliander { 64626ad340eSHenning Colliander int top, trigger; 64726ad340eSHenning Colliander u32 pwm_ctrl; 64826ad340eSHenning Colliander unsigned long irq; 64926ad340eSHenning Colliander 65026ad340eSHenning Colliander kvaser_pciefd_pwm_stop(can); 65126ad340eSHenning Colliander spin_lock_irqsave(&can->lock, irq); 65226ad340eSHenning Colliander /* Set frequency to 500 KHz */ 653ec44dd57SChrister Beskow top = can->kv_pcie->bus_freq / (2 * 500000) - 1; 65426ad340eSHenning Colliander 655954fb212SJimmy Assarsson pwm_ctrl = FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TRIGGER_MASK, top); 656954fb212SJimmy Assarsson pwm_ctrl |= FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TOP_MASK, top); 65726ad340eSHenning Colliander iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG); 65826ad340eSHenning Colliander 65926ad340eSHenning Colliander /* Set duty cycle to 95 */ 66026ad340eSHenning Colliander trigger = (100 * top - 95 * (top + 1) + 50) / 100; 661954fb212SJimmy Assarsson pwm_ctrl = FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TRIGGER_MASK, trigger); 662954fb212SJimmy Assarsson pwm_ctrl |= FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TOP_MASK, top); 66326ad340eSHenning Colliander iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG); 66426ad340eSHenning Colliander spin_unlock_irqrestore(&can->lock, irq); 66526ad340eSHenning Colliander } 66626ad340eSHenning Colliander 66726ad340eSHenning Colliander static int kvaser_pciefd_open(struct net_device *netdev) 66826ad340eSHenning Colliander { 66926ad340eSHenning Colliander int err; 67026ad340eSHenning Colliander struct kvaser_pciefd_can *can = netdev_priv(netdev); 67126ad340eSHenning Colliander 67226ad340eSHenning Colliander err = open_candev(netdev); 67326ad340eSHenning Colliander if (err) 67426ad340eSHenning Colliander return err; 67526ad340eSHenning Colliander 67626ad340eSHenning Colliander err = kvaser_pciefd_bus_on(can); 67713a84cf3SZhang Qilong if (err) { 67813a84cf3SZhang Qilong close_candev(netdev); 67926ad340eSHenning Colliander return err; 68013a84cf3SZhang Qilong } 68126ad340eSHenning Colliander 68226ad340eSHenning Colliander return 0; 68326ad340eSHenning Colliander } 68426ad340eSHenning Colliander 68526ad340eSHenning Colliander static int kvaser_pciefd_stop(struct net_device *netdev) 68626ad340eSHenning Colliander { 68726ad340eSHenning Colliander struct kvaser_pciefd_can *can = netdev_priv(netdev); 68826ad340eSHenning Colliander int ret = 0; 68926ad340eSHenning Colliander 69026ad340eSHenning Colliander /* Don't interrupt ongoing flush */ 69126ad340eSHenning Colliander if (!completion_done(&can->flush_comp)) 69226ad340eSHenning Colliander kvaser_pciefd_start_controller_flush(can); 69326ad340eSHenning Colliander 69426ad340eSHenning Colliander if (!wait_for_completion_timeout(&can->flush_comp, 69526ad340eSHenning Colliander KVASER_PCIEFD_WAIT_TIMEOUT)) { 69626ad340eSHenning Colliander netdev_err(can->can.dev, "Timeout during stop\n"); 69726ad340eSHenning Colliander ret = -ETIMEDOUT; 69826ad340eSHenning Colliander } else { 69926ad340eSHenning Colliander iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); 70026ad340eSHenning Colliander del_timer(&can->bec_poll_timer); 70126ad340eSHenning Colliander } 702aed0e6caSJimmy Assarsson can->can.state = CAN_STATE_STOPPED; 70326ad340eSHenning Colliander close_candev(netdev); 70426ad340eSHenning Colliander 70526ad340eSHenning Colliander return ret; 70626ad340eSHenning Colliander } 70726ad340eSHenning Colliander 70826ad340eSHenning Colliander static int kvaser_pciefd_prepare_tx_packet(struct kvaser_pciefd_tx_packet *p, 70926ad340eSHenning Colliander struct kvaser_pciefd_can *can, 71026ad340eSHenning Colliander struct sk_buff *skb) 71126ad340eSHenning Colliander { 71226ad340eSHenning Colliander struct canfd_frame *cf = (struct canfd_frame *)skb->data; 71326ad340eSHenning Colliander int packet_size; 71426ad340eSHenning Colliander int seq = can->echo_idx; 71526ad340eSHenning Colliander 71626ad340eSHenning Colliander memset(p, 0, sizeof(*p)); 71726ad340eSHenning Colliander if (can->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT) 71826ad340eSHenning Colliander p->header[1] |= KVASER_PCIEFD_TPACKET_SMS; 71926ad340eSHenning Colliander 72026ad340eSHenning Colliander if (cf->can_id & CAN_RTR_FLAG) 72126ad340eSHenning Colliander p->header[0] |= KVASER_PCIEFD_RPACKET_RTR; 72226ad340eSHenning Colliander 72326ad340eSHenning Colliander if (cf->can_id & CAN_EFF_FLAG) 72426ad340eSHenning Colliander p->header[0] |= KVASER_PCIEFD_RPACKET_IDE; 72526ad340eSHenning Colliander 726954fb212SJimmy Assarsson p->header[0] |= FIELD_PREP(KVASER_PCIEFD_RPACKET_ID_MASK, cf->can_id); 72726ad340eSHenning Colliander p->header[1] |= KVASER_PCIEFD_TPACKET_AREQ; 72826ad340eSHenning Colliander 72926ad340eSHenning Colliander if (can_is_canfd_skb(skb)) { 730f07008a2SJimmy Assarsson p->header[1] |= FIELD_PREP(KVASER_PCIEFD_RPACKET_DLC_MASK, 731f07008a2SJimmy Assarsson can_fd_len2dlc(cf->len)); 73226ad340eSHenning Colliander p->header[1] |= KVASER_PCIEFD_RPACKET_FDF; 73326ad340eSHenning Colliander if (cf->flags & CANFD_BRS) 73426ad340eSHenning Colliander p->header[1] |= KVASER_PCIEFD_RPACKET_BRS; 73526ad340eSHenning Colliander if (cf->flags & CANFD_ESI) 73626ad340eSHenning Colliander p->header[1] |= KVASER_PCIEFD_RPACKET_ESI; 737f07008a2SJimmy Assarsson } else { 738f07008a2SJimmy Assarsson p->header[1] |= 739f07008a2SJimmy Assarsson FIELD_PREP(KVASER_PCIEFD_RPACKET_DLC_MASK, 740f07008a2SJimmy Assarsson can_get_cc_dlc((struct can_frame *)cf, can->can.ctrlmode)); 74126ad340eSHenning Colliander } 74226ad340eSHenning Colliander 743954fb212SJimmy Assarsson p->header[1] |= FIELD_PREP(KVASER_PCIEFD_PACKET_SEQ_MASK, seq); 74426ad340eSHenning Colliander 74526ad340eSHenning Colliander packet_size = cf->len; 74626ad340eSHenning Colliander memcpy(p->data, cf->data, packet_size); 74726ad340eSHenning Colliander 74826ad340eSHenning Colliander return DIV_ROUND_UP(packet_size, 4); 74926ad340eSHenning Colliander } 75026ad340eSHenning Colliander 75126ad340eSHenning Colliander static netdev_tx_t kvaser_pciefd_start_xmit(struct sk_buff *skb, 75226ad340eSHenning Colliander struct net_device *netdev) 75326ad340eSHenning Colliander { 75426ad340eSHenning Colliander struct kvaser_pciefd_can *can = netdev_priv(netdev); 75526ad340eSHenning Colliander unsigned long irq_flags; 75626ad340eSHenning Colliander struct kvaser_pciefd_tx_packet packet; 757f4845741SJimmy Assarsson int nr_words; 75826ad340eSHenning Colliander u8 count; 75926ad340eSHenning Colliander 760ae64438bSOliver Hartkopp if (can_dev_dropped_skb(netdev, skb)) 76126ad340eSHenning Colliander return NETDEV_TX_OK; 76226ad340eSHenning Colliander 763f4845741SJimmy Assarsson nr_words = kvaser_pciefd_prepare_tx_packet(&packet, can, skb); 76426ad340eSHenning Colliander 76526ad340eSHenning Colliander spin_lock_irqsave(&can->echo_lock, irq_flags); 76626ad340eSHenning Colliander /* Prepare and save echo skb in internal slot */ 7671dcb6e57SVincent Mailhol can_put_echo_skb(skb, netdev, can->echo_idx, 0); 76826ad340eSHenning Colliander 76926ad340eSHenning Colliander /* Move echo index to the next slot */ 77026ad340eSHenning Colliander can->echo_idx = (can->echo_idx + 1) % can->can.echo_skb_max; 77126ad340eSHenning Colliander 77226ad340eSHenning Colliander /* Write header to fifo */ 77326ad340eSHenning Colliander iowrite32(packet.header[0], 77426ad340eSHenning Colliander can->reg_base + KVASER_PCIEFD_KCAN_FIFO_REG); 77526ad340eSHenning Colliander iowrite32(packet.header[1], 77626ad340eSHenning Colliander can->reg_base + KVASER_PCIEFD_KCAN_FIFO_REG); 77726ad340eSHenning Colliander 778f4845741SJimmy Assarsson if (nr_words) { 779f4845741SJimmy Assarsson u32 data_last = ((u32 *)packet.data)[nr_words - 1]; 78026ad340eSHenning Colliander 78126ad340eSHenning Colliander /* Write data to fifo, except last word */ 78226ad340eSHenning Colliander iowrite32_rep(can->reg_base + 78326ad340eSHenning Colliander KVASER_PCIEFD_KCAN_FIFO_REG, packet.data, 784f4845741SJimmy Assarsson nr_words - 1); 78526ad340eSHenning Colliander /* Write last word to end of fifo */ 78626ad340eSHenning Colliander __raw_writel(data_last, can->reg_base + 78726ad340eSHenning Colliander KVASER_PCIEFD_KCAN_FIFO_LAST_REG); 78826ad340eSHenning Colliander } else { 78926ad340eSHenning Colliander /* Complete write to fifo */ 79026ad340eSHenning Colliander __raw_writel(0, can->reg_base + 79126ad340eSHenning Colliander KVASER_PCIEFD_KCAN_FIFO_LAST_REG); 79226ad340eSHenning Colliander } 79326ad340eSHenning Colliander 794954fb212SJimmy Assarsson count = FIELD_GET(KVASER_PCIEFD_KCAN_TX_NR_PACKETS_CURRENT_MASK, 795f4845741SJimmy Assarsson ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG)); 79626ad340eSHenning Colliander /* No room for a new message, stop the queue until at least one 79726ad340eSHenning Colliander * successful transmit 79826ad340eSHenning Colliander */ 7996fdcd64eSJimmy Assarsson if (count >= can->can.echo_skb_max || can->can.echo_skb[can->echo_idx]) 80026ad340eSHenning Colliander netif_stop_queue(netdev); 80126ad340eSHenning Colliander spin_unlock_irqrestore(&can->echo_lock, irq_flags); 80226ad340eSHenning Colliander 80326ad340eSHenning Colliander return NETDEV_TX_OK; 80426ad340eSHenning Colliander } 80526ad340eSHenning Colliander 80626ad340eSHenning Colliander static int kvaser_pciefd_set_bittiming(struct kvaser_pciefd_can *can, bool data) 80726ad340eSHenning Colliander { 80826ad340eSHenning Colliander u32 mode, test, btrn; 80926ad340eSHenning Colliander unsigned long irq_flags; 81026ad340eSHenning Colliander int ret; 81126ad340eSHenning Colliander struct can_bittiming *bt; 81226ad340eSHenning Colliander 81326ad340eSHenning Colliander if (data) 81426ad340eSHenning Colliander bt = &can->can.data_bittiming; 81526ad340eSHenning Colliander else 81626ad340eSHenning Colliander bt = &can->can.bittiming; 81726ad340eSHenning Colliander 818954fb212SJimmy Assarsson btrn = FIELD_PREP(KVASER_PCIEFD_KCAN_BTRN_TSEG2_MASK, bt->phase_seg2 - 1) | 819954fb212SJimmy Assarsson FIELD_PREP(KVASER_PCIEFD_KCAN_BTRN_TSEG1_MASK, bt->prop_seg + bt->phase_seg1 - 1) | 820954fb212SJimmy Assarsson FIELD_PREP(KVASER_PCIEFD_KCAN_BTRN_SJW_MASK, bt->sjw - 1) | 821954fb212SJimmy Assarsson FIELD_PREP(KVASER_PCIEFD_KCAN_BTRN_BRP_MASK, bt->brp - 1); 82226ad340eSHenning Colliander 82326ad340eSHenning Colliander spin_lock_irqsave(&can->lock, irq_flags); 82426ad340eSHenning Colliander mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); 82526ad340eSHenning Colliander /* Put the circuit in reset mode */ 82626ad340eSHenning Colliander iowrite32(mode | KVASER_PCIEFD_KCAN_MODE_RM, 82726ad340eSHenning Colliander can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); 82826ad340eSHenning Colliander 82926ad340eSHenning Colliander /* Can only set bittiming if in reset mode */ 83026ad340eSHenning Colliander ret = readl_poll_timeout(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG, 831f4845741SJimmy Assarsson test, test & KVASER_PCIEFD_KCAN_MODE_RM, 0, 10); 83226ad340eSHenning Colliander if (ret) { 83326ad340eSHenning Colliander spin_unlock_irqrestore(&can->lock, irq_flags); 83426ad340eSHenning Colliander return -EBUSY; 83526ad340eSHenning Colliander } 83626ad340eSHenning Colliander 83726ad340eSHenning Colliander if (data) 83826ad340eSHenning Colliander iowrite32(btrn, can->reg_base + KVASER_PCIEFD_KCAN_BTRD_REG); 83926ad340eSHenning Colliander else 84026ad340eSHenning Colliander iowrite32(btrn, can->reg_base + KVASER_PCIEFD_KCAN_BTRN_REG); 84126ad340eSHenning Colliander /* Restore previous reset mode status */ 84226ad340eSHenning Colliander iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); 84326ad340eSHenning Colliander spin_unlock_irqrestore(&can->lock, irq_flags); 844f4845741SJimmy Assarsson 84526ad340eSHenning Colliander return 0; 84626ad340eSHenning Colliander } 84726ad340eSHenning Colliander 84826ad340eSHenning Colliander static int kvaser_pciefd_set_nominal_bittiming(struct net_device *ndev) 84926ad340eSHenning Colliander { 85026ad340eSHenning Colliander return kvaser_pciefd_set_bittiming(netdev_priv(ndev), false); 85126ad340eSHenning Colliander } 85226ad340eSHenning Colliander 85326ad340eSHenning Colliander static int kvaser_pciefd_set_data_bittiming(struct net_device *ndev) 85426ad340eSHenning Colliander { 85526ad340eSHenning Colliander return kvaser_pciefd_set_bittiming(netdev_priv(ndev), true); 85626ad340eSHenning Colliander } 85726ad340eSHenning Colliander 85826ad340eSHenning Colliander static int kvaser_pciefd_set_mode(struct net_device *ndev, enum can_mode mode) 85926ad340eSHenning Colliander { 86026ad340eSHenning Colliander struct kvaser_pciefd_can *can = netdev_priv(ndev); 86126ad340eSHenning Colliander int ret = 0; 86226ad340eSHenning Colliander 86326ad340eSHenning Colliander switch (mode) { 86426ad340eSHenning Colliander case CAN_MODE_START: 86526ad340eSHenning Colliander if (!can->can.restart_ms) 86626ad340eSHenning Colliander ret = kvaser_pciefd_bus_on(can); 86726ad340eSHenning Colliander break; 86826ad340eSHenning Colliander default: 86926ad340eSHenning Colliander return -EOPNOTSUPP; 87026ad340eSHenning Colliander } 87126ad340eSHenning Colliander 87226ad340eSHenning Colliander return ret; 87326ad340eSHenning Colliander } 87426ad340eSHenning Colliander 87526ad340eSHenning Colliander static int kvaser_pciefd_get_berr_counter(const struct net_device *ndev, 87626ad340eSHenning Colliander struct can_berr_counter *bec) 87726ad340eSHenning Colliander { 87826ad340eSHenning Colliander struct kvaser_pciefd_can *can = netdev_priv(ndev); 87926ad340eSHenning Colliander 88026ad340eSHenning Colliander bec->rxerr = can->bec.rxerr; 88126ad340eSHenning Colliander bec->txerr = can->bec.txerr; 882f4845741SJimmy Assarsson 88326ad340eSHenning Colliander return 0; 88426ad340eSHenning Colliander } 88526ad340eSHenning Colliander 88626ad340eSHenning Colliander static void kvaser_pciefd_bec_poll_timer(struct timer_list *data) 88726ad340eSHenning Colliander { 88826ad340eSHenning Colliander struct kvaser_pciefd_can *can = from_timer(can, data, bec_poll_timer); 88926ad340eSHenning Colliander 89026ad340eSHenning Colliander kvaser_pciefd_enable_err_gen(can); 89126ad340eSHenning Colliander kvaser_pciefd_request_status(can); 89226ad340eSHenning Colliander can->err_rep_cnt = 0; 89326ad340eSHenning Colliander } 89426ad340eSHenning Colliander 89526ad340eSHenning Colliander static const struct net_device_ops kvaser_pciefd_netdev_ops = { 89626ad340eSHenning Colliander .ndo_open = kvaser_pciefd_open, 89726ad340eSHenning Colliander .ndo_stop = kvaser_pciefd_stop, 898fa5cc7e1SVincent Mailhol .ndo_eth_ioctl = can_eth_ioctl_hwts, 89926ad340eSHenning Colliander .ndo_start_xmit = kvaser_pciefd_start_xmit, 90026ad340eSHenning Colliander .ndo_change_mtu = can_change_mtu, 90126ad340eSHenning Colliander }; 90226ad340eSHenning Colliander 903fa5cc7e1SVincent Mailhol static const struct ethtool_ops kvaser_pciefd_ethtool_ops = { 904fa5cc7e1SVincent Mailhol .get_ts_info = can_ethtool_op_get_ts_info_hwts, 905fa5cc7e1SVincent Mailhol }; 906fa5cc7e1SVincent Mailhol 90726ad340eSHenning Colliander static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie) 90826ad340eSHenning Colliander { 90926ad340eSHenning Colliander int i; 91026ad340eSHenning Colliander 91126ad340eSHenning Colliander for (i = 0; i < pcie->nr_channels; i++) { 91226ad340eSHenning Colliander struct net_device *netdev; 91326ad340eSHenning Colliander struct kvaser_pciefd_can *can; 914954fb212SJimmy Assarsson u32 status, tx_nr_packets_max; 91526ad340eSHenning Colliander 91626ad340eSHenning Colliander netdev = alloc_candev(sizeof(struct kvaser_pciefd_can), 91726ad340eSHenning Colliander KVASER_PCIEFD_CAN_TX_MAX_COUNT); 91826ad340eSHenning Colliander if (!netdev) 91926ad340eSHenning Colliander return -ENOMEM; 92026ad340eSHenning Colliander 92126ad340eSHenning Colliander can = netdev_priv(netdev); 92226ad340eSHenning Colliander netdev->netdev_ops = &kvaser_pciefd_netdev_ops; 923fa5cc7e1SVincent Mailhol netdev->ethtool_ops = &kvaser_pciefd_ethtool_ops; 924c2ad8129SJimmy Assarsson can->reg_base = KVASER_PCIEFD_KCAN_CHX_ADDR(pcie, i); 92526ad340eSHenning Colliander can->kv_pcie = pcie; 92626ad340eSHenning Colliander can->cmd_seq = 0; 92726ad340eSHenning Colliander can->err_rep_cnt = 0; 92826ad340eSHenning Colliander can->bec.txerr = 0; 92926ad340eSHenning Colliander can->bec.rxerr = 0; 93026ad340eSHenning Colliander 93126ad340eSHenning Colliander init_completion(&can->start_comp); 93226ad340eSHenning Colliander init_completion(&can->flush_comp); 933f4845741SJimmy Assarsson timer_setup(&can->bec_poll_timer, kvaser_pciefd_bec_poll_timer, 0); 93426ad340eSHenning Colliander 9357c6e6bceSJimmy Assarsson /* Disable Bus load reporting */ 9367c6e6bceSJimmy Assarsson iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_BUS_LOAD_REG); 9377c6e6bceSJimmy Assarsson 938954fb212SJimmy Assarsson tx_nr_packets_max = 939954fb212SJimmy Assarsson FIELD_GET(KVASER_PCIEFD_KCAN_TX_NR_PACKETS_MAX_MASK, 940f4845741SJimmy Assarsson ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG)); 94126ad340eSHenning Colliander 94226ad340eSHenning Colliander can->can.clock.freq = pcie->freq; 9436fdcd64eSJimmy Assarsson can->can.echo_skb_max = min(KVASER_PCIEFD_CAN_TX_MAX_COUNT, tx_nr_packets_max - 1); 94426ad340eSHenning Colliander can->echo_idx = 0; 94526ad340eSHenning Colliander spin_lock_init(&can->echo_lock); 94626ad340eSHenning Colliander spin_lock_init(&can->lock); 947f4845741SJimmy Assarsson 94826ad340eSHenning Colliander can->can.bittiming_const = &kvaser_pciefd_bittiming_const; 94926ad340eSHenning Colliander can->can.data_bittiming_const = &kvaser_pciefd_bittiming_const; 95026ad340eSHenning Colliander can->can.do_set_bittiming = kvaser_pciefd_set_nominal_bittiming; 951f4845741SJimmy Assarsson can->can.do_set_data_bittiming = kvaser_pciefd_set_data_bittiming; 95226ad340eSHenning Colliander can->can.do_set_mode = kvaser_pciefd_set_mode; 95326ad340eSHenning Colliander can->can.do_get_berr_counter = kvaser_pciefd_get_berr_counter; 95426ad340eSHenning Colliander can->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY | 95526ad340eSHenning Colliander CAN_CTRLMODE_FD | 956f07008a2SJimmy Assarsson CAN_CTRLMODE_FD_NON_ISO | 957f07008a2SJimmy Assarsson CAN_CTRLMODE_CC_LEN8_DLC; 95826ad340eSHenning Colliander 95926ad340eSHenning Colliander status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG); 96026ad340eSHenning Colliander if (!(status & KVASER_PCIEFD_KCAN_STAT_FD)) { 96126ad340eSHenning Colliander dev_err(&pcie->pci->dev, 96226ad340eSHenning Colliander "CAN FD not supported as expected %d\n", i); 96326ad340eSHenning Colliander 96426ad340eSHenning Colliander free_candev(netdev); 96526ad340eSHenning Colliander return -ENODEV; 96626ad340eSHenning Colliander } 96726ad340eSHenning Colliander 96826ad340eSHenning Colliander if (status & KVASER_PCIEFD_KCAN_STAT_CAP) 96926ad340eSHenning Colliander can->can.ctrlmode_supported |= CAN_CTRLMODE_ONE_SHOT; 97026ad340eSHenning Colliander 97126ad340eSHenning Colliander netdev->flags |= IFF_ECHO; 97226ad340eSHenning Colliander SET_NETDEV_DEV(netdev, &pcie->pci->dev); 97326ad340eSHenning Colliander 974f4845741SJimmy Assarsson iowrite32(GENMASK(31, 0), can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); 975262d7a52SJimmy Assarsson iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD, 97626ad340eSHenning Colliander can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); 97726ad340eSHenning Colliander 97826ad340eSHenning Colliander pcie->can[i] = can; 97926ad340eSHenning Colliander kvaser_pciefd_pwm_start(can); 98026ad340eSHenning Colliander } 98126ad340eSHenning Colliander 98226ad340eSHenning Colliander return 0; 98326ad340eSHenning Colliander } 98426ad340eSHenning Colliander 98526ad340eSHenning Colliander static int kvaser_pciefd_reg_candev(struct kvaser_pciefd *pcie) 98626ad340eSHenning Colliander { 98726ad340eSHenning Colliander int i; 98826ad340eSHenning Colliander 98926ad340eSHenning Colliander for (i = 0; i < pcie->nr_channels; i++) { 99026ad340eSHenning Colliander int err = register_candev(pcie->can[i]->can.dev); 99126ad340eSHenning Colliander 99226ad340eSHenning Colliander if (err) { 99326ad340eSHenning Colliander int j; 99426ad340eSHenning Colliander 99526ad340eSHenning Colliander /* Unregister all successfully registered devices. */ 99626ad340eSHenning Colliander for (j = 0; j < i; j++) 99726ad340eSHenning Colliander unregister_candev(pcie->can[j]->can.dev); 99826ad340eSHenning Colliander return err; 99926ad340eSHenning Colliander } 100026ad340eSHenning Colliander } 100126ad340eSHenning Colliander 100226ad340eSHenning Colliander return 0; 100326ad340eSHenning Colliander } 100426ad340eSHenning Colliander 1005c2ad8129SJimmy Assarsson static void kvaser_pciefd_write_dma_map_altera(struct kvaser_pciefd *pcie, 1006c2ad8129SJimmy Assarsson dma_addr_t addr, int index) 100726ad340eSHenning Colliander { 1008c2ad8129SJimmy Assarsson void __iomem *serdes_base; 100926ad340eSHenning Colliander u32 word1, word2; 101026ad340eSHenning Colliander 101126ad340eSHenning Colliander #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT 1012c2ad8129SJimmy Assarsson word1 = addr | KVASER_PCIEFD_ALTERA_DMA_64BIT; 101326ad340eSHenning Colliander word2 = addr >> 32; 101426ad340eSHenning Colliander #else 101526ad340eSHenning Colliander word1 = addr; 101626ad340eSHenning Colliander word2 = 0; 101726ad340eSHenning Colliander #endif 1018c2ad8129SJimmy Assarsson serdes_base = KVASER_PCIEFD_SERDES_ADDR(pcie) + 0x8 * index; 1019c2ad8129SJimmy Assarsson iowrite32(word1, serdes_base); 1020c2ad8129SJimmy Assarsson iowrite32(word2, serdes_base + 0x4); 102126ad340eSHenning Colliander } 102226ad340eSHenning Colliander 1023f33ad677SJimmy Assarsson static void kvaser_pciefd_write_dma_map_sf2(struct kvaser_pciefd *pcie, 1024f33ad677SJimmy Assarsson dma_addr_t addr, int index) 1025f33ad677SJimmy Assarsson { 1026f33ad677SJimmy Assarsson void __iomem *serdes_base; 1027f33ad677SJimmy Assarsson u32 lsb = addr & KVASER_PCIEFD_SF2_DMA_LSB_MASK; 1028f33ad677SJimmy Assarsson u32 msb = 0x0; 1029f33ad677SJimmy Assarsson 1030f33ad677SJimmy Assarsson #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT 1031f33ad677SJimmy Assarsson msb = addr >> 32; 1032f33ad677SJimmy Assarsson #endif 1033f33ad677SJimmy Assarsson serdes_base = KVASER_PCIEFD_SERDES_ADDR(pcie) + 0x10 * index; 1034f33ad677SJimmy Assarsson iowrite32(lsb, serdes_base); 1035f33ad677SJimmy Assarsson iowrite32(msb, serdes_base + 0x4); 1036f33ad677SJimmy Assarsson } 1037f33ad677SJimmy Assarsson 103826ad340eSHenning Colliander static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie) 103926ad340eSHenning Colliander { 104026ad340eSHenning Colliander int i; 104126ad340eSHenning Colliander u32 srb_status; 1042c589557dSJimmy Assarsson u32 srb_packet_count; 104326ad340eSHenning Colliander dma_addr_t dma_addr[KVASER_PCIEFD_DMA_COUNT]; 104426ad340eSHenning Colliander 104526ad340eSHenning Colliander /* Disable the DMA */ 1046c2ad8129SJimmy Assarsson iowrite32(0, KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CTRL_REG); 104726ad340eSHenning Colliander for (i = 0; i < KVASER_PCIEFD_DMA_COUNT; i++) { 1048f4845741SJimmy Assarsson pcie->dma_data[i] = dmam_alloc_coherent(&pcie->pci->dev, 104926ad340eSHenning Colliander KVASER_PCIEFD_DMA_SIZE, 105026ad340eSHenning Colliander &dma_addr[i], 105126ad340eSHenning Colliander GFP_KERNEL); 105226ad340eSHenning Colliander 105326ad340eSHenning Colliander if (!pcie->dma_data[i] || !dma_addr[i]) { 105426ad340eSHenning Colliander dev_err(&pcie->pci->dev, "Rx dma_alloc(%u) failure\n", 105526ad340eSHenning Colliander KVASER_PCIEFD_DMA_SIZE); 105626ad340eSHenning Colliander return -ENOMEM; 105726ad340eSHenning Colliander } 1058c2ad8129SJimmy Assarsson pcie->driver_data->ops->kvaser_pciefd_write_dma_map(pcie, dma_addr[i], i); 105926ad340eSHenning Colliander } 106026ad340eSHenning Colliander 106126ad340eSHenning Colliander /* Reset Rx FIFO, and both DMA buffers */ 106226ad340eSHenning Colliander iowrite32(KVASER_PCIEFD_SRB_CMD_FOR | KVASER_PCIEFD_SRB_CMD_RDB0 | 106326ad340eSHenning Colliander KVASER_PCIEFD_SRB_CMD_RDB1, 1064c2ad8129SJimmy Assarsson KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG); 1065c589557dSJimmy Assarsson /* Empty Rx FIFO */ 1066954fb212SJimmy Assarsson srb_packet_count = 1067954fb212SJimmy Assarsson FIELD_GET(KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK, 1068c2ad8129SJimmy Assarsson ioread32(KVASER_PCIEFD_SRB_ADDR(pcie) + 1069c2ad8129SJimmy Assarsson KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG)); 1070c589557dSJimmy Assarsson while (srb_packet_count) { 1071c589557dSJimmy Assarsson /* Drop current packet in FIFO */ 1072c2ad8129SJimmy Assarsson ioread32(KVASER_PCIEFD_SRB_FIFO_ADDR(pcie) + KVASER_PCIEFD_SRB_FIFO_LAST_REG); 1073c589557dSJimmy Assarsson srb_packet_count--; 1074c589557dSJimmy Assarsson } 1075c589557dSJimmy Assarsson 1076c2ad8129SJimmy Assarsson srb_status = ioread32(KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_STAT_REG); 107726ad340eSHenning Colliander if (!(srb_status & KVASER_PCIEFD_SRB_STAT_DI)) { 107826ad340eSHenning Colliander dev_err(&pcie->pci->dev, "DMA not idle before enabling\n"); 107926ad340eSHenning Colliander return -EIO; 108026ad340eSHenning Colliander } 108126ad340eSHenning Colliander 108226ad340eSHenning Colliander /* Enable the DMA */ 108326ad340eSHenning Colliander iowrite32(KVASER_PCIEFD_SRB_CTRL_DMA_ENABLE, 1084c2ad8129SJimmy Assarsson KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CTRL_REG); 108526ad340eSHenning Colliander 108626ad340eSHenning Colliander return 0; 108726ad340eSHenning Colliander } 108826ad340eSHenning Colliander 108926ad340eSHenning Colliander static int kvaser_pciefd_setup_board(struct kvaser_pciefd *pcie) 109026ad340eSHenning Colliander { 1091954fb212SJimmy Assarsson u32 version, srb_status, build; 109226ad340eSHenning Colliander 1093c2ad8129SJimmy Assarsson version = ioread32(KVASER_PCIEFD_SYSID_ADDR(pcie) + KVASER_PCIEFD_SYSID_VERSION_REG); 1094c496adafSJimmy Assarsson pcie->nr_channels = min(KVASER_PCIEFD_MAX_CAN_CHANNELS, 1095954fb212SJimmy Assarsson FIELD_GET(KVASER_PCIEFD_SYSID_VERSION_NR_CHAN_MASK, version)); 109626ad340eSHenning Colliander 1097c2ad8129SJimmy Assarsson build = ioread32(KVASER_PCIEFD_SYSID_ADDR(pcie) + KVASER_PCIEFD_SYSID_BUILD_REG); 1098954fb212SJimmy Assarsson dev_dbg(&pcie->pci->dev, "Version %lu.%lu.%lu\n", 1099954fb212SJimmy Assarsson FIELD_GET(KVASER_PCIEFD_SYSID_VERSION_MAJOR_MASK, version), 1100954fb212SJimmy Assarsson FIELD_GET(KVASER_PCIEFD_SYSID_VERSION_MINOR_MASK, version), 1101954fb212SJimmy Assarsson FIELD_GET(KVASER_PCIEFD_SYSID_BUILD_SEQ_MASK, build)); 110226ad340eSHenning Colliander 1103c2ad8129SJimmy Assarsson srb_status = ioread32(KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_STAT_REG); 110426ad340eSHenning Colliander if (!(srb_status & KVASER_PCIEFD_SRB_STAT_DMA)) { 1105f4845741SJimmy Assarsson dev_err(&pcie->pci->dev, "Hardware without DMA is not supported\n"); 110626ad340eSHenning Colliander return -ENODEV; 110726ad340eSHenning Colliander } 110826ad340eSHenning Colliander 1109c2ad8129SJimmy Assarsson pcie->bus_freq = ioread32(KVASER_PCIEFD_SYSID_ADDR(pcie) + KVASER_PCIEFD_SYSID_BUSFREQ_REG); 1110c2ad8129SJimmy Assarsson pcie->freq = ioread32(KVASER_PCIEFD_SYSID_ADDR(pcie) + KVASER_PCIEFD_SYSID_CANFREQ_REG); 111126ad340eSHenning Colliander pcie->freq_to_ticks_div = pcie->freq / 1000000; 111226ad340eSHenning Colliander if (pcie->freq_to_ticks_div == 0) 111326ad340eSHenning Colliander pcie->freq_to_ticks_div = 1; 111426ad340eSHenning Colliander /* Turn off all loopback functionality */ 1115c2ad8129SJimmy Assarsson iowrite32(0, KVASER_PCIEFD_LOOPBACK_ADDR(pcie)); 1116f4845741SJimmy Assarsson 1117c496adafSJimmy Assarsson return 0; 111826ad340eSHenning Colliander } 111926ad340eSHenning Colliander 112026ad340eSHenning Colliander static int kvaser_pciefd_handle_data_packet(struct kvaser_pciefd *pcie, 112126ad340eSHenning Colliander struct kvaser_pciefd_rx_packet *p, 112226ad340eSHenning Colliander __le32 *data) 112326ad340eSHenning Colliander { 112426ad340eSHenning Colliander struct sk_buff *skb; 112526ad340eSHenning Colliander struct canfd_frame *cf; 112626ad340eSHenning Colliander struct can_priv *priv; 1127954fb212SJimmy Assarsson u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]); 1128f07008a2SJimmy Assarsson u8 dlc; 112926ad340eSHenning Colliander 113026ad340eSHenning Colliander if (ch_id >= pcie->nr_channels) 113126ad340eSHenning Colliander return -EIO; 113226ad340eSHenning Colliander 113326ad340eSHenning Colliander priv = &pcie->can[ch_id]->can; 1134f07008a2SJimmy Assarsson dlc = FIELD_GET(KVASER_PCIEFD_RPACKET_DLC_MASK, p->header[1]); 113526ad340eSHenning Colliander 113626ad340eSHenning Colliander if (p->header[1] & KVASER_PCIEFD_RPACKET_FDF) { 113726ad340eSHenning Colliander skb = alloc_canfd_skb(priv->dev, &cf); 113826ad340eSHenning Colliander if (!skb) { 1139f4845741SJimmy Assarsson priv->dev->stats.rx_dropped++; 114026ad340eSHenning Colliander return -ENOMEM; 114126ad340eSHenning Colliander } 114226ad340eSHenning Colliander 1143f07008a2SJimmy Assarsson cf->len = can_fd_dlc2len(dlc); 114426ad340eSHenning Colliander if (p->header[1] & KVASER_PCIEFD_RPACKET_BRS) 114526ad340eSHenning Colliander cf->flags |= CANFD_BRS; 114626ad340eSHenning Colliander if (p->header[1] & KVASER_PCIEFD_RPACKET_ESI) 114726ad340eSHenning Colliander cf->flags |= CANFD_ESI; 114826ad340eSHenning Colliander } else { 114926ad340eSHenning Colliander skb = alloc_can_skb(priv->dev, (struct can_frame **)&cf); 115026ad340eSHenning Colliander if (!skb) { 1151f4845741SJimmy Assarsson priv->dev->stats.rx_dropped++; 115226ad340eSHenning Colliander return -ENOMEM; 115326ad340eSHenning Colliander } 1154f07008a2SJimmy Assarsson can_frame_set_cc_len((struct can_frame *)cf, dlc, priv->ctrlmode); 115526ad340eSHenning Colliander } 115626ad340eSHenning Colliander 1157954fb212SJimmy Assarsson cf->can_id = FIELD_GET(KVASER_PCIEFD_RPACKET_ID_MASK, p->header[0]); 115826ad340eSHenning Colliander if (p->header[0] & KVASER_PCIEFD_RPACKET_IDE) 115926ad340eSHenning Colliander cf->can_id |= CAN_EFF_FLAG; 116026ad340eSHenning Colliander 11618e674ca7SVincent Mailhol if (p->header[0] & KVASER_PCIEFD_RPACKET_RTR) { 116226ad340eSHenning Colliander cf->can_id |= CAN_RTR_FLAG; 11638e674ca7SVincent Mailhol } else { 116426ad340eSHenning Colliander memcpy(cf->data, data, cf->len); 1165f4845741SJimmy Assarsson priv->dev->stats.rx_bytes += cf->len; 11668e674ca7SVincent Mailhol } 1167f4845741SJimmy Assarsson priv->dev->stats.rx_packets++; 11682d55e9f9SJimmy Assarsson kvaser_pciefd_set_skb_timestamp(pcie, skb, p->timestamp); 116926ad340eSHenning Colliander 117026ad340eSHenning Colliander return netif_rx(skb); 117126ad340eSHenning Colliander } 117226ad340eSHenning Colliander 117326ad340eSHenning Colliander static void kvaser_pciefd_change_state(struct kvaser_pciefd_can *can, 117426ad340eSHenning Colliander struct can_frame *cf, 117526ad340eSHenning Colliander enum can_state new_state, 117626ad340eSHenning Colliander enum can_state tx_state, 117726ad340eSHenning Colliander enum can_state rx_state) 117826ad340eSHenning Colliander { 117926ad340eSHenning Colliander can_change_state(can->can.dev, cf, tx_state, rx_state); 118026ad340eSHenning Colliander 118126ad340eSHenning Colliander if (new_state == CAN_STATE_BUS_OFF) { 118226ad340eSHenning Colliander struct net_device *ndev = can->can.dev; 118326ad340eSHenning Colliander unsigned long irq_flags; 118426ad340eSHenning Colliander 118526ad340eSHenning Colliander spin_lock_irqsave(&can->lock, irq_flags); 118626ad340eSHenning Colliander netif_stop_queue(can->can.dev); 118726ad340eSHenning Colliander spin_unlock_irqrestore(&can->lock, irq_flags); 118826ad340eSHenning Colliander /* Prevent CAN controller from auto recover from bus off */ 118926ad340eSHenning Colliander if (!can->can.restart_ms) { 119026ad340eSHenning Colliander kvaser_pciefd_start_controller_flush(can); 119126ad340eSHenning Colliander can_bus_off(ndev); 119226ad340eSHenning Colliander } 119326ad340eSHenning Colliander } 119426ad340eSHenning Colliander } 119526ad340eSHenning Colliander 119626ad340eSHenning Colliander static void kvaser_pciefd_packet_to_state(struct kvaser_pciefd_rx_packet *p, 119726ad340eSHenning Colliander struct can_berr_counter *bec, 119826ad340eSHenning Colliander enum can_state *new_state, 119926ad340eSHenning Colliander enum can_state *tx_state, 120026ad340eSHenning Colliander enum can_state *rx_state) 120126ad340eSHenning Colliander { 120226ad340eSHenning Colliander if (p->header[0] & KVASER_PCIEFD_SPACK_BOFF || 120326ad340eSHenning Colliander p->header[0] & KVASER_PCIEFD_SPACK_IRM) 120426ad340eSHenning Colliander *new_state = CAN_STATE_BUS_OFF; 120526ad340eSHenning Colliander else if (bec->txerr >= 255 || bec->rxerr >= 255) 120626ad340eSHenning Colliander *new_state = CAN_STATE_BUS_OFF; 120726ad340eSHenning Colliander else if (p->header[1] & KVASER_PCIEFD_SPACK_EPLR) 120826ad340eSHenning Colliander *new_state = CAN_STATE_ERROR_PASSIVE; 120926ad340eSHenning Colliander else if (bec->txerr >= 128 || bec->rxerr >= 128) 121026ad340eSHenning Colliander *new_state = CAN_STATE_ERROR_PASSIVE; 121126ad340eSHenning Colliander else if (p->header[1] & KVASER_PCIEFD_SPACK_EWLR) 121226ad340eSHenning Colliander *new_state = CAN_STATE_ERROR_WARNING; 121326ad340eSHenning Colliander else if (bec->txerr >= 96 || bec->rxerr >= 96) 121426ad340eSHenning Colliander *new_state = CAN_STATE_ERROR_WARNING; 121526ad340eSHenning Colliander else 121626ad340eSHenning Colliander *new_state = CAN_STATE_ERROR_ACTIVE; 121726ad340eSHenning Colliander 121826ad340eSHenning Colliander *tx_state = bec->txerr >= bec->rxerr ? *new_state : 0; 121926ad340eSHenning Colliander *rx_state = bec->txerr <= bec->rxerr ? *new_state : 0; 122026ad340eSHenning Colliander } 122126ad340eSHenning Colliander 122226ad340eSHenning Colliander static int kvaser_pciefd_rx_error_frame(struct kvaser_pciefd_can *can, 122326ad340eSHenning Colliander struct kvaser_pciefd_rx_packet *p) 122426ad340eSHenning Colliander { 122526ad340eSHenning Colliander struct can_berr_counter bec; 122626ad340eSHenning Colliander enum can_state old_state, new_state, tx_state, rx_state; 122726ad340eSHenning Colliander struct net_device *ndev = can->can.dev; 122826ad340eSHenning Colliander struct sk_buff *skb; 122926ad340eSHenning Colliander struct can_frame *cf = NULL; 123026ad340eSHenning Colliander 123126ad340eSHenning Colliander old_state = can->can.state; 123226ad340eSHenning Colliander 1233954fb212SJimmy Assarsson bec.txerr = FIELD_GET(KVASER_PCIEFD_SPACK_TXERR_MASK, p->header[0]); 1234954fb212SJimmy Assarsson bec.rxerr = FIELD_GET(KVASER_PCIEFD_SPACK_RXERR_MASK, p->header[0]); 123526ad340eSHenning Colliander 1236f4845741SJimmy Assarsson kvaser_pciefd_packet_to_state(p, &bec, &new_state, &tx_state, &rx_state); 123726ad340eSHenning Colliander skb = alloc_can_err_skb(ndev, &cf); 123826ad340eSHenning Colliander if (new_state != old_state) { 1239f4845741SJimmy Assarsson kvaser_pciefd_change_state(can, cf, new_state, tx_state, rx_state); 124026ad340eSHenning Colliander if (old_state == CAN_STATE_BUS_OFF && 124126ad340eSHenning Colliander new_state == CAN_STATE_ERROR_ACTIVE && 124226ad340eSHenning Colliander can->can.restart_ms) { 124326ad340eSHenning Colliander can->can.can_stats.restarts++; 124426ad340eSHenning Colliander if (skb) 124526ad340eSHenning Colliander cf->can_id |= CAN_ERR_RESTARTED; 124626ad340eSHenning Colliander } 124726ad340eSHenning Colliander } 124826ad340eSHenning Colliander 124926ad340eSHenning Colliander can->err_rep_cnt++; 125026ad340eSHenning Colliander can->can.can_stats.bus_error++; 125136aea60fSJimmy Assarsson if (p->header[1] & KVASER_PCIEFD_EPACK_DIR_TX) 1252f4845741SJimmy Assarsson ndev->stats.tx_errors++; 125336aea60fSJimmy Assarsson else 1254f4845741SJimmy Assarsson ndev->stats.rx_errors++; 125526ad340eSHenning Colliander 125626ad340eSHenning Colliander can->bec.txerr = bec.txerr; 125726ad340eSHenning Colliander can->bec.rxerr = bec.rxerr; 125826ad340eSHenning Colliander 125926ad340eSHenning Colliander if (!skb) { 1260f4845741SJimmy Assarsson ndev->stats.rx_dropped++; 126126ad340eSHenning Colliander return -ENOMEM; 126226ad340eSHenning Colliander } 126326ad340eSHenning Colliander 12642d55e9f9SJimmy Assarsson kvaser_pciefd_set_skb_timestamp(can->kv_pcie, skb, p->timestamp); 12653e5c291cSVincent Mailhol cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_CNT; 126626ad340eSHenning Colliander cf->data[6] = bec.txerr; 126726ad340eSHenning Colliander cf->data[7] = bec.rxerr; 126826ad340eSHenning Colliander 126926ad340eSHenning Colliander netif_rx(skb); 1270f4845741SJimmy Assarsson 127126ad340eSHenning Colliander return 0; 127226ad340eSHenning Colliander } 127326ad340eSHenning Colliander 127426ad340eSHenning Colliander static int kvaser_pciefd_handle_error_packet(struct kvaser_pciefd *pcie, 127526ad340eSHenning Colliander struct kvaser_pciefd_rx_packet *p) 127626ad340eSHenning Colliander { 127726ad340eSHenning Colliander struct kvaser_pciefd_can *can; 1278954fb212SJimmy Assarsson u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]); 127926ad340eSHenning Colliander 128026ad340eSHenning Colliander if (ch_id >= pcie->nr_channels) 128126ad340eSHenning Colliander return -EIO; 128226ad340eSHenning Colliander 128326ad340eSHenning Colliander can = pcie->can[ch_id]; 128426ad340eSHenning Colliander kvaser_pciefd_rx_error_frame(can, p); 128526ad340eSHenning Colliander if (can->err_rep_cnt >= KVASER_PCIEFD_MAX_ERR_REP) 128626ad340eSHenning Colliander /* Do not report more errors, until bec_poll_timer expires */ 128726ad340eSHenning Colliander kvaser_pciefd_disable_err_gen(can); 128826ad340eSHenning Colliander /* Start polling the error counters */ 128926ad340eSHenning Colliander mod_timer(&can->bec_poll_timer, KVASER_PCIEFD_BEC_POLL_FREQ); 1290f4845741SJimmy Assarsson 129126ad340eSHenning Colliander return 0; 129226ad340eSHenning Colliander } 129326ad340eSHenning Colliander 129426ad340eSHenning Colliander static int kvaser_pciefd_handle_status_resp(struct kvaser_pciefd_can *can, 129526ad340eSHenning Colliander struct kvaser_pciefd_rx_packet *p) 129626ad340eSHenning Colliander { 129726ad340eSHenning Colliander struct can_berr_counter bec; 129826ad340eSHenning Colliander enum can_state old_state, new_state, tx_state, rx_state; 129926ad340eSHenning Colliander 130026ad340eSHenning Colliander old_state = can->can.state; 130126ad340eSHenning Colliander 1302954fb212SJimmy Assarsson bec.txerr = FIELD_GET(KVASER_PCIEFD_SPACK_TXERR_MASK, p->header[0]); 1303954fb212SJimmy Assarsson bec.rxerr = FIELD_GET(KVASER_PCIEFD_SPACK_RXERR_MASK, p->header[0]); 130426ad340eSHenning Colliander 1305f4845741SJimmy Assarsson kvaser_pciefd_packet_to_state(p, &bec, &new_state, &tx_state, &rx_state); 130626ad340eSHenning Colliander if (new_state != old_state) { 130726ad340eSHenning Colliander struct net_device *ndev = can->can.dev; 130826ad340eSHenning Colliander struct sk_buff *skb; 130926ad340eSHenning Colliander struct can_frame *cf; 131026ad340eSHenning Colliander 131126ad340eSHenning Colliander skb = alloc_can_err_skb(ndev, &cf); 131226ad340eSHenning Colliander if (!skb) { 1313f4845741SJimmy Assarsson ndev->stats.rx_dropped++; 131426ad340eSHenning Colliander return -ENOMEM; 131526ad340eSHenning Colliander } 131626ad340eSHenning Colliander 1317f4845741SJimmy Assarsson kvaser_pciefd_change_state(can, cf, new_state, tx_state, rx_state); 131826ad340eSHenning Colliander if (old_state == CAN_STATE_BUS_OFF && 131926ad340eSHenning Colliander new_state == CAN_STATE_ERROR_ACTIVE && 132026ad340eSHenning Colliander can->can.restart_ms) { 132126ad340eSHenning Colliander can->can.can_stats.restarts++; 132226ad340eSHenning Colliander cf->can_id |= CAN_ERR_RESTARTED; 132326ad340eSHenning Colliander } 132426ad340eSHenning Colliander 13252d55e9f9SJimmy Assarsson kvaser_pciefd_set_skb_timestamp(can->kv_pcie, skb, p->timestamp); 132626ad340eSHenning Colliander 132726ad340eSHenning Colliander cf->data[6] = bec.txerr; 132826ad340eSHenning Colliander cf->data[7] = bec.rxerr; 132926ad340eSHenning Colliander 133026ad340eSHenning Colliander netif_rx(skb); 133126ad340eSHenning Colliander } 133226ad340eSHenning Colliander can->bec.txerr = bec.txerr; 133326ad340eSHenning Colliander can->bec.rxerr = bec.rxerr; 133426ad340eSHenning Colliander /* Check if we need to poll the error counters */ 133526ad340eSHenning Colliander if (bec.txerr || bec.rxerr) 133626ad340eSHenning Colliander mod_timer(&can->bec_poll_timer, KVASER_PCIEFD_BEC_POLL_FREQ); 133726ad340eSHenning Colliander 133826ad340eSHenning Colliander return 0; 133926ad340eSHenning Colliander } 134026ad340eSHenning Colliander 134126ad340eSHenning Colliander static int kvaser_pciefd_handle_status_packet(struct kvaser_pciefd *pcie, 134226ad340eSHenning Colliander struct kvaser_pciefd_rx_packet *p) 134326ad340eSHenning Colliander { 134426ad340eSHenning Colliander struct kvaser_pciefd_can *can; 134526ad340eSHenning Colliander u8 cmdseq; 134626ad340eSHenning Colliander u32 status; 1347954fb212SJimmy Assarsson u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]); 134826ad340eSHenning Colliander 134926ad340eSHenning Colliander if (ch_id >= pcie->nr_channels) 135026ad340eSHenning Colliander return -EIO; 135126ad340eSHenning Colliander 135226ad340eSHenning Colliander can = pcie->can[ch_id]; 135326ad340eSHenning Colliander 135426ad340eSHenning Colliander status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG); 1355954fb212SJimmy Assarsson cmdseq = FIELD_GET(KVASER_PCIEFD_KCAN_STAT_SEQNO_MASK, status); 135626ad340eSHenning Colliander 135726ad340eSHenning Colliander /* Reset done, start abort and flush */ 135826ad340eSHenning Colliander if (p->header[0] & KVASER_PCIEFD_SPACK_IRM && 135926ad340eSHenning Colliander p->header[0] & KVASER_PCIEFD_SPACK_RMCD && 136026ad340eSHenning Colliander p->header[1] & KVASER_PCIEFD_SPACK_AUTO && 1361954fb212SJimmy Assarsson cmdseq == FIELD_GET(KVASER_PCIEFD_PACKET_SEQ_MASK, p->header[1]) && 136226ad340eSHenning Colliander status & KVASER_PCIEFD_KCAN_STAT_IDLE) { 136326ad340eSHenning Colliander iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD, 136426ad340eSHenning Colliander can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); 1365f4845741SJimmy Assarsson kvaser_pciefd_abort_flush_reset(can); 136626ad340eSHenning Colliander } else if (p->header[0] & KVASER_PCIEFD_SPACK_IDET && 136726ad340eSHenning Colliander p->header[0] & KVASER_PCIEFD_SPACK_IRM && 1368954fb212SJimmy Assarsson cmdseq == FIELD_GET(KVASER_PCIEFD_PACKET_SEQ_MASK, p->header[1]) && 136926ad340eSHenning Colliander status & KVASER_PCIEFD_KCAN_STAT_IDLE) { 137026ad340eSHenning Colliander /* Reset detected, send end of flush if no packet are in FIFO */ 1371f4845741SJimmy Assarsson u8 count; 137226ad340eSHenning Colliander 1373f4845741SJimmy Assarsson count = FIELD_GET(KVASER_PCIEFD_KCAN_TX_NR_PACKETS_CURRENT_MASK, 1374f4845741SJimmy Assarsson ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG)); 137526ad340eSHenning Colliander if (!count) 1376954fb212SJimmy Assarsson iowrite32(FIELD_PREP(KVASER_PCIEFD_KCAN_CTRL_TYPE_MASK, 1377954fb212SJimmy Assarsson KVASER_PCIEFD_KCAN_CTRL_TYPE_EFLUSH), 137826ad340eSHenning Colliander can->reg_base + KVASER_PCIEFD_KCAN_CTRL_REG); 137926ad340eSHenning Colliander } else if (!(p->header[1] & KVASER_PCIEFD_SPACK_AUTO) && 1380954fb212SJimmy Assarsson cmdseq == FIELD_GET(KVASER_PCIEFD_PACKET_SEQ_MASK, p->header[1])) { 138126ad340eSHenning Colliander /* Response to status request received */ 138226ad340eSHenning Colliander kvaser_pciefd_handle_status_resp(can, p); 138326ad340eSHenning Colliander if (can->can.state != CAN_STATE_BUS_OFF && 138426ad340eSHenning Colliander can->can.state != CAN_STATE_ERROR_ACTIVE) { 1385f4845741SJimmy Assarsson mod_timer(&can->bec_poll_timer, KVASER_PCIEFD_BEC_POLL_FREQ); 138626ad340eSHenning Colliander } 138726ad340eSHenning Colliander } else if (p->header[0] & KVASER_PCIEFD_SPACK_RMCD && 1388f4845741SJimmy Assarsson !(status & KVASER_PCIEFD_KCAN_STAT_BUS_OFF_MASK)) { 138926ad340eSHenning Colliander /* Reset to bus on detected */ 139026ad340eSHenning Colliander if (!completion_done(&can->start_comp)) 139126ad340eSHenning Colliander complete(&can->start_comp); 139226ad340eSHenning Colliander } 139326ad340eSHenning Colliander 139426ad340eSHenning Colliander return 0; 139526ad340eSHenning Colliander } 139626ad340eSHenning Colliander 139726ad340eSHenning Colliander static void kvaser_pciefd_handle_nack_packet(struct kvaser_pciefd_can *can, 139826ad340eSHenning Colliander struct kvaser_pciefd_rx_packet *p) 139926ad340eSHenning Colliander { 140026ad340eSHenning Colliander struct sk_buff *skb; 140126ad340eSHenning Colliander struct can_frame *cf; 140226ad340eSHenning Colliander 140326ad340eSHenning Colliander skb = alloc_can_err_skb(can->can.dev, &cf); 1404f4845741SJimmy Assarsson can->can.dev->stats.tx_errors++; 140526ad340eSHenning Colliander if (p->header[0] & KVASER_PCIEFD_APACKET_ABL) { 140626ad340eSHenning Colliander if (skb) 140726ad340eSHenning Colliander cf->can_id |= CAN_ERR_LOSTARB; 140826ad340eSHenning Colliander can->can.can_stats.arbitration_lost++; 140926ad340eSHenning Colliander } else if (skb) { 141026ad340eSHenning Colliander cf->can_id |= CAN_ERR_ACK; 141126ad340eSHenning Colliander } 141226ad340eSHenning Colliander 141326ad340eSHenning Colliander if (skb) { 141426ad340eSHenning Colliander cf->can_id |= CAN_ERR_BUSERROR; 1415ec681b91SJimmy Assarsson kvaser_pciefd_set_skb_timestamp(can->kv_pcie, skb, p->timestamp); 141626ad340eSHenning Colliander netif_rx(skb); 141726ad340eSHenning Colliander } else { 1418f4845741SJimmy Assarsson can->can.dev->stats.rx_dropped++; 141926ad340eSHenning Colliander netdev_warn(can->can.dev, "No memory left for err_skb\n"); 142026ad340eSHenning Colliander } 142126ad340eSHenning Colliander } 142226ad340eSHenning Colliander 142326ad340eSHenning Colliander static int kvaser_pciefd_handle_ack_packet(struct kvaser_pciefd *pcie, 142426ad340eSHenning Colliander struct kvaser_pciefd_rx_packet *p) 142526ad340eSHenning Colliander { 142626ad340eSHenning Colliander struct kvaser_pciefd_can *can; 142726ad340eSHenning Colliander bool one_shot_fail = false; 1428954fb212SJimmy Assarsson u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]); 142926ad340eSHenning Colliander 143026ad340eSHenning Colliander if (ch_id >= pcie->nr_channels) 143126ad340eSHenning Colliander return -EIO; 143226ad340eSHenning Colliander 143326ad340eSHenning Colliander can = pcie->can[ch_id]; 143426ad340eSHenning Colliander /* Ignore control packet ACK */ 143526ad340eSHenning Colliander if (p->header[0] & KVASER_PCIEFD_APACKET_CT) 143626ad340eSHenning Colliander return 0; 143726ad340eSHenning Colliander 143826ad340eSHenning Colliander if (p->header[0] & KVASER_PCIEFD_APACKET_NACK) { 143926ad340eSHenning Colliander kvaser_pciefd_handle_nack_packet(can, p); 144026ad340eSHenning Colliander one_shot_fail = true; 144126ad340eSHenning Colliander } 144226ad340eSHenning Colliander 144326ad340eSHenning Colliander if (p->header[0] & KVASER_PCIEFD_APACKET_FLU) { 144426ad340eSHenning Colliander netdev_dbg(can->can.dev, "Packet was flushed\n"); 144526ad340eSHenning Colliander } else { 1446954fb212SJimmy Assarsson int echo_idx = FIELD_GET(KVASER_PCIEFD_PACKET_SEQ_MASK, p->header[0]); 1447f4845741SJimmy Assarsson int len; 1448ec681b91SJimmy Assarsson u8 count; 1449ec681b91SJimmy Assarsson struct sk_buff *skb; 1450ec681b91SJimmy Assarsson 1451ec681b91SJimmy Assarsson skb = can->can.echo_skb[echo_idx]; 1452ec681b91SJimmy Assarsson if (skb) 1453ec681b91SJimmy Assarsson kvaser_pciefd_set_skb_timestamp(pcie, skb, p->timestamp); 1454f4845741SJimmy Assarsson len = can_get_echo_skb(can->can.dev, echo_idx, NULL); 1455954fb212SJimmy Assarsson count = FIELD_GET(KVASER_PCIEFD_KCAN_TX_NR_PACKETS_CURRENT_MASK, 1456f4845741SJimmy Assarsson ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG)); 145726ad340eSHenning Colliander 14586fdcd64eSJimmy Assarsson if (count < can->can.echo_skb_max && netif_queue_stopped(can->can.dev)) 145926ad340eSHenning Colliander netif_wake_queue(can->can.dev); 146026ad340eSHenning Colliander 146126ad340eSHenning Colliander if (!one_shot_fail) { 1462f4845741SJimmy Assarsson can->can.dev->stats.tx_bytes += len; 1463f4845741SJimmy Assarsson can->can.dev->stats.tx_packets++; 146426ad340eSHenning Colliander } 146526ad340eSHenning Colliander } 146626ad340eSHenning Colliander 146726ad340eSHenning Colliander return 0; 146826ad340eSHenning Colliander } 146926ad340eSHenning Colliander 147026ad340eSHenning Colliander static int kvaser_pciefd_handle_eflush_packet(struct kvaser_pciefd *pcie, 147126ad340eSHenning Colliander struct kvaser_pciefd_rx_packet *p) 147226ad340eSHenning Colliander { 147326ad340eSHenning Colliander struct kvaser_pciefd_can *can; 1474954fb212SJimmy Assarsson u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]); 147526ad340eSHenning Colliander 147626ad340eSHenning Colliander if (ch_id >= pcie->nr_channels) 147726ad340eSHenning Colliander return -EIO; 147826ad340eSHenning Colliander 147926ad340eSHenning Colliander can = pcie->can[ch_id]; 148026ad340eSHenning Colliander 148126ad340eSHenning Colliander if (!completion_done(&can->flush_comp)) 148226ad340eSHenning Colliander complete(&can->flush_comp); 148326ad340eSHenning Colliander 148426ad340eSHenning Colliander return 0; 148526ad340eSHenning Colliander } 148626ad340eSHenning Colliander 148726ad340eSHenning Colliander static int kvaser_pciefd_read_packet(struct kvaser_pciefd *pcie, int *start_pos, 148826ad340eSHenning Colliander int dma_buf) 148926ad340eSHenning Colliander { 149026ad340eSHenning Colliander __le32 *buffer = pcie->dma_data[dma_buf]; 149126ad340eSHenning Colliander __le64 timestamp; 149226ad340eSHenning Colliander struct kvaser_pciefd_rx_packet packet; 149326ad340eSHenning Colliander struct kvaser_pciefd_rx_packet *p = &packet; 149426ad340eSHenning Colliander u8 type; 149526ad340eSHenning Colliander int pos = *start_pos; 149626ad340eSHenning Colliander int size; 149726ad340eSHenning Colliander int ret = 0; 149826ad340eSHenning Colliander 149926ad340eSHenning Colliander size = le32_to_cpu(buffer[pos++]); 150026ad340eSHenning Colliander if (!size) { 150126ad340eSHenning Colliander *start_pos = 0; 150226ad340eSHenning Colliander return 0; 150326ad340eSHenning Colliander } 150426ad340eSHenning Colliander 150526ad340eSHenning Colliander p->header[0] = le32_to_cpu(buffer[pos++]); 150626ad340eSHenning Colliander p->header[1] = le32_to_cpu(buffer[pos++]); 150726ad340eSHenning Colliander 150826ad340eSHenning Colliander /* Read 64-bit timestamp */ 150926ad340eSHenning Colliander memcpy(×tamp, &buffer[pos], sizeof(__le64)); 151026ad340eSHenning Colliander pos += 2; 151126ad340eSHenning Colliander p->timestamp = le64_to_cpu(timestamp); 151226ad340eSHenning Colliander 1513954fb212SJimmy Assarsson type = FIELD_GET(KVASER_PCIEFD_PACKET_TYPE_MASK, p->header[1]); 151426ad340eSHenning Colliander switch (type) { 151526ad340eSHenning Colliander case KVASER_PCIEFD_PACK_TYPE_DATA: 151626ad340eSHenning Colliander ret = kvaser_pciefd_handle_data_packet(pcie, p, &buffer[pos]); 151726ad340eSHenning Colliander if (!(p->header[0] & KVASER_PCIEFD_RPACKET_RTR)) { 151826ad340eSHenning Colliander u8 data_len; 151926ad340eSHenning Colliander 1520954fb212SJimmy Assarsson data_len = can_fd_dlc2len(FIELD_GET(KVASER_PCIEFD_RPACKET_DLC_MASK, 1521954fb212SJimmy Assarsson p->header[1])); 152226ad340eSHenning Colliander pos += DIV_ROUND_UP(data_len, 4); 152326ad340eSHenning Colliander } 152426ad340eSHenning Colliander break; 152526ad340eSHenning Colliander 152626ad340eSHenning Colliander case KVASER_PCIEFD_PACK_TYPE_ACK: 152726ad340eSHenning Colliander ret = kvaser_pciefd_handle_ack_packet(pcie, p); 152826ad340eSHenning Colliander break; 152926ad340eSHenning Colliander 153026ad340eSHenning Colliander case KVASER_PCIEFD_PACK_TYPE_STATUS: 153126ad340eSHenning Colliander ret = kvaser_pciefd_handle_status_packet(pcie, p); 153226ad340eSHenning Colliander break; 153326ad340eSHenning Colliander 153426ad340eSHenning Colliander case KVASER_PCIEFD_PACK_TYPE_ERROR: 153526ad340eSHenning Colliander ret = kvaser_pciefd_handle_error_packet(pcie, p); 153626ad340eSHenning Colliander break; 153726ad340eSHenning Colliander 153826ad340eSHenning Colliander case KVASER_PCIEFD_PACK_TYPE_EFLUSH_ACK: 153926ad340eSHenning Colliander ret = kvaser_pciefd_handle_eflush_packet(pcie, p); 154026ad340eSHenning Colliander break; 154126ad340eSHenning Colliander 154226ad340eSHenning Colliander case KVASER_PCIEFD_PACK_TYPE_ACK_DATA: 154326ad340eSHenning Colliander case KVASER_PCIEFD_PACK_TYPE_BUS_LOAD: 154476c66ddfSJimmy Assarsson case KVASER_PCIEFD_PACK_TYPE_EFRAME_ACK: 154526ad340eSHenning Colliander case KVASER_PCIEFD_PACK_TYPE_TXRQ: 154626ad340eSHenning Colliander dev_info(&pcie->pci->dev, 154726ad340eSHenning Colliander "Received unexpected packet type 0x%08X\n", type); 154826ad340eSHenning Colliander break; 154926ad340eSHenning Colliander 155026ad340eSHenning Colliander default: 155126ad340eSHenning Colliander dev_err(&pcie->pci->dev, "Unknown packet type 0x%08X\n", type); 155226ad340eSHenning Colliander ret = -EIO; 155326ad340eSHenning Colliander break; 155426ad340eSHenning Colliander } 155526ad340eSHenning Colliander 155626ad340eSHenning Colliander if (ret) 155726ad340eSHenning Colliander return ret; 155826ad340eSHenning Colliander 155926ad340eSHenning Colliander /* Position does not point to the end of the package, 156026ad340eSHenning Colliander * corrupted packet size? 156126ad340eSHenning Colliander */ 156226ad340eSHenning Colliander if ((*start_pos + size) != pos) 156326ad340eSHenning Colliander return -EIO; 156426ad340eSHenning Colliander 156526ad340eSHenning Colliander /* Point to the next packet header, if any */ 156626ad340eSHenning Colliander *start_pos = pos; 156726ad340eSHenning Colliander 156826ad340eSHenning Colliander return ret; 156926ad340eSHenning Colliander } 157026ad340eSHenning Colliander 157126ad340eSHenning Colliander static int kvaser_pciefd_read_buffer(struct kvaser_pciefd *pcie, int dma_buf) 157226ad340eSHenning Colliander { 157326ad340eSHenning Colliander int pos = 0; 157426ad340eSHenning Colliander int res = 0; 157526ad340eSHenning Colliander 157626ad340eSHenning Colliander do { 157726ad340eSHenning Colliander res = kvaser_pciefd_read_packet(pcie, &pos, dma_buf); 157826ad340eSHenning Colliander } while (!res && pos > 0 && pos < KVASER_PCIEFD_DMA_SIZE); 157926ad340eSHenning Colliander 158026ad340eSHenning Colliander return res; 158126ad340eSHenning Colliander } 158226ad340eSHenning Colliander 158324aecf55SJimmy Assarsson static void kvaser_pciefd_receive_irq(struct kvaser_pciefd *pcie) 158426ad340eSHenning Colliander { 1585c2ad8129SJimmy Assarsson u32 irq = ioread32(KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_IRQ_REG); 158626ad340eSHenning Colliander 158726ad340eSHenning Colliander if (irq & KVASER_PCIEFD_SRB_IRQ_DPD0) { 158826ad340eSHenning Colliander kvaser_pciefd_read_buffer(pcie, 0); 158926ad340eSHenning Colliander /* Reset DMA buffer 0 */ 159026ad340eSHenning Colliander iowrite32(KVASER_PCIEFD_SRB_CMD_RDB0, 1591c2ad8129SJimmy Assarsson KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG); 159226ad340eSHenning Colliander } 159326ad340eSHenning Colliander 159426ad340eSHenning Colliander if (irq & KVASER_PCIEFD_SRB_IRQ_DPD1) { 159526ad340eSHenning Colliander kvaser_pciefd_read_buffer(pcie, 1); 159626ad340eSHenning Colliander /* Reset DMA buffer 1 */ 159726ad340eSHenning Colliander iowrite32(KVASER_PCIEFD_SRB_CMD_RDB1, 1598c2ad8129SJimmy Assarsson KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG); 159926ad340eSHenning Colliander } 160026ad340eSHenning Colliander 160126ad340eSHenning Colliander if (irq & KVASER_PCIEFD_SRB_IRQ_DOF0 || 160226ad340eSHenning Colliander irq & KVASER_PCIEFD_SRB_IRQ_DOF1 || 160326ad340eSHenning Colliander irq & KVASER_PCIEFD_SRB_IRQ_DUF0 || 160426ad340eSHenning Colliander irq & KVASER_PCIEFD_SRB_IRQ_DUF1) 160526ad340eSHenning Colliander dev_err(&pcie->pci->dev, "DMA IRQ error 0x%08X\n", irq); 160626ad340eSHenning Colliander 1607c2ad8129SJimmy Assarsson iowrite32(irq, KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_IRQ_REG); 160826ad340eSHenning Colliander } 160926ad340eSHenning Colliander 161024aecf55SJimmy Assarsson static void kvaser_pciefd_transmit_irq(struct kvaser_pciefd_can *can) 161126ad340eSHenning Colliander { 161226ad340eSHenning Colliander u32 irq = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); 161326ad340eSHenning Colliander 161426ad340eSHenning Colliander if (irq & KVASER_PCIEFD_KCAN_IRQ_TOF) 161526ad340eSHenning Colliander netdev_err(can->can.dev, "Tx FIFO overflow\n"); 161626ad340eSHenning Colliander 161726ad340eSHenning Colliander if (irq & KVASER_PCIEFD_KCAN_IRQ_BPP) 161826ad340eSHenning Colliander netdev_err(can->can.dev, 161926ad340eSHenning Colliander "Fail to change bittiming, when not in reset mode\n"); 162026ad340eSHenning Colliander 162126ad340eSHenning Colliander if (irq & KVASER_PCIEFD_KCAN_IRQ_FDIC) 162226ad340eSHenning Colliander netdev_err(can->can.dev, "CAN FD frame in CAN mode\n"); 162326ad340eSHenning Colliander 162426ad340eSHenning Colliander if (irq & KVASER_PCIEFD_KCAN_IRQ_ROF) 162526ad340eSHenning Colliander netdev_err(can->can.dev, "Rx FIFO overflow\n"); 162626ad340eSHenning Colliander 162726ad340eSHenning Colliander iowrite32(irq, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); 162826ad340eSHenning Colliander } 162926ad340eSHenning Colliander 163026ad340eSHenning Colliander static irqreturn_t kvaser_pciefd_irq_handler(int irq, void *dev) 163126ad340eSHenning Colliander { 163226ad340eSHenning Colliander struct kvaser_pciefd *pcie = (struct kvaser_pciefd *)dev; 1633c2ad8129SJimmy Assarsson const struct kvaser_pciefd_irq_mask *irq_mask = pcie->driver_data->irq_mask; 1634*00e4c694SMartin Jocic u32 pci_irq = ioread32(KVASER_PCIEFD_PCI_IRQ_ADDR(pcie)); 163526ad340eSHenning Colliander int i; 163626ad340eSHenning Colliander 1637*00e4c694SMartin Jocic if (!(pci_irq & irq_mask->all)) 163826ad340eSHenning Colliander return IRQ_NONE; 163926ad340eSHenning Colliander 1640*00e4c694SMartin Jocic if (pci_irq & irq_mask->kcan_rx0) 164126ad340eSHenning Colliander kvaser_pciefd_receive_irq(pcie); 164226ad340eSHenning Colliander 164326ad340eSHenning Colliander for (i = 0; i < pcie->nr_channels; i++) { 1644*00e4c694SMartin Jocic if (pci_irq & irq_mask->kcan_tx[i]) 164526ad340eSHenning Colliander kvaser_pciefd_transmit_irq(pcie->can[i]); 164626ad340eSHenning Colliander } 164726ad340eSHenning Colliander 164826ad340eSHenning Colliander return IRQ_HANDLED; 164926ad340eSHenning Colliander } 165026ad340eSHenning Colliander 165126ad340eSHenning Colliander static void kvaser_pciefd_teardown_can_ctrls(struct kvaser_pciefd *pcie) 165226ad340eSHenning Colliander { 165326ad340eSHenning Colliander int i; 165426ad340eSHenning Colliander 165526ad340eSHenning Colliander for (i = 0; i < pcie->nr_channels; i++) { 1656f4845741SJimmy Assarsson struct kvaser_pciefd_can *can = pcie->can[i]; 1657f4845741SJimmy Assarsson 165826ad340eSHenning Colliander if (can) { 1659f4845741SJimmy Assarsson iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); 166026ad340eSHenning Colliander kvaser_pciefd_pwm_stop(can); 166126ad340eSHenning Colliander free_candev(can->can.dev); 166226ad340eSHenning Colliander } 166326ad340eSHenning Colliander } 166426ad340eSHenning Colliander } 166526ad340eSHenning Colliander 166626ad340eSHenning Colliander static int kvaser_pciefd_probe(struct pci_dev *pdev, 166726ad340eSHenning Colliander const struct pci_device_id *id) 166826ad340eSHenning Colliander { 166926ad340eSHenning Colliander int err; 167026ad340eSHenning Colliander struct kvaser_pciefd *pcie; 1671c2ad8129SJimmy Assarsson const struct kvaser_pciefd_irq_mask *irq_mask; 1672c2ad8129SJimmy Assarsson void __iomem *irq_en_base; 167326ad340eSHenning Colliander 167426ad340eSHenning Colliander pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL); 167526ad340eSHenning Colliander if (!pcie) 167626ad340eSHenning Colliander return -ENOMEM; 167726ad340eSHenning Colliander 167826ad340eSHenning Colliander pci_set_drvdata(pdev, pcie); 167926ad340eSHenning Colliander pcie->pci = pdev; 1680c2ad8129SJimmy Assarsson pcie->driver_data = (const struct kvaser_pciefd_driver_data *)id->driver_data; 1681c2ad8129SJimmy Assarsson irq_mask = pcie->driver_data->irq_mask; 168226ad340eSHenning Colliander 168326ad340eSHenning Colliander err = pci_enable_device(pdev); 168426ad340eSHenning Colliander if (err) 168526ad340eSHenning Colliander return err; 168626ad340eSHenning Colliander 168726ad340eSHenning Colliander err = pci_request_regions(pdev, KVASER_PCIEFD_DRV_NAME); 168826ad340eSHenning Colliander if (err) 168926ad340eSHenning Colliander goto err_disable_pci; 169026ad340eSHenning Colliander 169126ad340eSHenning Colliander pcie->reg_base = pci_iomap(pdev, 0, 0); 169226ad340eSHenning Colliander if (!pcie->reg_base) { 169326ad340eSHenning Colliander err = -ENOMEM; 169426ad340eSHenning Colliander goto err_release_regions; 169526ad340eSHenning Colliander } 169626ad340eSHenning Colliander 169726ad340eSHenning Colliander err = kvaser_pciefd_setup_board(pcie); 169826ad340eSHenning Colliander if (err) 169926ad340eSHenning Colliander goto err_pci_iounmap; 170026ad340eSHenning Colliander 170126ad340eSHenning Colliander err = kvaser_pciefd_setup_dma(pcie); 170226ad340eSHenning Colliander if (err) 170326ad340eSHenning Colliander goto err_pci_iounmap; 170426ad340eSHenning Colliander 170526ad340eSHenning Colliander pci_set_master(pdev); 170626ad340eSHenning Colliander 170726ad340eSHenning Colliander err = kvaser_pciefd_setup_can_ctrls(pcie); 170826ad340eSHenning Colliander if (err) 170926ad340eSHenning Colliander goto err_teardown_can_ctrls; 171026ad340eSHenning Colliander 171184762d8dSJimmy Assarsson err = request_irq(pcie->pci->irq, kvaser_pciefd_irq_handler, 171284762d8dSJimmy Assarsson IRQF_SHARED, KVASER_PCIEFD_DRV_NAME, pcie); 171384762d8dSJimmy Assarsson if (err) 171484762d8dSJimmy Assarsson goto err_teardown_can_ctrls; 171584762d8dSJimmy Assarsson 171626ad340eSHenning Colliander iowrite32(KVASER_PCIEFD_SRB_IRQ_DPD0 | KVASER_PCIEFD_SRB_IRQ_DPD1, 1717c2ad8129SJimmy Assarsson KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_IRQ_REG); 171826ad340eSHenning Colliander 171926ad340eSHenning Colliander iowrite32(KVASER_PCIEFD_SRB_IRQ_DPD0 | KVASER_PCIEFD_SRB_IRQ_DPD1 | 172026ad340eSHenning Colliander KVASER_PCIEFD_SRB_IRQ_DOF0 | KVASER_PCIEFD_SRB_IRQ_DOF1 | 172126ad340eSHenning Colliander KVASER_PCIEFD_SRB_IRQ_DUF0 | KVASER_PCIEFD_SRB_IRQ_DUF1, 1722c2ad8129SJimmy Assarsson KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_IEN_REG); 172326ad340eSHenning Colliander 17247c921556SJimmy Assarsson /* Enable PCI interrupts */ 1725c2ad8129SJimmy Assarsson irq_en_base = KVASER_PCIEFD_PCI_IEN_ADDR(pcie); 1726c2ad8129SJimmy Assarsson iowrite32(irq_mask->all, irq_en_base); 172726ad340eSHenning Colliander /* Ready the DMA buffers */ 172826ad340eSHenning Colliander iowrite32(KVASER_PCIEFD_SRB_CMD_RDB0, 1729c2ad8129SJimmy Assarsson KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG); 173026ad340eSHenning Colliander iowrite32(KVASER_PCIEFD_SRB_CMD_RDB1, 1731c2ad8129SJimmy Assarsson KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CMD_REG); 173226ad340eSHenning Colliander 173326ad340eSHenning Colliander err = kvaser_pciefd_reg_candev(pcie); 173426ad340eSHenning Colliander if (err) 173526ad340eSHenning Colliander goto err_free_irq; 173626ad340eSHenning Colliander 173726ad340eSHenning Colliander return 0; 173826ad340eSHenning Colliander 173926ad340eSHenning Colliander err_free_irq: 174011164bc3SJimmy Assarsson /* Disable PCI interrupts */ 1741c2ad8129SJimmy Assarsson iowrite32(0, irq_en_base); 174226ad340eSHenning Colliander free_irq(pcie->pci->irq, pcie); 174326ad340eSHenning Colliander 174426ad340eSHenning Colliander err_teardown_can_ctrls: 174526ad340eSHenning Colliander kvaser_pciefd_teardown_can_ctrls(pcie); 1746c2ad8129SJimmy Assarsson iowrite32(0, KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CTRL_REG); 174726ad340eSHenning Colliander pci_clear_master(pdev); 174826ad340eSHenning Colliander 174926ad340eSHenning Colliander err_pci_iounmap: 175026ad340eSHenning Colliander pci_iounmap(pdev, pcie->reg_base); 175126ad340eSHenning Colliander 175226ad340eSHenning Colliander err_release_regions: 175326ad340eSHenning Colliander pci_release_regions(pdev); 175426ad340eSHenning Colliander 175526ad340eSHenning Colliander err_disable_pci: 175626ad340eSHenning Colliander pci_disable_device(pdev); 175726ad340eSHenning Colliander 175826ad340eSHenning Colliander return err; 175926ad340eSHenning Colliander } 176026ad340eSHenning Colliander 176126ad340eSHenning Colliander static void kvaser_pciefd_remove_all_ctrls(struct kvaser_pciefd *pcie) 176226ad340eSHenning Colliander { 176326ad340eSHenning Colliander int i; 176426ad340eSHenning Colliander 176526ad340eSHenning Colliander for (i = 0; i < pcie->nr_channels; i++) { 1766f4845741SJimmy Assarsson struct kvaser_pciefd_can *can = pcie->can[i]; 1767f4845741SJimmy Assarsson 176826ad340eSHenning Colliander if (can) { 1769f4845741SJimmy Assarsson iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); 177026ad340eSHenning Colliander unregister_candev(can->can.dev); 177126ad340eSHenning Colliander del_timer(&can->bec_poll_timer); 177226ad340eSHenning Colliander kvaser_pciefd_pwm_stop(can); 177326ad340eSHenning Colliander free_candev(can->can.dev); 177426ad340eSHenning Colliander } 177526ad340eSHenning Colliander } 177626ad340eSHenning Colliander } 177726ad340eSHenning Colliander 177826ad340eSHenning Colliander static void kvaser_pciefd_remove(struct pci_dev *pdev) 177926ad340eSHenning Colliander { 178026ad340eSHenning Colliander struct kvaser_pciefd *pcie = pci_get_drvdata(pdev); 178126ad340eSHenning Colliander 178226ad340eSHenning Colliander kvaser_pciefd_remove_all_ctrls(pcie); 178326ad340eSHenning Colliander 17847c921556SJimmy Assarsson /* Disable interrupts */ 1785c2ad8129SJimmy Assarsson iowrite32(0, KVASER_PCIEFD_SRB_ADDR(pcie) + KVASER_PCIEFD_SRB_CTRL_REG); 1786c2ad8129SJimmy Assarsson iowrite32(0, KVASER_PCIEFD_PCI_IEN_ADDR(pcie)); 178726ad340eSHenning Colliander 178826ad340eSHenning Colliander free_irq(pcie->pci->irq, pcie); 178926ad340eSHenning Colliander 179026ad340eSHenning Colliander pci_iounmap(pdev, pcie->reg_base); 179126ad340eSHenning Colliander pci_release_regions(pdev); 179226ad340eSHenning Colliander pci_disable_device(pdev); 179326ad340eSHenning Colliander } 179426ad340eSHenning Colliander 179526ad340eSHenning Colliander static struct pci_driver kvaser_pciefd = { 179626ad340eSHenning Colliander .name = KVASER_PCIEFD_DRV_NAME, 179726ad340eSHenning Colliander .id_table = kvaser_pciefd_id_table, 179826ad340eSHenning Colliander .probe = kvaser_pciefd_probe, 179926ad340eSHenning Colliander .remove = kvaser_pciefd_remove, 180026ad340eSHenning Colliander }; 180126ad340eSHenning Colliander 180226ad340eSHenning Colliander module_pci_driver(kvaser_pciefd) 1803