18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause 28c2ecf20Sopenharmony_ci/* Copyright (C) 2018 KVASER AB, Sweden. All rights reserved. 38c2ecf20Sopenharmony_ci * Parts of this driver are based on the following: 48c2ecf20Sopenharmony_ci * - Kvaser linux pciefd driver (version 5.25) 58c2ecf20Sopenharmony_ci * - PEAK linux canfd driver 68c2ecf20Sopenharmony_ci * - Altera Avalon EPCS flash controller driver 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/kernel.h> 108c2ecf20Sopenharmony_ci#include <linux/module.h> 118c2ecf20Sopenharmony_ci#include <linux/device.h> 128c2ecf20Sopenharmony_ci#include <linux/pci.h> 138c2ecf20Sopenharmony_ci#include <linux/can/dev.h> 148c2ecf20Sopenharmony_ci#include <linux/timer.h> 158c2ecf20Sopenharmony_ci#include <linux/netdevice.h> 168c2ecf20Sopenharmony_ci#include <linux/crc32.h> 178c2ecf20Sopenharmony_ci#include <linux/iopoll.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL"); 208c2ecf20Sopenharmony_ciMODULE_AUTHOR("Kvaser AB <support@kvaser.com>"); 218c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices"); 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_DRV_NAME "kvaser_pciefd" 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_WAIT_TIMEOUT msecs_to_jiffies(1000) 268c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_BEC_POLL_FREQ (jiffies + msecs_to_jiffies(200)) 278c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_MAX_ERR_REP 256 288c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_CAN_TX_MAX_COUNT 17 298c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_MAX_CAN_CHANNELS 4 308c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_DMA_COUNT 2 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_DMA_SIZE (4 * 1024) 338c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_64BIT_DMA_BIT BIT(0) 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_VENDOR 0x1a07 368c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_4HS_ID 0x0d 378c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_2HS_ID 0x0e 388c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_HS_ID 0x0f 398c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_MINIPCIE_HS_ID 0x10 408c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_MINIPCIE_2HS_ID 0x11 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci/* PCIe IRQ registers */ 438c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_IRQ_REG 0x40 448c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_IEN_REG 0x50 458c2ecf20Sopenharmony_ci/* DMA map */ 468c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_DMA_MAP_BASE 0x1000 478c2ecf20Sopenharmony_ci/* Kvaser KCAN CAN controller registers */ 488c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN0_BASE 0x10000 498c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_BASE_OFFSET 0x1000 508c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_FIFO_REG 0x100 518c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_FIFO_LAST_REG 0x180 528c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_CTRL_REG 0x2c0 538c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_CMD_REG 0x400 548c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_IEN_REG 0x408 558c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_IRQ_REG 0x410 568c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_TX_NPACKETS_REG 0x414 578c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_STAT_REG 0x418 588c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_MODE_REG 0x41c 598c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_BTRN_REG 0x420 608c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_BUS_LOAD_REG 0x424 618c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_BTRD_REG 0x428 628c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_PWM_REG 0x430 638c2ecf20Sopenharmony_ci/* Loopback control register */ 648c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_LOOP_REG 0x1f000 658c2ecf20Sopenharmony_ci/* System identification and information registers */ 668c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SYSID_BASE 0x1f020 678c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SYSID_VERSION_REG (KVASER_PCIEFD_SYSID_BASE + 0x8) 688c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SYSID_CANFREQ_REG (KVASER_PCIEFD_SYSID_BASE + 0xc) 698c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SYSID_BUSFREQ_REG (KVASER_PCIEFD_SYSID_BASE + 0x10) 708c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SYSID_BUILD_REG (KVASER_PCIEFD_SYSID_BASE + 0x14) 718c2ecf20Sopenharmony_ci/* Shared receive buffer registers */ 728c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_BASE 0x1f200 738c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_FIFO_LAST_REG (KVASER_PCIEFD_SRB_BASE + 0x1f4) 748c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_CMD_REG (KVASER_PCIEFD_SRB_BASE + 0x200) 758c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_IEN_REG (KVASER_PCIEFD_SRB_BASE + 0x204) 768c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_IRQ_REG (KVASER_PCIEFD_SRB_BASE + 0x20c) 778c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_STAT_REG (KVASER_PCIEFD_SRB_BASE + 0x210) 788c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG (KVASER_PCIEFD_SRB_BASE + 0x214) 798c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_CTRL_REG (KVASER_PCIEFD_SRB_BASE + 0x218) 808c2ecf20Sopenharmony_ci/* EPCS flash controller registers */ 818c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPI_BASE 0x1fc00 828c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPI_RX_REG KVASER_PCIEFD_SPI_BASE 838c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPI_TX_REG (KVASER_PCIEFD_SPI_BASE + 0x4) 848c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPI_STATUS_REG (KVASER_PCIEFD_SPI_BASE + 0x8) 858c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPI_CTRL_REG (KVASER_PCIEFD_SPI_BASE + 0xc) 868c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPI_SSEL_REG (KVASER_PCIEFD_SPI_BASE + 0x14) 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_IRQ_ALL_MSK 0x1f 898c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_IRQ_SRB BIT(4) 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SYSID_NRCHAN_SHIFT 24 928c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SYSID_MAJOR_VER_SHIFT 16 938c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SYSID_BUILD_VER_SHIFT 1 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci/* Reset DMA buffer 0, 1 and FIFO offset */ 968c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_CMD_RDB0 BIT(4) 978c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_CMD_RDB1 BIT(5) 988c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_CMD_FOR BIT(0) 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci/* DMA packet done, buffer 0 and 1 */ 1018c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_IRQ_DPD0 BIT(8) 1028c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_IRQ_DPD1 BIT(9) 1038c2ecf20Sopenharmony_ci/* DMA overflow, buffer 0 and 1 */ 1048c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_IRQ_DOF0 BIT(10) 1058c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_IRQ_DOF1 BIT(11) 1068c2ecf20Sopenharmony_ci/* DMA underflow, buffer 0 and 1 */ 1078c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_IRQ_DUF0 BIT(12) 1088c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_IRQ_DUF1 BIT(13) 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci/* DMA idle */ 1118c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_STAT_DI BIT(15) 1128c2ecf20Sopenharmony_ci/* DMA support */ 1138c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_STAT_DMA BIT(24) 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci/* SRB current packet level */ 1168c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK 0xff 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci/* DMA Enable */ 1198c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SRB_CTRL_DMA_ENABLE BIT(0) 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci/* EPCS flash controller definitions */ 1228c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_CFG_IMG_SZ (64 * 1024) 1238c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_CFG_IMG_OFFSET (31 * 65536L) 1248c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_CFG_MAX_PARAMS 256 1258c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_CFG_MAGIC 0xcafef00d 1268c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_CFG_PARAM_MAX_SZ 24 1278c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_CFG_SYS_VER 1 1288c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_CFG_PARAM_NR_CHAN 130 1298c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPI_TMT BIT(5) 1308c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPI_TRDY BIT(6) 1318c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPI_RRDY BIT(7) 1328c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_FLASH_ID_EPCS16 0x14 1338c2ecf20Sopenharmony_ci/* Commands for controlling the onboard flash */ 1348c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_FLASH_RES_CMD 0xab 1358c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_FLASH_READ_CMD 0x3 1368c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_FLASH_STATUS_CMD 0x5 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci/* Kvaser KCAN definitions */ 1398c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_CTRL_EFLUSH (4 << 29) 1408c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_CTRL_EFRAME (5 << 29) 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT 16 1438c2ecf20Sopenharmony_ci/* Request status packet */ 1448c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_CMD_SRQ BIT(0) 1458c2ecf20Sopenharmony_ci/* Abort, flush and reset */ 1468c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_CMD_AT BIT(1) 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci/* Tx FIFO unaligned read */ 1498c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_IRQ_TAR BIT(0) 1508c2ecf20Sopenharmony_ci/* Tx FIFO unaligned end */ 1518c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_IRQ_TAE BIT(1) 1528c2ecf20Sopenharmony_ci/* Bus parameter protection error */ 1538c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_IRQ_BPP BIT(2) 1548c2ecf20Sopenharmony_ci/* FDF bit when controller is in classic mode */ 1558c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_IRQ_FDIC BIT(3) 1568c2ecf20Sopenharmony_ci/* Rx FIFO overflow */ 1578c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_IRQ_ROF BIT(5) 1588c2ecf20Sopenharmony_ci/* Abort done */ 1598c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_IRQ_ABD BIT(13) 1608c2ecf20Sopenharmony_ci/* Tx buffer flush done */ 1618c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_IRQ_TFD BIT(14) 1628c2ecf20Sopenharmony_ci/* Tx FIFO overflow */ 1638c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_IRQ_TOF BIT(15) 1648c2ecf20Sopenharmony_ci/* Tx FIFO empty */ 1658c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_IRQ_TE BIT(16) 1668c2ecf20Sopenharmony_ci/* Transmitter unaligned */ 1678c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_IRQ_TAL BIT(17) 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_TX_NPACKETS_MAX_SHIFT 16 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_STAT_SEQNO_SHIFT 24 1728c2ecf20Sopenharmony_ci/* Abort request */ 1738c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_STAT_AR BIT(7) 1748c2ecf20Sopenharmony_ci/* Idle state. Controller in reset mode and no abort or flush pending */ 1758c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_STAT_IDLE BIT(10) 1768c2ecf20Sopenharmony_ci/* Bus off */ 1778c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_STAT_BOFF BIT(11) 1788c2ecf20Sopenharmony_ci/* Reset mode request */ 1798c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_STAT_RMR BIT(14) 1808c2ecf20Sopenharmony_ci/* Controller in reset mode */ 1818c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_STAT_IRM BIT(15) 1828c2ecf20Sopenharmony_ci/* Controller got one-shot capability */ 1838c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_STAT_CAP BIT(16) 1848c2ecf20Sopenharmony_ci/* Controller got CAN FD capability */ 1858c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_STAT_FD BIT(19) 1868c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_STAT_BUS_OFF_MSK (KVASER_PCIEFD_KCAN_STAT_AR | \ 1878c2ecf20Sopenharmony_ci KVASER_PCIEFD_KCAN_STAT_BOFF | KVASER_PCIEFD_KCAN_STAT_RMR | \ 1888c2ecf20Sopenharmony_ci KVASER_PCIEFD_KCAN_STAT_IRM) 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci/* Reset mode */ 1918c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_MODE_RM BIT(8) 1928c2ecf20Sopenharmony_ci/* Listen only mode */ 1938c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_MODE_LOM BIT(9) 1948c2ecf20Sopenharmony_ci/* Error packet enable */ 1958c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_MODE_EPEN BIT(12) 1968c2ecf20Sopenharmony_ci/* CAN FD non-ISO */ 1978c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_MODE_NIFDEN BIT(15) 1988c2ecf20Sopenharmony_ci/* Acknowledgment packet type */ 1998c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_MODE_APT BIT(20) 2008c2ecf20Sopenharmony_ci/* Active error flag enable. Clear to force error passive */ 2018c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_MODE_EEN BIT(23) 2028c2ecf20Sopenharmony_ci/* Classic CAN mode */ 2038c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_MODE_CCM BIT(31) 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_BTRN_SJW_SHIFT 13 2068c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_BTRN_TSEG1_SHIFT 17 2078c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_BTRN_TSEG2_SHIFT 26 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT 16 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci/* Kvaser KCAN packet types */ 2128c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_PACK_TYPE_DATA 0 2138c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_PACK_TYPE_ACK 1 2148c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_PACK_TYPE_TXRQ 2 2158c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_PACK_TYPE_ERROR 3 2168c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_PACK_TYPE_EFLUSH_ACK 4 2178c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_PACK_TYPE_EFRAME_ACK 5 2188c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_PACK_TYPE_ACK_DATA 6 2198c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_PACK_TYPE_STATUS 8 2208c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_PACK_TYPE_BUS_LOAD 9 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci/* Kvaser KCAN packet common definitions */ 2238c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_PACKET_SEQ_MSK 0xff 2248c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_PACKET_CHID_SHIFT 25 2258c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_PACKET_TYPE_SHIFT 28 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci/* Kvaser KCAN TDATA and RDATA first word */ 2288c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_RPACKET_IDE BIT(30) 2298c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_RPACKET_RTR BIT(29) 2308c2ecf20Sopenharmony_ci/* Kvaser KCAN TDATA and RDATA second word */ 2318c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_RPACKET_ESI BIT(13) 2328c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_RPACKET_BRS BIT(14) 2338c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_RPACKET_FDF BIT(15) 2348c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_RPACKET_DLC_SHIFT 8 2358c2ecf20Sopenharmony_ci/* Kvaser KCAN TDATA second word */ 2368c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_TPACKET_SMS BIT(16) 2378c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_TPACKET_AREQ BIT(31) 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci/* Kvaser KCAN APACKET */ 2408c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_APACKET_FLU BIT(8) 2418c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_APACKET_CT BIT(9) 2428c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_APACKET_ABL BIT(10) 2438c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_APACKET_NACK BIT(11) 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci/* Kvaser KCAN SPACK first word */ 2468c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPACK_RXERR_SHIFT 8 2478c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPACK_BOFF BIT(16) 2488c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPACK_IDET BIT(20) 2498c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPACK_IRM BIT(21) 2508c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPACK_RMCD BIT(22) 2518c2ecf20Sopenharmony_ci/* Kvaser KCAN SPACK second word */ 2528c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPACK_AUTO BIT(21) 2538c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPACK_EWLR BIT(23) 2548c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_SPACK_EPLR BIT(24) 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci/* Kvaser KCAN_EPACK second word */ 2578c2ecf20Sopenharmony_ci#define KVASER_PCIEFD_EPACK_DIR_TX BIT(0) 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_cistruct kvaser_pciefd; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_cistruct kvaser_pciefd_can { 2628c2ecf20Sopenharmony_ci struct can_priv can; 2638c2ecf20Sopenharmony_ci struct kvaser_pciefd *kv_pcie; 2648c2ecf20Sopenharmony_ci void __iomem *reg_base; 2658c2ecf20Sopenharmony_ci struct can_berr_counter bec; 2668c2ecf20Sopenharmony_ci u8 cmd_seq; 2678c2ecf20Sopenharmony_ci int err_rep_cnt; 2688c2ecf20Sopenharmony_ci int echo_idx; 2698c2ecf20Sopenharmony_ci spinlock_t lock; /* Locks sensitive registers (e.g. MODE) */ 2708c2ecf20Sopenharmony_ci spinlock_t echo_lock; /* Locks the message echo buffer */ 2718c2ecf20Sopenharmony_ci struct timer_list bec_poll_timer; 2728c2ecf20Sopenharmony_ci struct completion start_comp, flush_comp; 2738c2ecf20Sopenharmony_ci}; 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_cistruct kvaser_pciefd { 2768c2ecf20Sopenharmony_ci struct pci_dev *pci; 2778c2ecf20Sopenharmony_ci void __iomem *reg_base; 2788c2ecf20Sopenharmony_ci struct kvaser_pciefd_can *can[KVASER_PCIEFD_MAX_CAN_CHANNELS]; 2798c2ecf20Sopenharmony_ci void *dma_data[KVASER_PCIEFD_DMA_COUNT]; 2808c2ecf20Sopenharmony_ci u8 nr_channels; 2818c2ecf20Sopenharmony_ci u32 bus_freq; 2828c2ecf20Sopenharmony_ci u32 freq; 2838c2ecf20Sopenharmony_ci u32 freq_to_ticks_div; 2848c2ecf20Sopenharmony_ci}; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_cistruct kvaser_pciefd_rx_packet { 2878c2ecf20Sopenharmony_ci u32 header[2]; 2888c2ecf20Sopenharmony_ci u64 timestamp; 2898c2ecf20Sopenharmony_ci}; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_cistruct kvaser_pciefd_tx_packet { 2928c2ecf20Sopenharmony_ci u32 header[2]; 2938c2ecf20Sopenharmony_ci u8 data[64]; 2948c2ecf20Sopenharmony_ci}; 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_cistatic const struct can_bittiming_const kvaser_pciefd_bittiming_const = { 2978c2ecf20Sopenharmony_ci .name = KVASER_PCIEFD_DRV_NAME, 2988c2ecf20Sopenharmony_ci .tseg1_min = 1, 2998c2ecf20Sopenharmony_ci .tseg1_max = 512, 3008c2ecf20Sopenharmony_ci .tseg2_min = 1, 3018c2ecf20Sopenharmony_ci .tseg2_max = 32, 3028c2ecf20Sopenharmony_ci .sjw_max = 16, 3038c2ecf20Sopenharmony_ci .brp_min = 1, 3048c2ecf20Sopenharmony_ci .brp_max = 8192, 3058c2ecf20Sopenharmony_ci .brp_inc = 1, 3068c2ecf20Sopenharmony_ci}; 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_cistruct kvaser_pciefd_cfg_param { 3098c2ecf20Sopenharmony_ci __le32 magic; 3108c2ecf20Sopenharmony_ci __le32 nr; 3118c2ecf20Sopenharmony_ci __le32 len; 3128c2ecf20Sopenharmony_ci u8 data[KVASER_PCIEFD_CFG_PARAM_MAX_SZ]; 3138c2ecf20Sopenharmony_ci}; 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_cistruct kvaser_pciefd_cfg_img { 3168c2ecf20Sopenharmony_ci __le32 version; 3178c2ecf20Sopenharmony_ci __le32 magic; 3188c2ecf20Sopenharmony_ci __le32 crc; 3198c2ecf20Sopenharmony_ci struct kvaser_pciefd_cfg_param params[KVASER_PCIEFD_CFG_MAX_PARAMS]; 3208c2ecf20Sopenharmony_ci}; 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_cistatic struct pci_device_id kvaser_pciefd_id_table[] = { 3238c2ecf20Sopenharmony_ci { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_4HS_ID), }, 3248c2ecf20Sopenharmony_ci { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_2HS_ID), }, 3258c2ecf20Sopenharmony_ci { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_HS_ID), }, 3268c2ecf20Sopenharmony_ci { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_HS_ID), }, 3278c2ecf20Sopenharmony_ci { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_2HS_ID), }, 3288c2ecf20Sopenharmony_ci { 0,}, 3298c2ecf20Sopenharmony_ci}; 3308c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, kvaser_pciefd_id_table); 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci/* Onboard flash memory functions */ 3338c2ecf20Sopenharmony_cistatic int kvaser_pciefd_spi_wait_loop(struct kvaser_pciefd *pcie, int msk) 3348c2ecf20Sopenharmony_ci{ 3358c2ecf20Sopenharmony_ci u32 res; 3368c2ecf20Sopenharmony_ci int ret; 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci ret = readl_poll_timeout(pcie->reg_base + KVASER_PCIEFD_SPI_STATUS_REG, 3398c2ecf20Sopenharmony_ci res, res & msk, 0, 10); 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci return ret; 3428c2ecf20Sopenharmony_ci} 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_cistatic int kvaser_pciefd_spi_cmd(struct kvaser_pciefd *pcie, const u8 *tx, 3458c2ecf20Sopenharmony_ci u32 tx_len, u8 *rx, u32 rx_len) 3468c2ecf20Sopenharmony_ci{ 3478c2ecf20Sopenharmony_ci int c; 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci iowrite32(BIT(0), pcie->reg_base + KVASER_PCIEFD_SPI_SSEL_REG); 3508c2ecf20Sopenharmony_ci iowrite32(BIT(10), pcie->reg_base + KVASER_PCIEFD_SPI_CTRL_REG); 3518c2ecf20Sopenharmony_ci ioread32(pcie->reg_base + KVASER_PCIEFD_SPI_RX_REG); 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci c = tx_len; 3548c2ecf20Sopenharmony_ci while (c--) { 3558c2ecf20Sopenharmony_ci if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_TRDY)) 3568c2ecf20Sopenharmony_ci return -EIO; 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci iowrite32(*tx++, pcie->reg_base + KVASER_PCIEFD_SPI_TX_REG); 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_RRDY)) 3618c2ecf20Sopenharmony_ci return -EIO; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci ioread32(pcie->reg_base + KVASER_PCIEFD_SPI_RX_REG); 3648c2ecf20Sopenharmony_ci } 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci c = rx_len; 3678c2ecf20Sopenharmony_ci while (c-- > 0) { 3688c2ecf20Sopenharmony_ci if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_TRDY)) 3698c2ecf20Sopenharmony_ci return -EIO; 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SPI_TX_REG); 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_RRDY)) 3748c2ecf20Sopenharmony_ci return -EIO; 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci *rx++ = ioread32(pcie->reg_base + KVASER_PCIEFD_SPI_RX_REG); 3778c2ecf20Sopenharmony_ci } 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_TMT)) 3808c2ecf20Sopenharmony_ci return -EIO; 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SPI_CTRL_REG); 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci if (c != -1) { 3858c2ecf20Sopenharmony_ci dev_err(&pcie->pci->dev, "Flash SPI transfer failed\n"); 3868c2ecf20Sopenharmony_ci return -EIO; 3878c2ecf20Sopenharmony_ci } 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci return 0; 3908c2ecf20Sopenharmony_ci} 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_cistatic int kvaser_pciefd_cfg_read_and_verify(struct kvaser_pciefd *pcie, 3938c2ecf20Sopenharmony_ci struct kvaser_pciefd_cfg_img *img) 3948c2ecf20Sopenharmony_ci{ 3958c2ecf20Sopenharmony_ci int offset = KVASER_PCIEFD_CFG_IMG_OFFSET; 3968c2ecf20Sopenharmony_ci int res, crc; 3978c2ecf20Sopenharmony_ci u8 *crc_buff; 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci u8 cmd[] = { 4008c2ecf20Sopenharmony_ci KVASER_PCIEFD_FLASH_READ_CMD, 4018c2ecf20Sopenharmony_ci (u8)((offset >> 16) & 0xff), 4028c2ecf20Sopenharmony_ci (u8)((offset >> 8) & 0xff), 4038c2ecf20Sopenharmony_ci (u8)(offset & 0xff) 4048c2ecf20Sopenharmony_ci }; 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci res = kvaser_pciefd_spi_cmd(pcie, cmd, ARRAY_SIZE(cmd), (u8 *)img, 4078c2ecf20Sopenharmony_ci KVASER_PCIEFD_CFG_IMG_SZ); 4088c2ecf20Sopenharmony_ci if (res) 4098c2ecf20Sopenharmony_ci return res; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci crc_buff = (u8 *)img->params; 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci if (le32_to_cpu(img->version) != KVASER_PCIEFD_CFG_SYS_VER) { 4148c2ecf20Sopenharmony_ci dev_err(&pcie->pci->dev, 4158c2ecf20Sopenharmony_ci "Config flash corrupted, version number is wrong\n"); 4168c2ecf20Sopenharmony_ci return -ENODEV; 4178c2ecf20Sopenharmony_ci } 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci if (le32_to_cpu(img->magic) != KVASER_PCIEFD_CFG_MAGIC) { 4208c2ecf20Sopenharmony_ci dev_err(&pcie->pci->dev, 4218c2ecf20Sopenharmony_ci "Config flash corrupted, magic number is wrong\n"); 4228c2ecf20Sopenharmony_ci return -ENODEV; 4238c2ecf20Sopenharmony_ci } 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci crc = ~crc32_be(0xffffffff, crc_buff, sizeof(img->params)); 4268c2ecf20Sopenharmony_ci if (le32_to_cpu(img->crc) != crc) { 4278c2ecf20Sopenharmony_ci dev_err(&pcie->pci->dev, 4288c2ecf20Sopenharmony_ci "Stored CRC does not match flash image contents\n"); 4298c2ecf20Sopenharmony_ci return -EIO; 4308c2ecf20Sopenharmony_ci } 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci return 0; 4338c2ecf20Sopenharmony_ci} 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_cistatic void kvaser_pciefd_cfg_read_params(struct kvaser_pciefd *pcie, 4368c2ecf20Sopenharmony_ci struct kvaser_pciefd_cfg_img *img) 4378c2ecf20Sopenharmony_ci{ 4388c2ecf20Sopenharmony_ci struct kvaser_pciefd_cfg_param *param; 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci param = &img->params[KVASER_PCIEFD_CFG_PARAM_NR_CHAN]; 4418c2ecf20Sopenharmony_ci memcpy(&pcie->nr_channels, param->data, le32_to_cpu(param->len)); 4428c2ecf20Sopenharmony_ci} 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_cistatic int kvaser_pciefd_read_cfg(struct kvaser_pciefd *pcie) 4458c2ecf20Sopenharmony_ci{ 4468c2ecf20Sopenharmony_ci int res; 4478c2ecf20Sopenharmony_ci struct kvaser_pciefd_cfg_img *img; 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ci /* Read electronic signature */ 4508c2ecf20Sopenharmony_ci u8 cmd[] = {KVASER_PCIEFD_FLASH_RES_CMD, 0, 0, 0}; 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci res = kvaser_pciefd_spi_cmd(pcie, cmd, ARRAY_SIZE(cmd), cmd, 1); 4538c2ecf20Sopenharmony_ci if (res) 4548c2ecf20Sopenharmony_ci return -EIO; 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci img = kmalloc(KVASER_PCIEFD_CFG_IMG_SZ, GFP_KERNEL); 4578c2ecf20Sopenharmony_ci if (!img) 4588c2ecf20Sopenharmony_ci return -ENOMEM; 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci if (cmd[0] != KVASER_PCIEFD_FLASH_ID_EPCS16) { 4618c2ecf20Sopenharmony_ci dev_err(&pcie->pci->dev, 4628c2ecf20Sopenharmony_ci "Flash id is 0x%x instead of expected EPCS16 (0x%x)\n", 4638c2ecf20Sopenharmony_ci cmd[0], KVASER_PCIEFD_FLASH_ID_EPCS16); 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci res = -ENODEV; 4668c2ecf20Sopenharmony_ci goto image_free; 4678c2ecf20Sopenharmony_ci } 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci cmd[0] = KVASER_PCIEFD_FLASH_STATUS_CMD; 4708c2ecf20Sopenharmony_ci res = kvaser_pciefd_spi_cmd(pcie, cmd, 1, cmd, 1); 4718c2ecf20Sopenharmony_ci if (res) { 4728c2ecf20Sopenharmony_ci goto image_free; 4738c2ecf20Sopenharmony_ci } else if (cmd[0] & 1) { 4748c2ecf20Sopenharmony_ci res = -EIO; 4758c2ecf20Sopenharmony_ci /* No write is ever done, the WIP should never be set */ 4768c2ecf20Sopenharmony_ci dev_err(&pcie->pci->dev, "Unexpected WIP bit set in flash\n"); 4778c2ecf20Sopenharmony_ci goto image_free; 4788c2ecf20Sopenharmony_ci } 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci res = kvaser_pciefd_cfg_read_and_verify(pcie, img); 4818c2ecf20Sopenharmony_ci if (res) { 4828c2ecf20Sopenharmony_ci res = -EIO; 4838c2ecf20Sopenharmony_ci goto image_free; 4848c2ecf20Sopenharmony_ci } 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci kvaser_pciefd_cfg_read_params(pcie, img); 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ciimage_free: 4898c2ecf20Sopenharmony_ci kfree(img); 4908c2ecf20Sopenharmony_ci return res; 4918c2ecf20Sopenharmony_ci} 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_cistatic void kvaser_pciefd_request_status(struct kvaser_pciefd_can *can) 4948c2ecf20Sopenharmony_ci{ 4958c2ecf20Sopenharmony_ci u32 cmd; 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci cmd = KVASER_PCIEFD_KCAN_CMD_SRQ; 4988c2ecf20Sopenharmony_ci cmd |= ++can->cmd_seq << KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT; 4998c2ecf20Sopenharmony_ci iowrite32(cmd, can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG); 5008c2ecf20Sopenharmony_ci} 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_cistatic void kvaser_pciefd_enable_err_gen(struct kvaser_pciefd_can *can) 5038c2ecf20Sopenharmony_ci{ 5048c2ecf20Sopenharmony_ci u32 mode; 5058c2ecf20Sopenharmony_ci unsigned long irq; 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci spin_lock_irqsave(&can->lock, irq); 5088c2ecf20Sopenharmony_ci mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); 5098c2ecf20Sopenharmony_ci if (!(mode & KVASER_PCIEFD_KCAN_MODE_EPEN)) { 5108c2ecf20Sopenharmony_ci mode |= KVASER_PCIEFD_KCAN_MODE_EPEN; 5118c2ecf20Sopenharmony_ci iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); 5128c2ecf20Sopenharmony_ci } 5138c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&can->lock, irq); 5148c2ecf20Sopenharmony_ci} 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_cistatic void kvaser_pciefd_disable_err_gen(struct kvaser_pciefd_can *can) 5178c2ecf20Sopenharmony_ci{ 5188c2ecf20Sopenharmony_ci u32 mode; 5198c2ecf20Sopenharmony_ci unsigned long irq; 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci spin_lock_irqsave(&can->lock, irq); 5228c2ecf20Sopenharmony_ci mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); 5238c2ecf20Sopenharmony_ci mode &= ~KVASER_PCIEFD_KCAN_MODE_EPEN; 5248c2ecf20Sopenharmony_ci iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); 5258c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&can->lock, irq); 5268c2ecf20Sopenharmony_ci} 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_cistatic int kvaser_pciefd_set_tx_irq(struct kvaser_pciefd_can *can) 5298c2ecf20Sopenharmony_ci{ 5308c2ecf20Sopenharmony_ci u32 msk; 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci msk = KVASER_PCIEFD_KCAN_IRQ_TE | KVASER_PCIEFD_KCAN_IRQ_ROF | 5338c2ecf20Sopenharmony_ci KVASER_PCIEFD_KCAN_IRQ_TOF | KVASER_PCIEFD_KCAN_IRQ_ABD | 5348c2ecf20Sopenharmony_ci KVASER_PCIEFD_KCAN_IRQ_TAE | KVASER_PCIEFD_KCAN_IRQ_TAL | 5358c2ecf20Sopenharmony_ci KVASER_PCIEFD_KCAN_IRQ_FDIC | KVASER_PCIEFD_KCAN_IRQ_BPP | 5368c2ecf20Sopenharmony_ci KVASER_PCIEFD_KCAN_IRQ_TAR; 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci iowrite32(msk, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci return 0; 5418c2ecf20Sopenharmony_ci} 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_cistatic void kvaser_pciefd_setup_controller(struct kvaser_pciefd_can *can) 5448c2ecf20Sopenharmony_ci{ 5458c2ecf20Sopenharmony_ci u32 mode; 5468c2ecf20Sopenharmony_ci unsigned long irq; 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci spin_lock_irqsave(&can->lock, irq); 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); 5518c2ecf20Sopenharmony_ci if (can->can.ctrlmode & CAN_CTRLMODE_FD) { 5528c2ecf20Sopenharmony_ci mode &= ~KVASER_PCIEFD_KCAN_MODE_CCM; 5538c2ecf20Sopenharmony_ci if (can->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO) 5548c2ecf20Sopenharmony_ci mode |= KVASER_PCIEFD_KCAN_MODE_NIFDEN; 5558c2ecf20Sopenharmony_ci else 5568c2ecf20Sopenharmony_ci mode &= ~KVASER_PCIEFD_KCAN_MODE_NIFDEN; 5578c2ecf20Sopenharmony_ci } else { 5588c2ecf20Sopenharmony_ci mode |= KVASER_PCIEFD_KCAN_MODE_CCM; 5598c2ecf20Sopenharmony_ci mode &= ~KVASER_PCIEFD_KCAN_MODE_NIFDEN; 5608c2ecf20Sopenharmony_ci } 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci if (can->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) 5638c2ecf20Sopenharmony_ci mode |= KVASER_PCIEFD_KCAN_MODE_LOM; 5648c2ecf20Sopenharmony_ci else 5658c2ecf20Sopenharmony_ci mode &= ~KVASER_PCIEFD_KCAN_MODE_LOM; 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci mode |= KVASER_PCIEFD_KCAN_MODE_EEN; 5688c2ecf20Sopenharmony_ci mode |= KVASER_PCIEFD_KCAN_MODE_EPEN; 5698c2ecf20Sopenharmony_ci /* Use ACK packet type */ 5708c2ecf20Sopenharmony_ci mode &= ~KVASER_PCIEFD_KCAN_MODE_APT; 5718c2ecf20Sopenharmony_ci mode &= ~KVASER_PCIEFD_KCAN_MODE_RM; 5728c2ecf20Sopenharmony_ci iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&can->lock, irq); 5758c2ecf20Sopenharmony_ci} 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_cistatic void kvaser_pciefd_start_controller_flush(struct kvaser_pciefd_can *can) 5788c2ecf20Sopenharmony_ci{ 5798c2ecf20Sopenharmony_ci u32 status; 5808c2ecf20Sopenharmony_ci unsigned long irq; 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci spin_lock_irqsave(&can->lock, irq); 5838c2ecf20Sopenharmony_ci iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); 5848c2ecf20Sopenharmony_ci iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD, 5858c2ecf20Sopenharmony_ci can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG); 5888c2ecf20Sopenharmony_ci if (status & KVASER_PCIEFD_KCAN_STAT_IDLE) { 5898c2ecf20Sopenharmony_ci u32 cmd; 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci /* If controller is already idle, run abort, flush and reset */ 5928c2ecf20Sopenharmony_ci cmd = KVASER_PCIEFD_KCAN_CMD_AT; 5938c2ecf20Sopenharmony_ci cmd |= ++can->cmd_seq << KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT; 5948c2ecf20Sopenharmony_ci iowrite32(cmd, can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG); 5958c2ecf20Sopenharmony_ci } else if (!(status & KVASER_PCIEFD_KCAN_STAT_RMR)) { 5968c2ecf20Sopenharmony_ci u32 mode; 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci /* Put controller in reset mode */ 5998c2ecf20Sopenharmony_ci mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); 6008c2ecf20Sopenharmony_ci mode |= KVASER_PCIEFD_KCAN_MODE_RM; 6018c2ecf20Sopenharmony_ci iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); 6028c2ecf20Sopenharmony_ci } 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&can->lock, irq); 6058c2ecf20Sopenharmony_ci} 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_cistatic int kvaser_pciefd_bus_on(struct kvaser_pciefd_can *can) 6088c2ecf20Sopenharmony_ci{ 6098c2ecf20Sopenharmony_ci u32 mode; 6108c2ecf20Sopenharmony_ci unsigned long irq; 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci del_timer(&can->bec_poll_timer); 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci if (!completion_done(&can->flush_comp)) 6158c2ecf20Sopenharmony_ci kvaser_pciefd_start_controller_flush(can); 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci if (!wait_for_completion_timeout(&can->flush_comp, 6188c2ecf20Sopenharmony_ci KVASER_PCIEFD_WAIT_TIMEOUT)) { 6198c2ecf20Sopenharmony_ci netdev_err(can->can.dev, "Timeout during bus on flush\n"); 6208c2ecf20Sopenharmony_ci return -ETIMEDOUT; 6218c2ecf20Sopenharmony_ci } 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci spin_lock_irqsave(&can->lock, irq); 6248c2ecf20Sopenharmony_ci iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); 6258c2ecf20Sopenharmony_ci iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD, 6288c2ecf20Sopenharmony_ci can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_ci mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); 6318c2ecf20Sopenharmony_ci mode &= ~KVASER_PCIEFD_KCAN_MODE_RM; 6328c2ecf20Sopenharmony_ci iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); 6338c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&can->lock, irq); 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci if (!wait_for_completion_timeout(&can->start_comp, 6368c2ecf20Sopenharmony_ci KVASER_PCIEFD_WAIT_TIMEOUT)) { 6378c2ecf20Sopenharmony_ci netdev_err(can->can.dev, "Timeout during bus on reset\n"); 6388c2ecf20Sopenharmony_ci return -ETIMEDOUT; 6398c2ecf20Sopenharmony_ci } 6408c2ecf20Sopenharmony_ci /* Reset interrupt handling */ 6418c2ecf20Sopenharmony_ci iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); 6428c2ecf20Sopenharmony_ci iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci kvaser_pciefd_set_tx_irq(can); 6458c2ecf20Sopenharmony_ci kvaser_pciefd_setup_controller(can); 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci can->can.state = CAN_STATE_ERROR_ACTIVE; 6488c2ecf20Sopenharmony_ci netif_wake_queue(can->can.dev); 6498c2ecf20Sopenharmony_ci can->bec.txerr = 0; 6508c2ecf20Sopenharmony_ci can->bec.rxerr = 0; 6518c2ecf20Sopenharmony_ci can->err_rep_cnt = 0; 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_ci return 0; 6548c2ecf20Sopenharmony_ci} 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_cistatic void kvaser_pciefd_pwm_stop(struct kvaser_pciefd_can *can) 6578c2ecf20Sopenharmony_ci{ 6588c2ecf20Sopenharmony_ci u8 top; 6598c2ecf20Sopenharmony_ci u32 pwm_ctrl; 6608c2ecf20Sopenharmony_ci unsigned long irq; 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci spin_lock_irqsave(&can->lock, irq); 6638c2ecf20Sopenharmony_ci pwm_ctrl = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG); 6648c2ecf20Sopenharmony_ci top = (pwm_ctrl >> KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT) & 0xff; 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci /* Set duty cycle to zero */ 6678c2ecf20Sopenharmony_ci pwm_ctrl |= top; 6688c2ecf20Sopenharmony_ci iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG); 6698c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&can->lock, irq); 6708c2ecf20Sopenharmony_ci} 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_cistatic void kvaser_pciefd_pwm_start(struct kvaser_pciefd_can *can) 6738c2ecf20Sopenharmony_ci{ 6748c2ecf20Sopenharmony_ci int top, trigger; 6758c2ecf20Sopenharmony_ci u32 pwm_ctrl; 6768c2ecf20Sopenharmony_ci unsigned long irq; 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_ci kvaser_pciefd_pwm_stop(can); 6798c2ecf20Sopenharmony_ci spin_lock_irqsave(&can->lock, irq); 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci /* Set frequency to 500 KHz*/ 6828c2ecf20Sopenharmony_ci top = can->kv_pcie->bus_freq / (2 * 500000) - 1; 6838c2ecf20Sopenharmony_ci 6848c2ecf20Sopenharmony_ci pwm_ctrl = top & 0xff; 6858c2ecf20Sopenharmony_ci pwm_ctrl |= (top & 0xff) << KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT; 6868c2ecf20Sopenharmony_ci iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG); 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci /* Set duty cycle to 95 */ 6898c2ecf20Sopenharmony_ci trigger = (100 * top - 95 * (top + 1) + 50) / 100; 6908c2ecf20Sopenharmony_ci pwm_ctrl = trigger & 0xff; 6918c2ecf20Sopenharmony_ci pwm_ctrl |= (top & 0xff) << KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT; 6928c2ecf20Sopenharmony_ci iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG); 6938c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&can->lock, irq); 6948c2ecf20Sopenharmony_ci} 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_cistatic int kvaser_pciefd_open(struct net_device *netdev) 6978c2ecf20Sopenharmony_ci{ 6988c2ecf20Sopenharmony_ci int err; 6998c2ecf20Sopenharmony_ci struct kvaser_pciefd_can *can = netdev_priv(netdev); 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci err = open_candev(netdev); 7028c2ecf20Sopenharmony_ci if (err) 7038c2ecf20Sopenharmony_ci return err; 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci err = kvaser_pciefd_bus_on(can); 7068c2ecf20Sopenharmony_ci if (err) { 7078c2ecf20Sopenharmony_ci close_candev(netdev); 7088c2ecf20Sopenharmony_ci return err; 7098c2ecf20Sopenharmony_ci } 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci return 0; 7128c2ecf20Sopenharmony_ci} 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_cistatic int kvaser_pciefd_stop(struct net_device *netdev) 7158c2ecf20Sopenharmony_ci{ 7168c2ecf20Sopenharmony_ci struct kvaser_pciefd_can *can = netdev_priv(netdev); 7178c2ecf20Sopenharmony_ci int ret = 0; 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci /* Don't interrupt ongoing flush */ 7208c2ecf20Sopenharmony_ci if (!completion_done(&can->flush_comp)) 7218c2ecf20Sopenharmony_ci kvaser_pciefd_start_controller_flush(can); 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci if (!wait_for_completion_timeout(&can->flush_comp, 7248c2ecf20Sopenharmony_ci KVASER_PCIEFD_WAIT_TIMEOUT)) { 7258c2ecf20Sopenharmony_ci netdev_err(can->can.dev, "Timeout during stop\n"); 7268c2ecf20Sopenharmony_ci ret = -ETIMEDOUT; 7278c2ecf20Sopenharmony_ci } else { 7288c2ecf20Sopenharmony_ci iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); 7298c2ecf20Sopenharmony_ci del_timer(&can->bec_poll_timer); 7308c2ecf20Sopenharmony_ci } 7318c2ecf20Sopenharmony_ci can->can.state = CAN_STATE_STOPPED; 7328c2ecf20Sopenharmony_ci close_candev(netdev); 7338c2ecf20Sopenharmony_ci 7348c2ecf20Sopenharmony_ci return ret; 7358c2ecf20Sopenharmony_ci} 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_cistatic int kvaser_pciefd_prepare_tx_packet(struct kvaser_pciefd_tx_packet *p, 7388c2ecf20Sopenharmony_ci struct kvaser_pciefd_can *can, 7398c2ecf20Sopenharmony_ci struct sk_buff *skb) 7408c2ecf20Sopenharmony_ci{ 7418c2ecf20Sopenharmony_ci struct canfd_frame *cf = (struct canfd_frame *)skb->data; 7428c2ecf20Sopenharmony_ci int packet_size; 7438c2ecf20Sopenharmony_ci int seq = can->echo_idx; 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci memset(p, 0, sizeof(*p)); 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci if (can->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT) 7488c2ecf20Sopenharmony_ci p->header[1] |= KVASER_PCIEFD_TPACKET_SMS; 7498c2ecf20Sopenharmony_ci 7508c2ecf20Sopenharmony_ci if (cf->can_id & CAN_RTR_FLAG) 7518c2ecf20Sopenharmony_ci p->header[0] |= KVASER_PCIEFD_RPACKET_RTR; 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci if (cf->can_id & CAN_EFF_FLAG) 7548c2ecf20Sopenharmony_ci p->header[0] |= KVASER_PCIEFD_RPACKET_IDE; 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci p->header[0] |= cf->can_id & CAN_EFF_MASK; 7578c2ecf20Sopenharmony_ci p->header[1] |= can_len2dlc(cf->len) << KVASER_PCIEFD_RPACKET_DLC_SHIFT; 7588c2ecf20Sopenharmony_ci p->header[1] |= KVASER_PCIEFD_TPACKET_AREQ; 7598c2ecf20Sopenharmony_ci 7608c2ecf20Sopenharmony_ci if (can_is_canfd_skb(skb)) { 7618c2ecf20Sopenharmony_ci p->header[1] |= KVASER_PCIEFD_RPACKET_FDF; 7628c2ecf20Sopenharmony_ci if (cf->flags & CANFD_BRS) 7638c2ecf20Sopenharmony_ci p->header[1] |= KVASER_PCIEFD_RPACKET_BRS; 7648c2ecf20Sopenharmony_ci if (cf->flags & CANFD_ESI) 7658c2ecf20Sopenharmony_ci p->header[1] |= KVASER_PCIEFD_RPACKET_ESI; 7668c2ecf20Sopenharmony_ci } 7678c2ecf20Sopenharmony_ci 7688c2ecf20Sopenharmony_ci p->header[1] |= seq & KVASER_PCIEFD_PACKET_SEQ_MSK; 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_ci packet_size = cf->len; 7718c2ecf20Sopenharmony_ci memcpy(p->data, cf->data, packet_size); 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci return DIV_ROUND_UP(packet_size, 4); 7748c2ecf20Sopenharmony_ci} 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_cistatic netdev_tx_t kvaser_pciefd_start_xmit(struct sk_buff *skb, 7778c2ecf20Sopenharmony_ci struct net_device *netdev) 7788c2ecf20Sopenharmony_ci{ 7798c2ecf20Sopenharmony_ci struct kvaser_pciefd_can *can = netdev_priv(netdev); 7808c2ecf20Sopenharmony_ci unsigned long irq_flags; 7818c2ecf20Sopenharmony_ci struct kvaser_pciefd_tx_packet packet; 7828c2ecf20Sopenharmony_ci int nwords; 7838c2ecf20Sopenharmony_ci u8 count; 7848c2ecf20Sopenharmony_ci 7858c2ecf20Sopenharmony_ci if (can_dropped_invalid_skb(netdev, skb)) 7868c2ecf20Sopenharmony_ci return NETDEV_TX_OK; 7878c2ecf20Sopenharmony_ci 7888c2ecf20Sopenharmony_ci nwords = kvaser_pciefd_prepare_tx_packet(&packet, can, skb); 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci spin_lock_irqsave(&can->echo_lock, irq_flags); 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_ci /* Prepare and save echo skb in internal slot */ 7938c2ecf20Sopenharmony_ci can_put_echo_skb(skb, netdev, can->echo_idx); 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci /* Move echo index to the next slot */ 7968c2ecf20Sopenharmony_ci can->echo_idx = (can->echo_idx + 1) % can->can.echo_skb_max; 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_ci /* Write header to fifo */ 7998c2ecf20Sopenharmony_ci iowrite32(packet.header[0], 8008c2ecf20Sopenharmony_ci can->reg_base + KVASER_PCIEFD_KCAN_FIFO_REG); 8018c2ecf20Sopenharmony_ci iowrite32(packet.header[1], 8028c2ecf20Sopenharmony_ci can->reg_base + KVASER_PCIEFD_KCAN_FIFO_REG); 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ci if (nwords) { 8058c2ecf20Sopenharmony_ci u32 data_last = ((u32 *)packet.data)[nwords - 1]; 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci /* Write data to fifo, except last word */ 8088c2ecf20Sopenharmony_ci iowrite32_rep(can->reg_base + 8098c2ecf20Sopenharmony_ci KVASER_PCIEFD_KCAN_FIFO_REG, packet.data, 8108c2ecf20Sopenharmony_ci nwords - 1); 8118c2ecf20Sopenharmony_ci /* Write last word to end of fifo */ 8128c2ecf20Sopenharmony_ci __raw_writel(data_last, can->reg_base + 8138c2ecf20Sopenharmony_ci KVASER_PCIEFD_KCAN_FIFO_LAST_REG); 8148c2ecf20Sopenharmony_ci } else { 8158c2ecf20Sopenharmony_ci /* Complete write to fifo */ 8168c2ecf20Sopenharmony_ci __raw_writel(0, can->reg_base + 8178c2ecf20Sopenharmony_ci KVASER_PCIEFD_KCAN_FIFO_LAST_REG); 8188c2ecf20Sopenharmony_ci } 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_ci count = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NPACKETS_REG); 8218c2ecf20Sopenharmony_ci /* No room for a new message, stop the queue until at least one 8228c2ecf20Sopenharmony_ci * successful transmit 8238c2ecf20Sopenharmony_ci */ 8248c2ecf20Sopenharmony_ci if (count >= KVASER_PCIEFD_CAN_TX_MAX_COUNT || 8258c2ecf20Sopenharmony_ci can->can.echo_skb[can->echo_idx]) 8268c2ecf20Sopenharmony_ci netif_stop_queue(netdev); 8278c2ecf20Sopenharmony_ci 8288c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&can->echo_lock, irq_flags); 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_ci return NETDEV_TX_OK; 8318c2ecf20Sopenharmony_ci} 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_cistatic int kvaser_pciefd_set_bittiming(struct kvaser_pciefd_can *can, bool data) 8348c2ecf20Sopenharmony_ci{ 8358c2ecf20Sopenharmony_ci u32 mode, test, btrn; 8368c2ecf20Sopenharmony_ci unsigned long irq_flags; 8378c2ecf20Sopenharmony_ci int ret; 8388c2ecf20Sopenharmony_ci struct can_bittiming *bt; 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_ci if (data) 8418c2ecf20Sopenharmony_ci bt = &can->can.data_bittiming; 8428c2ecf20Sopenharmony_ci else 8438c2ecf20Sopenharmony_ci bt = &can->can.bittiming; 8448c2ecf20Sopenharmony_ci 8458c2ecf20Sopenharmony_ci btrn = ((bt->phase_seg2 - 1) & 0x1f) << 8468c2ecf20Sopenharmony_ci KVASER_PCIEFD_KCAN_BTRN_TSEG2_SHIFT | 8478c2ecf20Sopenharmony_ci (((bt->prop_seg + bt->phase_seg1) - 1) & 0x1ff) << 8488c2ecf20Sopenharmony_ci KVASER_PCIEFD_KCAN_BTRN_TSEG1_SHIFT | 8498c2ecf20Sopenharmony_ci ((bt->sjw - 1) & 0xf) << KVASER_PCIEFD_KCAN_BTRN_SJW_SHIFT | 8508c2ecf20Sopenharmony_ci ((bt->brp - 1) & 0x1fff); 8518c2ecf20Sopenharmony_ci 8528c2ecf20Sopenharmony_ci spin_lock_irqsave(&can->lock, irq_flags); 8538c2ecf20Sopenharmony_ci mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci /* Put the circuit in reset mode */ 8568c2ecf20Sopenharmony_ci iowrite32(mode | KVASER_PCIEFD_KCAN_MODE_RM, 8578c2ecf20Sopenharmony_ci can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci /* Can only set bittiming if in reset mode */ 8608c2ecf20Sopenharmony_ci ret = readl_poll_timeout(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG, 8618c2ecf20Sopenharmony_ci test, test & KVASER_PCIEFD_KCAN_MODE_RM, 8628c2ecf20Sopenharmony_ci 0, 10); 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci if (ret) { 8658c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&can->lock, irq_flags); 8668c2ecf20Sopenharmony_ci return -EBUSY; 8678c2ecf20Sopenharmony_ci } 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_ci if (data) 8708c2ecf20Sopenharmony_ci iowrite32(btrn, can->reg_base + KVASER_PCIEFD_KCAN_BTRD_REG); 8718c2ecf20Sopenharmony_ci else 8728c2ecf20Sopenharmony_ci iowrite32(btrn, can->reg_base + KVASER_PCIEFD_KCAN_BTRN_REG); 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_ci /* Restore previous reset mode status */ 8758c2ecf20Sopenharmony_ci iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&can->lock, irq_flags); 8788c2ecf20Sopenharmony_ci return 0; 8798c2ecf20Sopenharmony_ci} 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_cistatic int kvaser_pciefd_set_nominal_bittiming(struct net_device *ndev) 8828c2ecf20Sopenharmony_ci{ 8838c2ecf20Sopenharmony_ci return kvaser_pciefd_set_bittiming(netdev_priv(ndev), false); 8848c2ecf20Sopenharmony_ci} 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_cistatic int kvaser_pciefd_set_data_bittiming(struct net_device *ndev) 8878c2ecf20Sopenharmony_ci{ 8888c2ecf20Sopenharmony_ci return kvaser_pciefd_set_bittiming(netdev_priv(ndev), true); 8898c2ecf20Sopenharmony_ci} 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_cistatic int kvaser_pciefd_set_mode(struct net_device *ndev, enum can_mode mode) 8928c2ecf20Sopenharmony_ci{ 8938c2ecf20Sopenharmony_ci struct kvaser_pciefd_can *can = netdev_priv(ndev); 8948c2ecf20Sopenharmony_ci int ret = 0; 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_ci switch (mode) { 8978c2ecf20Sopenharmony_ci case CAN_MODE_START: 8988c2ecf20Sopenharmony_ci if (!can->can.restart_ms) 8998c2ecf20Sopenharmony_ci ret = kvaser_pciefd_bus_on(can); 9008c2ecf20Sopenharmony_ci break; 9018c2ecf20Sopenharmony_ci default: 9028c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 9038c2ecf20Sopenharmony_ci } 9048c2ecf20Sopenharmony_ci 9058c2ecf20Sopenharmony_ci return ret; 9068c2ecf20Sopenharmony_ci} 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_cistatic int kvaser_pciefd_get_berr_counter(const struct net_device *ndev, 9098c2ecf20Sopenharmony_ci struct can_berr_counter *bec) 9108c2ecf20Sopenharmony_ci{ 9118c2ecf20Sopenharmony_ci struct kvaser_pciefd_can *can = netdev_priv(ndev); 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_ci bec->rxerr = can->bec.rxerr; 9148c2ecf20Sopenharmony_ci bec->txerr = can->bec.txerr; 9158c2ecf20Sopenharmony_ci return 0; 9168c2ecf20Sopenharmony_ci} 9178c2ecf20Sopenharmony_ci 9188c2ecf20Sopenharmony_cistatic void kvaser_pciefd_bec_poll_timer(struct timer_list *data) 9198c2ecf20Sopenharmony_ci{ 9208c2ecf20Sopenharmony_ci struct kvaser_pciefd_can *can = from_timer(can, data, bec_poll_timer); 9218c2ecf20Sopenharmony_ci 9228c2ecf20Sopenharmony_ci kvaser_pciefd_enable_err_gen(can); 9238c2ecf20Sopenharmony_ci kvaser_pciefd_request_status(can); 9248c2ecf20Sopenharmony_ci can->err_rep_cnt = 0; 9258c2ecf20Sopenharmony_ci} 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_cistatic const struct net_device_ops kvaser_pciefd_netdev_ops = { 9288c2ecf20Sopenharmony_ci .ndo_open = kvaser_pciefd_open, 9298c2ecf20Sopenharmony_ci .ndo_stop = kvaser_pciefd_stop, 9308c2ecf20Sopenharmony_ci .ndo_start_xmit = kvaser_pciefd_start_xmit, 9318c2ecf20Sopenharmony_ci .ndo_change_mtu = can_change_mtu, 9328c2ecf20Sopenharmony_ci}; 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_cistatic int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie) 9358c2ecf20Sopenharmony_ci{ 9368c2ecf20Sopenharmony_ci int i; 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci for (i = 0; i < pcie->nr_channels; i++) { 9398c2ecf20Sopenharmony_ci struct net_device *netdev; 9408c2ecf20Sopenharmony_ci struct kvaser_pciefd_can *can; 9418c2ecf20Sopenharmony_ci u32 status, tx_npackets; 9428c2ecf20Sopenharmony_ci 9438c2ecf20Sopenharmony_ci netdev = alloc_candev(sizeof(struct kvaser_pciefd_can), 9448c2ecf20Sopenharmony_ci KVASER_PCIEFD_CAN_TX_MAX_COUNT); 9458c2ecf20Sopenharmony_ci if (!netdev) 9468c2ecf20Sopenharmony_ci return -ENOMEM; 9478c2ecf20Sopenharmony_ci 9488c2ecf20Sopenharmony_ci can = netdev_priv(netdev); 9498c2ecf20Sopenharmony_ci netdev->netdev_ops = &kvaser_pciefd_netdev_ops; 9508c2ecf20Sopenharmony_ci can->reg_base = pcie->reg_base + KVASER_PCIEFD_KCAN0_BASE + 9518c2ecf20Sopenharmony_ci i * KVASER_PCIEFD_KCAN_BASE_OFFSET; 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci can->kv_pcie = pcie; 9548c2ecf20Sopenharmony_ci can->cmd_seq = 0; 9558c2ecf20Sopenharmony_ci can->err_rep_cnt = 0; 9568c2ecf20Sopenharmony_ci can->bec.txerr = 0; 9578c2ecf20Sopenharmony_ci can->bec.rxerr = 0; 9588c2ecf20Sopenharmony_ci 9598c2ecf20Sopenharmony_ci init_completion(&can->start_comp); 9608c2ecf20Sopenharmony_ci init_completion(&can->flush_comp); 9618c2ecf20Sopenharmony_ci timer_setup(&can->bec_poll_timer, kvaser_pciefd_bec_poll_timer, 9628c2ecf20Sopenharmony_ci 0); 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_ci /* Disable Bus load reporting */ 9658c2ecf20Sopenharmony_ci iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_BUS_LOAD_REG); 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_ci tx_npackets = ioread32(can->reg_base + 9688c2ecf20Sopenharmony_ci KVASER_PCIEFD_KCAN_TX_NPACKETS_REG); 9698c2ecf20Sopenharmony_ci if (((tx_npackets >> KVASER_PCIEFD_KCAN_TX_NPACKETS_MAX_SHIFT) & 9708c2ecf20Sopenharmony_ci 0xff) < KVASER_PCIEFD_CAN_TX_MAX_COUNT) { 9718c2ecf20Sopenharmony_ci dev_err(&pcie->pci->dev, 9728c2ecf20Sopenharmony_ci "Max Tx count is smaller than expected\n"); 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_ci free_candev(netdev); 9758c2ecf20Sopenharmony_ci return -ENODEV; 9768c2ecf20Sopenharmony_ci } 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_ci can->can.clock.freq = pcie->freq; 9798c2ecf20Sopenharmony_ci can->can.echo_skb_max = KVASER_PCIEFD_CAN_TX_MAX_COUNT; 9808c2ecf20Sopenharmony_ci can->echo_idx = 0; 9818c2ecf20Sopenharmony_ci spin_lock_init(&can->echo_lock); 9828c2ecf20Sopenharmony_ci spin_lock_init(&can->lock); 9838c2ecf20Sopenharmony_ci can->can.bittiming_const = &kvaser_pciefd_bittiming_const; 9848c2ecf20Sopenharmony_ci can->can.data_bittiming_const = &kvaser_pciefd_bittiming_const; 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_ci can->can.do_set_bittiming = kvaser_pciefd_set_nominal_bittiming; 9878c2ecf20Sopenharmony_ci can->can.do_set_data_bittiming = 9888c2ecf20Sopenharmony_ci kvaser_pciefd_set_data_bittiming; 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_ci can->can.do_set_mode = kvaser_pciefd_set_mode; 9918c2ecf20Sopenharmony_ci can->can.do_get_berr_counter = kvaser_pciefd_get_berr_counter; 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_ci can->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY | 9948c2ecf20Sopenharmony_ci CAN_CTRLMODE_FD | 9958c2ecf20Sopenharmony_ci CAN_CTRLMODE_FD_NON_ISO; 9968c2ecf20Sopenharmony_ci 9978c2ecf20Sopenharmony_ci status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG); 9988c2ecf20Sopenharmony_ci if (!(status & KVASER_PCIEFD_KCAN_STAT_FD)) { 9998c2ecf20Sopenharmony_ci dev_err(&pcie->pci->dev, 10008c2ecf20Sopenharmony_ci "CAN FD not supported as expected %d\n", i); 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_ci free_candev(netdev); 10038c2ecf20Sopenharmony_ci return -ENODEV; 10048c2ecf20Sopenharmony_ci } 10058c2ecf20Sopenharmony_ci 10068c2ecf20Sopenharmony_ci if (status & KVASER_PCIEFD_KCAN_STAT_CAP) 10078c2ecf20Sopenharmony_ci can->can.ctrlmode_supported |= CAN_CTRLMODE_ONE_SHOT; 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_ci netdev->flags |= IFF_ECHO; 10108c2ecf20Sopenharmony_ci 10118c2ecf20Sopenharmony_ci SET_NETDEV_DEV(netdev, &pcie->pci->dev); 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); 10148c2ecf20Sopenharmony_ci iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD, 10158c2ecf20Sopenharmony_ci can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_ci pcie->can[i] = can; 10188c2ecf20Sopenharmony_ci kvaser_pciefd_pwm_start(can); 10198c2ecf20Sopenharmony_ci } 10208c2ecf20Sopenharmony_ci 10218c2ecf20Sopenharmony_ci return 0; 10228c2ecf20Sopenharmony_ci} 10238c2ecf20Sopenharmony_ci 10248c2ecf20Sopenharmony_cistatic int kvaser_pciefd_reg_candev(struct kvaser_pciefd *pcie) 10258c2ecf20Sopenharmony_ci{ 10268c2ecf20Sopenharmony_ci int i; 10278c2ecf20Sopenharmony_ci 10288c2ecf20Sopenharmony_ci for (i = 0; i < pcie->nr_channels; i++) { 10298c2ecf20Sopenharmony_ci int err = register_candev(pcie->can[i]->can.dev); 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_ci if (err) { 10328c2ecf20Sopenharmony_ci int j; 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_ci /* Unregister all successfully registered devices. */ 10358c2ecf20Sopenharmony_ci for (j = 0; j < i; j++) 10368c2ecf20Sopenharmony_ci unregister_candev(pcie->can[j]->can.dev); 10378c2ecf20Sopenharmony_ci return err; 10388c2ecf20Sopenharmony_ci } 10398c2ecf20Sopenharmony_ci } 10408c2ecf20Sopenharmony_ci 10418c2ecf20Sopenharmony_ci return 0; 10428c2ecf20Sopenharmony_ci} 10438c2ecf20Sopenharmony_ci 10448c2ecf20Sopenharmony_cistatic void kvaser_pciefd_write_dma_map(struct kvaser_pciefd *pcie, 10458c2ecf20Sopenharmony_ci dma_addr_t addr, int offset) 10468c2ecf20Sopenharmony_ci{ 10478c2ecf20Sopenharmony_ci u32 word1, word2; 10488c2ecf20Sopenharmony_ci 10498c2ecf20Sopenharmony_ci#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT 10508c2ecf20Sopenharmony_ci word1 = addr | KVASER_PCIEFD_64BIT_DMA_BIT; 10518c2ecf20Sopenharmony_ci word2 = addr >> 32; 10528c2ecf20Sopenharmony_ci#else 10538c2ecf20Sopenharmony_ci word1 = addr; 10548c2ecf20Sopenharmony_ci word2 = 0; 10558c2ecf20Sopenharmony_ci#endif 10568c2ecf20Sopenharmony_ci iowrite32(word1, pcie->reg_base + offset); 10578c2ecf20Sopenharmony_ci iowrite32(word2, pcie->reg_base + offset + 4); 10588c2ecf20Sopenharmony_ci} 10598c2ecf20Sopenharmony_ci 10608c2ecf20Sopenharmony_cistatic int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie) 10618c2ecf20Sopenharmony_ci{ 10628c2ecf20Sopenharmony_ci int i; 10638c2ecf20Sopenharmony_ci u32 srb_status; 10648c2ecf20Sopenharmony_ci u32 srb_packet_count; 10658c2ecf20Sopenharmony_ci dma_addr_t dma_addr[KVASER_PCIEFD_DMA_COUNT]; 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_ci /* Disable the DMA */ 10688c2ecf20Sopenharmony_ci iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SRB_CTRL_REG); 10698c2ecf20Sopenharmony_ci for (i = 0; i < KVASER_PCIEFD_DMA_COUNT; i++) { 10708c2ecf20Sopenharmony_ci unsigned int offset = KVASER_PCIEFD_DMA_MAP_BASE + 8 * i; 10718c2ecf20Sopenharmony_ci 10728c2ecf20Sopenharmony_ci pcie->dma_data[i] = 10738c2ecf20Sopenharmony_ci dmam_alloc_coherent(&pcie->pci->dev, 10748c2ecf20Sopenharmony_ci KVASER_PCIEFD_DMA_SIZE, 10758c2ecf20Sopenharmony_ci &dma_addr[i], 10768c2ecf20Sopenharmony_ci GFP_KERNEL); 10778c2ecf20Sopenharmony_ci 10788c2ecf20Sopenharmony_ci if (!pcie->dma_data[i] || !dma_addr[i]) { 10798c2ecf20Sopenharmony_ci dev_err(&pcie->pci->dev, "Rx dma_alloc(%u) failure\n", 10808c2ecf20Sopenharmony_ci KVASER_PCIEFD_DMA_SIZE); 10818c2ecf20Sopenharmony_ci return -ENOMEM; 10828c2ecf20Sopenharmony_ci } 10838c2ecf20Sopenharmony_ci 10848c2ecf20Sopenharmony_ci kvaser_pciefd_write_dma_map(pcie, dma_addr[i], offset); 10858c2ecf20Sopenharmony_ci } 10868c2ecf20Sopenharmony_ci 10878c2ecf20Sopenharmony_ci /* Reset Rx FIFO, and both DMA buffers */ 10888c2ecf20Sopenharmony_ci iowrite32(KVASER_PCIEFD_SRB_CMD_FOR | KVASER_PCIEFD_SRB_CMD_RDB0 | 10898c2ecf20Sopenharmony_ci KVASER_PCIEFD_SRB_CMD_RDB1, 10908c2ecf20Sopenharmony_ci pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG); 10918c2ecf20Sopenharmony_ci 10928c2ecf20Sopenharmony_ci /* Empty Rx FIFO */ 10938c2ecf20Sopenharmony_ci srb_packet_count = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG) & 10948c2ecf20Sopenharmony_ci KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK; 10958c2ecf20Sopenharmony_ci while (srb_packet_count) { 10968c2ecf20Sopenharmony_ci /* Drop current packet in FIFO */ 10978c2ecf20Sopenharmony_ci ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_FIFO_LAST_REG); 10988c2ecf20Sopenharmony_ci srb_packet_count--; 10998c2ecf20Sopenharmony_ci } 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci srb_status = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_STAT_REG); 11028c2ecf20Sopenharmony_ci if (!(srb_status & KVASER_PCIEFD_SRB_STAT_DI)) { 11038c2ecf20Sopenharmony_ci dev_err(&pcie->pci->dev, "DMA not idle before enabling\n"); 11048c2ecf20Sopenharmony_ci return -EIO; 11058c2ecf20Sopenharmony_ci } 11068c2ecf20Sopenharmony_ci 11078c2ecf20Sopenharmony_ci /* Enable the DMA */ 11088c2ecf20Sopenharmony_ci iowrite32(KVASER_PCIEFD_SRB_CTRL_DMA_ENABLE, 11098c2ecf20Sopenharmony_ci pcie->reg_base + KVASER_PCIEFD_SRB_CTRL_REG); 11108c2ecf20Sopenharmony_ci 11118c2ecf20Sopenharmony_ci return 0; 11128c2ecf20Sopenharmony_ci} 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_cistatic int kvaser_pciefd_setup_board(struct kvaser_pciefd *pcie) 11158c2ecf20Sopenharmony_ci{ 11168c2ecf20Sopenharmony_ci u32 sysid, srb_status, build; 11178c2ecf20Sopenharmony_ci u8 sysid_nr_chan; 11188c2ecf20Sopenharmony_ci int ret; 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_ci ret = kvaser_pciefd_read_cfg(pcie); 11218c2ecf20Sopenharmony_ci if (ret) 11228c2ecf20Sopenharmony_ci return ret; 11238c2ecf20Sopenharmony_ci 11248c2ecf20Sopenharmony_ci sysid = ioread32(pcie->reg_base + KVASER_PCIEFD_SYSID_VERSION_REG); 11258c2ecf20Sopenharmony_ci sysid_nr_chan = (sysid >> KVASER_PCIEFD_SYSID_NRCHAN_SHIFT) & 0xff; 11268c2ecf20Sopenharmony_ci if (pcie->nr_channels != sysid_nr_chan) { 11278c2ecf20Sopenharmony_ci dev_err(&pcie->pci->dev, 11288c2ecf20Sopenharmony_ci "Number of channels does not match: %u vs %u\n", 11298c2ecf20Sopenharmony_ci pcie->nr_channels, 11308c2ecf20Sopenharmony_ci sysid_nr_chan); 11318c2ecf20Sopenharmony_ci return -ENODEV; 11328c2ecf20Sopenharmony_ci } 11338c2ecf20Sopenharmony_ci 11348c2ecf20Sopenharmony_ci if (pcie->nr_channels > KVASER_PCIEFD_MAX_CAN_CHANNELS) 11358c2ecf20Sopenharmony_ci pcie->nr_channels = KVASER_PCIEFD_MAX_CAN_CHANNELS; 11368c2ecf20Sopenharmony_ci 11378c2ecf20Sopenharmony_ci build = ioread32(pcie->reg_base + KVASER_PCIEFD_SYSID_BUILD_REG); 11388c2ecf20Sopenharmony_ci dev_dbg(&pcie->pci->dev, "Version %u.%u.%u\n", 11398c2ecf20Sopenharmony_ci (sysid >> KVASER_PCIEFD_SYSID_MAJOR_VER_SHIFT) & 0xff, 11408c2ecf20Sopenharmony_ci sysid & 0xff, 11418c2ecf20Sopenharmony_ci (build >> KVASER_PCIEFD_SYSID_BUILD_VER_SHIFT) & 0x7fff); 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_ci srb_status = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_STAT_REG); 11448c2ecf20Sopenharmony_ci if (!(srb_status & KVASER_PCIEFD_SRB_STAT_DMA)) { 11458c2ecf20Sopenharmony_ci dev_err(&pcie->pci->dev, 11468c2ecf20Sopenharmony_ci "Hardware without DMA is not supported\n"); 11478c2ecf20Sopenharmony_ci return -ENODEV; 11488c2ecf20Sopenharmony_ci } 11498c2ecf20Sopenharmony_ci 11508c2ecf20Sopenharmony_ci pcie->bus_freq = ioread32(pcie->reg_base + 11518c2ecf20Sopenharmony_ci KVASER_PCIEFD_SYSID_BUSFREQ_REG); 11528c2ecf20Sopenharmony_ci pcie->freq = ioread32(pcie->reg_base + KVASER_PCIEFD_SYSID_CANFREQ_REG); 11538c2ecf20Sopenharmony_ci pcie->freq_to_ticks_div = pcie->freq / 1000000; 11548c2ecf20Sopenharmony_ci if (pcie->freq_to_ticks_div == 0) 11558c2ecf20Sopenharmony_ci pcie->freq_to_ticks_div = 1; 11568c2ecf20Sopenharmony_ci 11578c2ecf20Sopenharmony_ci /* Turn off all loopback functionality */ 11588c2ecf20Sopenharmony_ci iowrite32(0, pcie->reg_base + KVASER_PCIEFD_LOOP_REG); 11598c2ecf20Sopenharmony_ci return ret; 11608c2ecf20Sopenharmony_ci} 11618c2ecf20Sopenharmony_ci 11628c2ecf20Sopenharmony_cistatic int kvaser_pciefd_handle_data_packet(struct kvaser_pciefd *pcie, 11638c2ecf20Sopenharmony_ci struct kvaser_pciefd_rx_packet *p, 11648c2ecf20Sopenharmony_ci __le32 *data) 11658c2ecf20Sopenharmony_ci{ 11668c2ecf20Sopenharmony_ci struct sk_buff *skb; 11678c2ecf20Sopenharmony_ci struct canfd_frame *cf; 11688c2ecf20Sopenharmony_ci struct can_priv *priv; 11698c2ecf20Sopenharmony_ci struct net_device_stats *stats; 11708c2ecf20Sopenharmony_ci struct skb_shared_hwtstamps *shhwtstamps; 11718c2ecf20Sopenharmony_ci u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7; 11728c2ecf20Sopenharmony_ci 11738c2ecf20Sopenharmony_ci if (ch_id >= pcie->nr_channels) 11748c2ecf20Sopenharmony_ci return -EIO; 11758c2ecf20Sopenharmony_ci 11768c2ecf20Sopenharmony_ci priv = &pcie->can[ch_id]->can; 11778c2ecf20Sopenharmony_ci stats = &priv->dev->stats; 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ci if (p->header[1] & KVASER_PCIEFD_RPACKET_FDF) { 11808c2ecf20Sopenharmony_ci skb = alloc_canfd_skb(priv->dev, &cf); 11818c2ecf20Sopenharmony_ci if (!skb) { 11828c2ecf20Sopenharmony_ci stats->rx_dropped++; 11838c2ecf20Sopenharmony_ci return -ENOMEM; 11848c2ecf20Sopenharmony_ci } 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_ci if (p->header[1] & KVASER_PCIEFD_RPACKET_BRS) 11878c2ecf20Sopenharmony_ci cf->flags |= CANFD_BRS; 11888c2ecf20Sopenharmony_ci 11898c2ecf20Sopenharmony_ci if (p->header[1] & KVASER_PCIEFD_RPACKET_ESI) 11908c2ecf20Sopenharmony_ci cf->flags |= CANFD_ESI; 11918c2ecf20Sopenharmony_ci } else { 11928c2ecf20Sopenharmony_ci skb = alloc_can_skb(priv->dev, (struct can_frame **)&cf); 11938c2ecf20Sopenharmony_ci if (!skb) { 11948c2ecf20Sopenharmony_ci stats->rx_dropped++; 11958c2ecf20Sopenharmony_ci return -ENOMEM; 11968c2ecf20Sopenharmony_ci } 11978c2ecf20Sopenharmony_ci } 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_ci cf->can_id = p->header[0] & CAN_EFF_MASK; 12008c2ecf20Sopenharmony_ci if (p->header[0] & KVASER_PCIEFD_RPACKET_IDE) 12018c2ecf20Sopenharmony_ci cf->can_id |= CAN_EFF_FLAG; 12028c2ecf20Sopenharmony_ci 12038c2ecf20Sopenharmony_ci cf->len = can_dlc2len(p->header[1] >> KVASER_PCIEFD_RPACKET_DLC_SHIFT); 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_ci if (p->header[0] & KVASER_PCIEFD_RPACKET_RTR) 12068c2ecf20Sopenharmony_ci cf->can_id |= CAN_RTR_FLAG; 12078c2ecf20Sopenharmony_ci else 12088c2ecf20Sopenharmony_ci memcpy(cf->data, data, cf->len); 12098c2ecf20Sopenharmony_ci 12108c2ecf20Sopenharmony_ci shhwtstamps = skb_hwtstamps(skb); 12118c2ecf20Sopenharmony_ci 12128c2ecf20Sopenharmony_ci shhwtstamps->hwtstamp = 12138c2ecf20Sopenharmony_ci ns_to_ktime(div_u64(p->timestamp * 1000, 12148c2ecf20Sopenharmony_ci pcie->freq_to_ticks_div)); 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_ci stats->rx_bytes += cf->len; 12178c2ecf20Sopenharmony_ci stats->rx_packets++; 12188c2ecf20Sopenharmony_ci 12198c2ecf20Sopenharmony_ci return netif_rx(skb); 12208c2ecf20Sopenharmony_ci} 12218c2ecf20Sopenharmony_ci 12228c2ecf20Sopenharmony_cistatic void kvaser_pciefd_change_state(struct kvaser_pciefd_can *can, 12238c2ecf20Sopenharmony_ci struct can_frame *cf, 12248c2ecf20Sopenharmony_ci enum can_state new_state, 12258c2ecf20Sopenharmony_ci enum can_state tx_state, 12268c2ecf20Sopenharmony_ci enum can_state rx_state) 12278c2ecf20Sopenharmony_ci{ 12288c2ecf20Sopenharmony_ci can_change_state(can->can.dev, cf, tx_state, rx_state); 12298c2ecf20Sopenharmony_ci 12308c2ecf20Sopenharmony_ci if (new_state == CAN_STATE_BUS_OFF) { 12318c2ecf20Sopenharmony_ci struct net_device *ndev = can->can.dev; 12328c2ecf20Sopenharmony_ci unsigned long irq_flags; 12338c2ecf20Sopenharmony_ci 12348c2ecf20Sopenharmony_ci spin_lock_irqsave(&can->lock, irq_flags); 12358c2ecf20Sopenharmony_ci netif_stop_queue(can->can.dev); 12368c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&can->lock, irq_flags); 12378c2ecf20Sopenharmony_ci 12388c2ecf20Sopenharmony_ci /* Prevent CAN controller from auto recover from bus off */ 12398c2ecf20Sopenharmony_ci if (!can->can.restart_ms) { 12408c2ecf20Sopenharmony_ci kvaser_pciefd_start_controller_flush(can); 12418c2ecf20Sopenharmony_ci can_bus_off(ndev); 12428c2ecf20Sopenharmony_ci } 12438c2ecf20Sopenharmony_ci } 12448c2ecf20Sopenharmony_ci} 12458c2ecf20Sopenharmony_ci 12468c2ecf20Sopenharmony_cistatic void kvaser_pciefd_packet_to_state(struct kvaser_pciefd_rx_packet *p, 12478c2ecf20Sopenharmony_ci struct can_berr_counter *bec, 12488c2ecf20Sopenharmony_ci enum can_state *new_state, 12498c2ecf20Sopenharmony_ci enum can_state *tx_state, 12508c2ecf20Sopenharmony_ci enum can_state *rx_state) 12518c2ecf20Sopenharmony_ci{ 12528c2ecf20Sopenharmony_ci if (p->header[0] & KVASER_PCIEFD_SPACK_BOFF || 12538c2ecf20Sopenharmony_ci p->header[0] & KVASER_PCIEFD_SPACK_IRM) 12548c2ecf20Sopenharmony_ci *new_state = CAN_STATE_BUS_OFF; 12558c2ecf20Sopenharmony_ci else if (bec->txerr >= 255 || bec->rxerr >= 255) 12568c2ecf20Sopenharmony_ci *new_state = CAN_STATE_BUS_OFF; 12578c2ecf20Sopenharmony_ci else if (p->header[1] & KVASER_PCIEFD_SPACK_EPLR) 12588c2ecf20Sopenharmony_ci *new_state = CAN_STATE_ERROR_PASSIVE; 12598c2ecf20Sopenharmony_ci else if (bec->txerr >= 128 || bec->rxerr >= 128) 12608c2ecf20Sopenharmony_ci *new_state = CAN_STATE_ERROR_PASSIVE; 12618c2ecf20Sopenharmony_ci else if (p->header[1] & KVASER_PCIEFD_SPACK_EWLR) 12628c2ecf20Sopenharmony_ci *new_state = CAN_STATE_ERROR_WARNING; 12638c2ecf20Sopenharmony_ci else if (bec->txerr >= 96 || bec->rxerr >= 96) 12648c2ecf20Sopenharmony_ci *new_state = CAN_STATE_ERROR_WARNING; 12658c2ecf20Sopenharmony_ci else 12668c2ecf20Sopenharmony_ci *new_state = CAN_STATE_ERROR_ACTIVE; 12678c2ecf20Sopenharmony_ci 12688c2ecf20Sopenharmony_ci *tx_state = bec->txerr >= bec->rxerr ? *new_state : 0; 12698c2ecf20Sopenharmony_ci *rx_state = bec->txerr <= bec->rxerr ? *new_state : 0; 12708c2ecf20Sopenharmony_ci} 12718c2ecf20Sopenharmony_ci 12728c2ecf20Sopenharmony_cistatic int kvaser_pciefd_rx_error_frame(struct kvaser_pciefd_can *can, 12738c2ecf20Sopenharmony_ci struct kvaser_pciefd_rx_packet *p) 12748c2ecf20Sopenharmony_ci{ 12758c2ecf20Sopenharmony_ci struct can_berr_counter bec; 12768c2ecf20Sopenharmony_ci enum can_state old_state, new_state, tx_state, rx_state; 12778c2ecf20Sopenharmony_ci struct net_device *ndev = can->can.dev; 12788c2ecf20Sopenharmony_ci struct sk_buff *skb; 12798c2ecf20Sopenharmony_ci struct can_frame *cf = NULL; 12808c2ecf20Sopenharmony_ci struct skb_shared_hwtstamps *shhwtstamps; 12818c2ecf20Sopenharmony_ci struct net_device_stats *stats = &ndev->stats; 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_ci old_state = can->can.state; 12848c2ecf20Sopenharmony_ci 12858c2ecf20Sopenharmony_ci bec.txerr = p->header[0] & 0xff; 12868c2ecf20Sopenharmony_ci bec.rxerr = (p->header[0] >> KVASER_PCIEFD_SPACK_RXERR_SHIFT) & 0xff; 12878c2ecf20Sopenharmony_ci 12888c2ecf20Sopenharmony_ci kvaser_pciefd_packet_to_state(p, &bec, &new_state, &tx_state, 12898c2ecf20Sopenharmony_ci &rx_state); 12908c2ecf20Sopenharmony_ci 12918c2ecf20Sopenharmony_ci skb = alloc_can_err_skb(ndev, &cf); 12928c2ecf20Sopenharmony_ci 12938c2ecf20Sopenharmony_ci if (new_state != old_state) { 12948c2ecf20Sopenharmony_ci kvaser_pciefd_change_state(can, cf, new_state, tx_state, 12958c2ecf20Sopenharmony_ci rx_state); 12968c2ecf20Sopenharmony_ci 12978c2ecf20Sopenharmony_ci if (old_state == CAN_STATE_BUS_OFF && 12988c2ecf20Sopenharmony_ci new_state == CAN_STATE_ERROR_ACTIVE && 12998c2ecf20Sopenharmony_ci can->can.restart_ms) { 13008c2ecf20Sopenharmony_ci can->can.can_stats.restarts++; 13018c2ecf20Sopenharmony_ci if (skb) 13028c2ecf20Sopenharmony_ci cf->can_id |= CAN_ERR_RESTARTED; 13038c2ecf20Sopenharmony_ci } 13048c2ecf20Sopenharmony_ci } 13058c2ecf20Sopenharmony_ci 13068c2ecf20Sopenharmony_ci can->err_rep_cnt++; 13078c2ecf20Sopenharmony_ci can->can.can_stats.bus_error++; 13088c2ecf20Sopenharmony_ci if (p->header[1] & KVASER_PCIEFD_EPACK_DIR_TX) 13098c2ecf20Sopenharmony_ci stats->tx_errors++; 13108c2ecf20Sopenharmony_ci else 13118c2ecf20Sopenharmony_ci stats->rx_errors++; 13128c2ecf20Sopenharmony_ci 13138c2ecf20Sopenharmony_ci can->bec.txerr = bec.txerr; 13148c2ecf20Sopenharmony_ci can->bec.rxerr = bec.rxerr; 13158c2ecf20Sopenharmony_ci 13168c2ecf20Sopenharmony_ci if (!skb) { 13178c2ecf20Sopenharmony_ci stats->rx_dropped++; 13188c2ecf20Sopenharmony_ci return -ENOMEM; 13198c2ecf20Sopenharmony_ci } 13208c2ecf20Sopenharmony_ci 13218c2ecf20Sopenharmony_ci shhwtstamps = skb_hwtstamps(skb); 13228c2ecf20Sopenharmony_ci shhwtstamps->hwtstamp = 13238c2ecf20Sopenharmony_ci ns_to_ktime(div_u64(p->timestamp * 1000, 13248c2ecf20Sopenharmony_ci can->kv_pcie->freq_to_ticks_div)); 13258c2ecf20Sopenharmony_ci cf->can_id |= CAN_ERR_BUSERROR; 13268c2ecf20Sopenharmony_ci 13278c2ecf20Sopenharmony_ci cf->data[6] = bec.txerr; 13288c2ecf20Sopenharmony_ci cf->data[7] = bec.rxerr; 13298c2ecf20Sopenharmony_ci 13308c2ecf20Sopenharmony_ci stats->rx_packets++; 13318c2ecf20Sopenharmony_ci stats->rx_bytes += cf->can_dlc; 13328c2ecf20Sopenharmony_ci 13338c2ecf20Sopenharmony_ci netif_rx(skb); 13348c2ecf20Sopenharmony_ci return 0; 13358c2ecf20Sopenharmony_ci} 13368c2ecf20Sopenharmony_ci 13378c2ecf20Sopenharmony_cistatic int kvaser_pciefd_handle_error_packet(struct kvaser_pciefd *pcie, 13388c2ecf20Sopenharmony_ci struct kvaser_pciefd_rx_packet *p) 13398c2ecf20Sopenharmony_ci{ 13408c2ecf20Sopenharmony_ci struct kvaser_pciefd_can *can; 13418c2ecf20Sopenharmony_ci u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7; 13428c2ecf20Sopenharmony_ci 13438c2ecf20Sopenharmony_ci if (ch_id >= pcie->nr_channels) 13448c2ecf20Sopenharmony_ci return -EIO; 13458c2ecf20Sopenharmony_ci 13468c2ecf20Sopenharmony_ci can = pcie->can[ch_id]; 13478c2ecf20Sopenharmony_ci 13488c2ecf20Sopenharmony_ci kvaser_pciefd_rx_error_frame(can, p); 13498c2ecf20Sopenharmony_ci if (can->err_rep_cnt >= KVASER_PCIEFD_MAX_ERR_REP) 13508c2ecf20Sopenharmony_ci /* Do not report more errors, until bec_poll_timer expires */ 13518c2ecf20Sopenharmony_ci kvaser_pciefd_disable_err_gen(can); 13528c2ecf20Sopenharmony_ci /* Start polling the error counters */ 13538c2ecf20Sopenharmony_ci mod_timer(&can->bec_poll_timer, KVASER_PCIEFD_BEC_POLL_FREQ); 13548c2ecf20Sopenharmony_ci return 0; 13558c2ecf20Sopenharmony_ci} 13568c2ecf20Sopenharmony_ci 13578c2ecf20Sopenharmony_cistatic int kvaser_pciefd_handle_status_resp(struct kvaser_pciefd_can *can, 13588c2ecf20Sopenharmony_ci struct kvaser_pciefd_rx_packet *p) 13598c2ecf20Sopenharmony_ci{ 13608c2ecf20Sopenharmony_ci struct can_berr_counter bec; 13618c2ecf20Sopenharmony_ci enum can_state old_state, new_state, tx_state, rx_state; 13628c2ecf20Sopenharmony_ci 13638c2ecf20Sopenharmony_ci old_state = can->can.state; 13648c2ecf20Sopenharmony_ci 13658c2ecf20Sopenharmony_ci bec.txerr = p->header[0] & 0xff; 13668c2ecf20Sopenharmony_ci bec.rxerr = (p->header[0] >> KVASER_PCIEFD_SPACK_RXERR_SHIFT) & 0xff; 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci kvaser_pciefd_packet_to_state(p, &bec, &new_state, &tx_state, 13698c2ecf20Sopenharmony_ci &rx_state); 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_ci if (new_state != old_state) { 13728c2ecf20Sopenharmony_ci struct net_device *ndev = can->can.dev; 13738c2ecf20Sopenharmony_ci struct sk_buff *skb; 13748c2ecf20Sopenharmony_ci struct can_frame *cf; 13758c2ecf20Sopenharmony_ci struct skb_shared_hwtstamps *shhwtstamps; 13768c2ecf20Sopenharmony_ci 13778c2ecf20Sopenharmony_ci skb = alloc_can_err_skb(ndev, &cf); 13788c2ecf20Sopenharmony_ci if (!skb) { 13798c2ecf20Sopenharmony_ci struct net_device_stats *stats = &ndev->stats; 13808c2ecf20Sopenharmony_ci 13818c2ecf20Sopenharmony_ci stats->rx_dropped++; 13828c2ecf20Sopenharmony_ci return -ENOMEM; 13838c2ecf20Sopenharmony_ci } 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_ci kvaser_pciefd_change_state(can, cf, new_state, tx_state, 13868c2ecf20Sopenharmony_ci rx_state); 13878c2ecf20Sopenharmony_ci 13888c2ecf20Sopenharmony_ci if (old_state == CAN_STATE_BUS_OFF && 13898c2ecf20Sopenharmony_ci new_state == CAN_STATE_ERROR_ACTIVE && 13908c2ecf20Sopenharmony_ci can->can.restart_ms) { 13918c2ecf20Sopenharmony_ci can->can.can_stats.restarts++; 13928c2ecf20Sopenharmony_ci cf->can_id |= CAN_ERR_RESTARTED; 13938c2ecf20Sopenharmony_ci } 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_ci shhwtstamps = skb_hwtstamps(skb); 13968c2ecf20Sopenharmony_ci shhwtstamps->hwtstamp = 13978c2ecf20Sopenharmony_ci ns_to_ktime(div_u64(p->timestamp * 1000, 13988c2ecf20Sopenharmony_ci can->kv_pcie->freq_to_ticks_div)); 13998c2ecf20Sopenharmony_ci 14008c2ecf20Sopenharmony_ci cf->data[6] = bec.txerr; 14018c2ecf20Sopenharmony_ci cf->data[7] = bec.rxerr; 14028c2ecf20Sopenharmony_ci 14038c2ecf20Sopenharmony_ci netif_rx(skb); 14048c2ecf20Sopenharmony_ci } 14058c2ecf20Sopenharmony_ci can->bec.txerr = bec.txerr; 14068c2ecf20Sopenharmony_ci can->bec.rxerr = bec.rxerr; 14078c2ecf20Sopenharmony_ci /* Check if we need to poll the error counters */ 14088c2ecf20Sopenharmony_ci if (bec.txerr || bec.rxerr) 14098c2ecf20Sopenharmony_ci mod_timer(&can->bec_poll_timer, KVASER_PCIEFD_BEC_POLL_FREQ); 14108c2ecf20Sopenharmony_ci 14118c2ecf20Sopenharmony_ci return 0; 14128c2ecf20Sopenharmony_ci} 14138c2ecf20Sopenharmony_ci 14148c2ecf20Sopenharmony_cistatic int kvaser_pciefd_handle_status_packet(struct kvaser_pciefd *pcie, 14158c2ecf20Sopenharmony_ci struct kvaser_pciefd_rx_packet *p) 14168c2ecf20Sopenharmony_ci{ 14178c2ecf20Sopenharmony_ci struct kvaser_pciefd_can *can; 14188c2ecf20Sopenharmony_ci u8 cmdseq; 14198c2ecf20Sopenharmony_ci u32 status; 14208c2ecf20Sopenharmony_ci u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7; 14218c2ecf20Sopenharmony_ci 14228c2ecf20Sopenharmony_ci if (ch_id >= pcie->nr_channels) 14238c2ecf20Sopenharmony_ci return -EIO; 14248c2ecf20Sopenharmony_ci 14258c2ecf20Sopenharmony_ci can = pcie->can[ch_id]; 14268c2ecf20Sopenharmony_ci 14278c2ecf20Sopenharmony_ci status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG); 14288c2ecf20Sopenharmony_ci cmdseq = (status >> KVASER_PCIEFD_KCAN_STAT_SEQNO_SHIFT) & 0xff; 14298c2ecf20Sopenharmony_ci 14308c2ecf20Sopenharmony_ci /* Reset done, start abort and flush */ 14318c2ecf20Sopenharmony_ci if (p->header[0] & KVASER_PCIEFD_SPACK_IRM && 14328c2ecf20Sopenharmony_ci p->header[0] & KVASER_PCIEFD_SPACK_RMCD && 14338c2ecf20Sopenharmony_ci p->header[1] & KVASER_PCIEFD_SPACK_AUTO && 14348c2ecf20Sopenharmony_ci cmdseq == (p->header[1] & KVASER_PCIEFD_PACKET_SEQ_MSK) && 14358c2ecf20Sopenharmony_ci status & KVASER_PCIEFD_KCAN_STAT_IDLE) { 14368c2ecf20Sopenharmony_ci u32 cmd; 14378c2ecf20Sopenharmony_ci 14388c2ecf20Sopenharmony_ci iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD, 14398c2ecf20Sopenharmony_ci can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); 14408c2ecf20Sopenharmony_ci cmd = KVASER_PCIEFD_KCAN_CMD_AT; 14418c2ecf20Sopenharmony_ci cmd |= ++can->cmd_seq << KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT; 14428c2ecf20Sopenharmony_ci iowrite32(cmd, can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG); 14438c2ecf20Sopenharmony_ci } else if (p->header[0] & KVASER_PCIEFD_SPACK_IDET && 14448c2ecf20Sopenharmony_ci p->header[0] & KVASER_PCIEFD_SPACK_IRM && 14458c2ecf20Sopenharmony_ci cmdseq == (p->header[1] & KVASER_PCIEFD_PACKET_SEQ_MSK) && 14468c2ecf20Sopenharmony_ci status & KVASER_PCIEFD_KCAN_STAT_IDLE) { 14478c2ecf20Sopenharmony_ci /* Reset detected, send end of flush if no packet are in FIFO */ 14488c2ecf20Sopenharmony_ci u8 count = ioread32(can->reg_base + 14498c2ecf20Sopenharmony_ci KVASER_PCIEFD_KCAN_TX_NPACKETS_REG) & 0xff; 14508c2ecf20Sopenharmony_ci 14518c2ecf20Sopenharmony_ci if (!count) 14528c2ecf20Sopenharmony_ci iowrite32(KVASER_PCIEFD_KCAN_CTRL_EFLUSH, 14538c2ecf20Sopenharmony_ci can->reg_base + KVASER_PCIEFD_KCAN_CTRL_REG); 14548c2ecf20Sopenharmony_ci } else if (!(p->header[1] & KVASER_PCIEFD_SPACK_AUTO) && 14558c2ecf20Sopenharmony_ci cmdseq == (p->header[1] & KVASER_PCIEFD_PACKET_SEQ_MSK)) { 14568c2ecf20Sopenharmony_ci /* Response to status request received */ 14578c2ecf20Sopenharmony_ci kvaser_pciefd_handle_status_resp(can, p); 14588c2ecf20Sopenharmony_ci if (can->can.state != CAN_STATE_BUS_OFF && 14598c2ecf20Sopenharmony_ci can->can.state != CAN_STATE_ERROR_ACTIVE) { 14608c2ecf20Sopenharmony_ci mod_timer(&can->bec_poll_timer, 14618c2ecf20Sopenharmony_ci KVASER_PCIEFD_BEC_POLL_FREQ); 14628c2ecf20Sopenharmony_ci } 14638c2ecf20Sopenharmony_ci } else if (p->header[0] & KVASER_PCIEFD_SPACK_RMCD && 14648c2ecf20Sopenharmony_ci !(status & KVASER_PCIEFD_KCAN_STAT_BUS_OFF_MSK)) { 14658c2ecf20Sopenharmony_ci /* Reset to bus on detected */ 14668c2ecf20Sopenharmony_ci if (!completion_done(&can->start_comp)) 14678c2ecf20Sopenharmony_ci complete(&can->start_comp); 14688c2ecf20Sopenharmony_ci } 14698c2ecf20Sopenharmony_ci 14708c2ecf20Sopenharmony_ci return 0; 14718c2ecf20Sopenharmony_ci} 14728c2ecf20Sopenharmony_ci 14738c2ecf20Sopenharmony_cistatic int kvaser_pciefd_handle_eack_packet(struct kvaser_pciefd *pcie, 14748c2ecf20Sopenharmony_ci struct kvaser_pciefd_rx_packet *p) 14758c2ecf20Sopenharmony_ci{ 14768c2ecf20Sopenharmony_ci struct kvaser_pciefd_can *can; 14778c2ecf20Sopenharmony_ci u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7; 14788c2ecf20Sopenharmony_ci 14798c2ecf20Sopenharmony_ci if (ch_id >= pcie->nr_channels) 14808c2ecf20Sopenharmony_ci return -EIO; 14818c2ecf20Sopenharmony_ci 14828c2ecf20Sopenharmony_ci can = pcie->can[ch_id]; 14838c2ecf20Sopenharmony_ci 14848c2ecf20Sopenharmony_ci /* If this is the last flushed packet, send end of flush */ 14858c2ecf20Sopenharmony_ci if (p->header[0] & KVASER_PCIEFD_APACKET_FLU) { 14868c2ecf20Sopenharmony_ci u8 count = ioread32(can->reg_base + 14878c2ecf20Sopenharmony_ci KVASER_PCIEFD_KCAN_TX_NPACKETS_REG) & 0xff; 14888c2ecf20Sopenharmony_ci 14898c2ecf20Sopenharmony_ci if (count == 0) 14908c2ecf20Sopenharmony_ci iowrite32(KVASER_PCIEFD_KCAN_CTRL_EFLUSH, 14918c2ecf20Sopenharmony_ci can->reg_base + KVASER_PCIEFD_KCAN_CTRL_REG); 14928c2ecf20Sopenharmony_ci } else { 14938c2ecf20Sopenharmony_ci int echo_idx = p->header[0] & KVASER_PCIEFD_PACKET_SEQ_MSK; 14948c2ecf20Sopenharmony_ci int dlc = can_get_echo_skb(can->can.dev, echo_idx); 14958c2ecf20Sopenharmony_ci struct net_device_stats *stats = &can->can.dev->stats; 14968c2ecf20Sopenharmony_ci 14978c2ecf20Sopenharmony_ci stats->tx_bytes += dlc; 14988c2ecf20Sopenharmony_ci stats->tx_packets++; 14998c2ecf20Sopenharmony_ci 15008c2ecf20Sopenharmony_ci if (netif_queue_stopped(can->can.dev)) 15018c2ecf20Sopenharmony_ci netif_wake_queue(can->can.dev); 15028c2ecf20Sopenharmony_ci } 15038c2ecf20Sopenharmony_ci 15048c2ecf20Sopenharmony_ci return 0; 15058c2ecf20Sopenharmony_ci} 15068c2ecf20Sopenharmony_ci 15078c2ecf20Sopenharmony_cistatic void kvaser_pciefd_handle_nack_packet(struct kvaser_pciefd_can *can, 15088c2ecf20Sopenharmony_ci struct kvaser_pciefd_rx_packet *p) 15098c2ecf20Sopenharmony_ci{ 15108c2ecf20Sopenharmony_ci struct sk_buff *skb; 15118c2ecf20Sopenharmony_ci struct net_device_stats *stats = &can->can.dev->stats; 15128c2ecf20Sopenharmony_ci struct can_frame *cf; 15138c2ecf20Sopenharmony_ci 15148c2ecf20Sopenharmony_ci skb = alloc_can_err_skb(can->can.dev, &cf); 15158c2ecf20Sopenharmony_ci 15168c2ecf20Sopenharmony_ci stats->tx_errors++; 15178c2ecf20Sopenharmony_ci if (p->header[0] & KVASER_PCIEFD_APACKET_ABL) { 15188c2ecf20Sopenharmony_ci if (skb) 15198c2ecf20Sopenharmony_ci cf->can_id |= CAN_ERR_LOSTARB; 15208c2ecf20Sopenharmony_ci can->can.can_stats.arbitration_lost++; 15218c2ecf20Sopenharmony_ci } else if (skb) { 15228c2ecf20Sopenharmony_ci cf->can_id |= CAN_ERR_ACK; 15238c2ecf20Sopenharmony_ci } 15248c2ecf20Sopenharmony_ci 15258c2ecf20Sopenharmony_ci if (skb) { 15268c2ecf20Sopenharmony_ci cf->can_id |= CAN_ERR_BUSERROR; 15278c2ecf20Sopenharmony_ci stats->rx_bytes += cf->can_dlc; 15288c2ecf20Sopenharmony_ci stats->rx_packets++; 15298c2ecf20Sopenharmony_ci netif_rx(skb); 15308c2ecf20Sopenharmony_ci } else { 15318c2ecf20Sopenharmony_ci stats->rx_dropped++; 15328c2ecf20Sopenharmony_ci netdev_warn(can->can.dev, "No memory left for err_skb\n"); 15338c2ecf20Sopenharmony_ci } 15348c2ecf20Sopenharmony_ci} 15358c2ecf20Sopenharmony_ci 15368c2ecf20Sopenharmony_cistatic int kvaser_pciefd_handle_ack_packet(struct kvaser_pciefd *pcie, 15378c2ecf20Sopenharmony_ci struct kvaser_pciefd_rx_packet *p) 15388c2ecf20Sopenharmony_ci{ 15398c2ecf20Sopenharmony_ci struct kvaser_pciefd_can *can; 15408c2ecf20Sopenharmony_ci bool one_shot_fail = false; 15418c2ecf20Sopenharmony_ci u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7; 15428c2ecf20Sopenharmony_ci 15438c2ecf20Sopenharmony_ci if (ch_id >= pcie->nr_channels) 15448c2ecf20Sopenharmony_ci return -EIO; 15458c2ecf20Sopenharmony_ci 15468c2ecf20Sopenharmony_ci can = pcie->can[ch_id]; 15478c2ecf20Sopenharmony_ci /* Ignore control packet ACK */ 15488c2ecf20Sopenharmony_ci if (p->header[0] & KVASER_PCIEFD_APACKET_CT) 15498c2ecf20Sopenharmony_ci return 0; 15508c2ecf20Sopenharmony_ci 15518c2ecf20Sopenharmony_ci if (p->header[0] & KVASER_PCIEFD_APACKET_NACK) { 15528c2ecf20Sopenharmony_ci kvaser_pciefd_handle_nack_packet(can, p); 15538c2ecf20Sopenharmony_ci one_shot_fail = true; 15548c2ecf20Sopenharmony_ci } 15558c2ecf20Sopenharmony_ci 15568c2ecf20Sopenharmony_ci if (p->header[0] & KVASER_PCIEFD_APACKET_FLU) { 15578c2ecf20Sopenharmony_ci netdev_dbg(can->can.dev, "Packet was flushed\n"); 15588c2ecf20Sopenharmony_ci } else { 15598c2ecf20Sopenharmony_ci int echo_idx = p->header[0] & KVASER_PCIEFD_PACKET_SEQ_MSK; 15608c2ecf20Sopenharmony_ci int dlc = can_get_echo_skb(can->can.dev, echo_idx); 15618c2ecf20Sopenharmony_ci u8 count = ioread32(can->reg_base + 15628c2ecf20Sopenharmony_ci KVASER_PCIEFD_KCAN_TX_NPACKETS_REG) & 0xff; 15638c2ecf20Sopenharmony_ci 15648c2ecf20Sopenharmony_ci if (count < KVASER_PCIEFD_CAN_TX_MAX_COUNT && 15658c2ecf20Sopenharmony_ci netif_queue_stopped(can->can.dev)) 15668c2ecf20Sopenharmony_ci netif_wake_queue(can->can.dev); 15678c2ecf20Sopenharmony_ci 15688c2ecf20Sopenharmony_ci if (!one_shot_fail) { 15698c2ecf20Sopenharmony_ci struct net_device_stats *stats = &can->can.dev->stats; 15708c2ecf20Sopenharmony_ci 15718c2ecf20Sopenharmony_ci stats->tx_bytes += dlc; 15728c2ecf20Sopenharmony_ci stats->tx_packets++; 15738c2ecf20Sopenharmony_ci } 15748c2ecf20Sopenharmony_ci } 15758c2ecf20Sopenharmony_ci 15768c2ecf20Sopenharmony_ci return 0; 15778c2ecf20Sopenharmony_ci} 15788c2ecf20Sopenharmony_ci 15798c2ecf20Sopenharmony_cistatic int kvaser_pciefd_handle_eflush_packet(struct kvaser_pciefd *pcie, 15808c2ecf20Sopenharmony_ci struct kvaser_pciefd_rx_packet *p) 15818c2ecf20Sopenharmony_ci{ 15828c2ecf20Sopenharmony_ci struct kvaser_pciefd_can *can; 15838c2ecf20Sopenharmony_ci u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7; 15848c2ecf20Sopenharmony_ci 15858c2ecf20Sopenharmony_ci if (ch_id >= pcie->nr_channels) 15868c2ecf20Sopenharmony_ci return -EIO; 15878c2ecf20Sopenharmony_ci 15888c2ecf20Sopenharmony_ci can = pcie->can[ch_id]; 15898c2ecf20Sopenharmony_ci 15908c2ecf20Sopenharmony_ci if (!completion_done(&can->flush_comp)) 15918c2ecf20Sopenharmony_ci complete(&can->flush_comp); 15928c2ecf20Sopenharmony_ci 15938c2ecf20Sopenharmony_ci return 0; 15948c2ecf20Sopenharmony_ci} 15958c2ecf20Sopenharmony_ci 15968c2ecf20Sopenharmony_cistatic int kvaser_pciefd_read_packet(struct kvaser_pciefd *pcie, int *start_pos, 15978c2ecf20Sopenharmony_ci int dma_buf) 15988c2ecf20Sopenharmony_ci{ 15998c2ecf20Sopenharmony_ci __le32 *buffer = pcie->dma_data[dma_buf]; 16008c2ecf20Sopenharmony_ci __le64 timestamp; 16018c2ecf20Sopenharmony_ci struct kvaser_pciefd_rx_packet packet; 16028c2ecf20Sopenharmony_ci struct kvaser_pciefd_rx_packet *p = &packet; 16038c2ecf20Sopenharmony_ci u8 type; 16048c2ecf20Sopenharmony_ci int pos = *start_pos; 16058c2ecf20Sopenharmony_ci int size; 16068c2ecf20Sopenharmony_ci int ret = 0; 16078c2ecf20Sopenharmony_ci 16088c2ecf20Sopenharmony_ci size = le32_to_cpu(buffer[pos++]); 16098c2ecf20Sopenharmony_ci if (!size) { 16108c2ecf20Sopenharmony_ci *start_pos = 0; 16118c2ecf20Sopenharmony_ci return 0; 16128c2ecf20Sopenharmony_ci } 16138c2ecf20Sopenharmony_ci 16148c2ecf20Sopenharmony_ci p->header[0] = le32_to_cpu(buffer[pos++]); 16158c2ecf20Sopenharmony_ci p->header[1] = le32_to_cpu(buffer[pos++]); 16168c2ecf20Sopenharmony_ci 16178c2ecf20Sopenharmony_ci /* Read 64-bit timestamp */ 16188c2ecf20Sopenharmony_ci memcpy(×tamp, &buffer[pos], sizeof(__le64)); 16198c2ecf20Sopenharmony_ci pos += 2; 16208c2ecf20Sopenharmony_ci p->timestamp = le64_to_cpu(timestamp); 16218c2ecf20Sopenharmony_ci 16228c2ecf20Sopenharmony_ci type = (p->header[1] >> KVASER_PCIEFD_PACKET_TYPE_SHIFT) & 0xf; 16238c2ecf20Sopenharmony_ci switch (type) { 16248c2ecf20Sopenharmony_ci case KVASER_PCIEFD_PACK_TYPE_DATA: 16258c2ecf20Sopenharmony_ci ret = kvaser_pciefd_handle_data_packet(pcie, p, &buffer[pos]); 16268c2ecf20Sopenharmony_ci if (!(p->header[0] & KVASER_PCIEFD_RPACKET_RTR)) { 16278c2ecf20Sopenharmony_ci u8 data_len; 16288c2ecf20Sopenharmony_ci 16298c2ecf20Sopenharmony_ci data_len = can_dlc2len(p->header[1] >> 16308c2ecf20Sopenharmony_ci KVASER_PCIEFD_RPACKET_DLC_SHIFT); 16318c2ecf20Sopenharmony_ci pos += DIV_ROUND_UP(data_len, 4); 16328c2ecf20Sopenharmony_ci } 16338c2ecf20Sopenharmony_ci break; 16348c2ecf20Sopenharmony_ci 16358c2ecf20Sopenharmony_ci case KVASER_PCIEFD_PACK_TYPE_ACK: 16368c2ecf20Sopenharmony_ci ret = kvaser_pciefd_handle_ack_packet(pcie, p); 16378c2ecf20Sopenharmony_ci break; 16388c2ecf20Sopenharmony_ci 16398c2ecf20Sopenharmony_ci case KVASER_PCIEFD_PACK_TYPE_STATUS: 16408c2ecf20Sopenharmony_ci ret = kvaser_pciefd_handle_status_packet(pcie, p); 16418c2ecf20Sopenharmony_ci break; 16428c2ecf20Sopenharmony_ci 16438c2ecf20Sopenharmony_ci case KVASER_PCIEFD_PACK_TYPE_ERROR: 16448c2ecf20Sopenharmony_ci ret = kvaser_pciefd_handle_error_packet(pcie, p); 16458c2ecf20Sopenharmony_ci break; 16468c2ecf20Sopenharmony_ci 16478c2ecf20Sopenharmony_ci case KVASER_PCIEFD_PACK_TYPE_EFRAME_ACK: 16488c2ecf20Sopenharmony_ci ret = kvaser_pciefd_handle_eack_packet(pcie, p); 16498c2ecf20Sopenharmony_ci break; 16508c2ecf20Sopenharmony_ci 16518c2ecf20Sopenharmony_ci case KVASER_PCIEFD_PACK_TYPE_EFLUSH_ACK: 16528c2ecf20Sopenharmony_ci ret = kvaser_pciefd_handle_eflush_packet(pcie, p); 16538c2ecf20Sopenharmony_ci break; 16548c2ecf20Sopenharmony_ci 16558c2ecf20Sopenharmony_ci case KVASER_PCIEFD_PACK_TYPE_ACK_DATA: 16568c2ecf20Sopenharmony_ci case KVASER_PCIEFD_PACK_TYPE_BUS_LOAD: 16578c2ecf20Sopenharmony_ci case KVASER_PCIEFD_PACK_TYPE_TXRQ: 16588c2ecf20Sopenharmony_ci dev_info(&pcie->pci->dev, 16598c2ecf20Sopenharmony_ci "Received unexpected packet type 0x%08X\n", type); 16608c2ecf20Sopenharmony_ci break; 16618c2ecf20Sopenharmony_ci 16628c2ecf20Sopenharmony_ci default: 16638c2ecf20Sopenharmony_ci dev_err(&pcie->pci->dev, "Unknown packet type 0x%08X\n", type); 16648c2ecf20Sopenharmony_ci ret = -EIO; 16658c2ecf20Sopenharmony_ci break; 16668c2ecf20Sopenharmony_ci } 16678c2ecf20Sopenharmony_ci 16688c2ecf20Sopenharmony_ci if (ret) 16698c2ecf20Sopenharmony_ci return ret; 16708c2ecf20Sopenharmony_ci 16718c2ecf20Sopenharmony_ci /* Position does not point to the end of the package, 16728c2ecf20Sopenharmony_ci * corrupted packet size? 16738c2ecf20Sopenharmony_ci */ 16748c2ecf20Sopenharmony_ci if ((*start_pos + size) != pos) 16758c2ecf20Sopenharmony_ci return -EIO; 16768c2ecf20Sopenharmony_ci 16778c2ecf20Sopenharmony_ci /* Point to the next packet header, if any */ 16788c2ecf20Sopenharmony_ci *start_pos = pos; 16798c2ecf20Sopenharmony_ci 16808c2ecf20Sopenharmony_ci return ret; 16818c2ecf20Sopenharmony_ci} 16828c2ecf20Sopenharmony_ci 16838c2ecf20Sopenharmony_cistatic int kvaser_pciefd_read_buffer(struct kvaser_pciefd *pcie, int dma_buf) 16848c2ecf20Sopenharmony_ci{ 16858c2ecf20Sopenharmony_ci int pos = 0; 16868c2ecf20Sopenharmony_ci int res = 0; 16878c2ecf20Sopenharmony_ci 16888c2ecf20Sopenharmony_ci do { 16898c2ecf20Sopenharmony_ci res = kvaser_pciefd_read_packet(pcie, &pos, dma_buf); 16908c2ecf20Sopenharmony_ci } while (!res && pos > 0 && pos < KVASER_PCIEFD_DMA_SIZE); 16918c2ecf20Sopenharmony_ci 16928c2ecf20Sopenharmony_ci return res; 16938c2ecf20Sopenharmony_ci} 16948c2ecf20Sopenharmony_ci 16958c2ecf20Sopenharmony_cistatic int kvaser_pciefd_receive_irq(struct kvaser_pciefd *pcie) 16968c2ecf20Sopenharmony_ci{ 16978c2ecf20Sopenharmony_ci u32 irq; 16988c2ecf20Sopenharmony_ci 16998c2ecf20Sopenharmony_ci irq = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_IRQ_REG); 17008c2ecf20Sopenharmony_ci if (irq & KVASER_PCIEFD_SRB_IRQ_DPD0) { 17018c2ecf20Sopenharmony_ci kvaser_pciefd_read_buffer(pcie, 0); 17028c2ecf20Sopenharmony_ci /* Reset DMA buffer 0 */ 17038c2ecf20Sopenharmony_ci iowrite32(KVASER_PCIEFD_SRB_CMD_RDB0, 17048c2ecf20Sopenharmony_ci pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG); 17058c2ecf20Sopenharmony_ci } 17068c2ecf20Sopenharmony_ci 17078c2ecf20Sopenharmony_ci if (irq & KVASER_PCIEFD_SRB_IRQ_DPD1) { 17088c2ecf20Sopenharmony_ci kvaser_pciefd_read_buffer(pcie, 1); 17098c2ecf20Sopenharmony_ci /* Reset DMA buffer 1 */ 17108c2ecf20Sopenharmony_ci iowrite32(KVASER_PCIEFD_SRB_CMD_RDB1, 17118c2ecf20Sopenharmony_ci pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG); 17128c2ecf20Sopenharmony_ci } 17138c2ecf20Sopenharmony_ci 17148c2ecf20Sopenharmony_ci if (irq & KVASER_PCIEFD_SRB_IRQ_DOF0 || 17158c2ecf20Sopenharmony_ci irq & KVASER_PCIEFD_SRB_IRQ_DOF1 || 17168c2ecf20Sopenharmony_ci irq & KVASER_PCIEFD_SRB_IRQ_DUF0 || 17178c2ecf20Sopenharmony_ci irq & KVASER_PCIEFD_SRB_IRQ_DUF1) 17188c2ecf20Sopenharmony_ci dev_err(&pcie->pci->dev, "DMA IRQ error 0x%08X\n", irq); 17198c2ecf20Sopenharmony_ci 17208c2ecf20Sopenharmony_ci iowrite32(irq, pcie->reg_base + KVASER_PCIEFD_SRB_IRQ_REG); 17218c2ecf20Sopenharmony_ci return 0; 17228c2ecf20Sopenharmony_ci} 17238c2ecf20Sopenharmony_ci 17248c2ecf20Sopenharmony_cistatic int kvaser_pciefd_transmit_irq(struct kvaser_pciefd_can *can) 17258c2ecf20Sopenharmony_ci{ 17268c2ecf20Sopenharmony_ci u32 irq = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); 17278c2ecf20Sopenharmony_ci 17288c2ecf20Sopenharmony_ci if (irq & KVASER_PCIEFD_KCAN_IRQ_TOF) 17298c2ecf20Sopenharmony_ci netdev_err(can->can.dev, "Tx FIFO overflow\n"); 17308c2ecf20Sopenharmony_ci 17318c2ecf20Sopenharmony_ci if (irq & KVASER_PCIEFD_KCAN_IRQ_BPP) 17328c2ecf20Sopenharmony_ci netdev_err(can->can.dev, 17338c2ecf20Sopenharmony_ci "Fail to change bittiming, when not in reset mode\n"); 17348c2ecf20Sopenharmony_ci 17358c2ecf20Sopenharmony_ci if (irq & KVASER_PCIEFD_KCAN_IRQ_FDIC) 17368c2ecf20Sopenharmony_ci netdev_err(can->can.dev, "CAN FD frame in CAN mode\n"); 17378c2ecf20Sopenharmony_ci 17388c2ecf20Sopenharmony_ci if (irq & KVASER_PCIEFD_KCAN_IRQ_ROF) 17398c2ecf20Sopenharmony_ci netdev_err(can->can.dev, "Rx FIFO overflow\n"); 17408c2ecf20Sopenharmony_ci 17418c2ecf20Sopenharmony_ci iowrite32(irq, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); 17428c2ecf20Sopenharmony_ci return 0; 17438c2ecf20Sopenharmony_ci} 17448c2ecf20Sopenharmony_ci 17458c2ecf20Sopenharmony_cistatic irqreturn_t kvaser_pciefd_irq_handler(int irq, void *dev) 17468c2ecf20Sopenharmony_ci{ 17478c2ecf20Sopenharmony_ci struct kvaser_pciefd *pcie = (struct kvaser_pciefd *)dev; 17488c2ecf20Sopenharmony_ci u32 board_irq; 17498c2ecf20Sopenharmony_ci int i; 17508c2ecf20Sopenharmony_ci 17518c2ecf20Sopenharmony_ci board_irq = ioread32(pcie->reg_base + KVASER_PCIEFD_IRQ_REG); 17528c2ecf20Sopenharmony_ci 17538c2ecf20Sopenharmony_ci if (!(board_irq & KVASER_PCIEFD_IRQ_ALL_MSK)) 17548c2ecf20Sopenharmony_ci return IRQ_NONE; 17558c2ecf20Sopenharmony_ci 17568c2ecf20Sopenharmony_ci if (board_irq & KVASER_PCIEFD_IRQ_SRB) 17578c2ecf20Sopenharmony_ci kvaser_pciefd_receive_irq(pcie); 17588c2ecf20Sopenharmony_ci 17598c2ecf20Sopenharmony_ci for (i = 0; i < pcie->nr_channels; i++) { 17608c2ecf20Sopenharmony_ci if (!pcie->can[i]) { 17618c2ecf20Sopenharmony_ci dev_err(&pcie->pci->dev, 17628c2ecf20Sopenharmony_ci "IRQ mask points to unallocated controller\n"); 17638c2ecf20Sopenharmony_ci break; 17648c2ecf20Sopenharmony_ci } 17658c2ecf20Sopenharmony_ci 17668c2ecf20Sopenharmony_ci /* Check that mask matches channel (i) IRQ mask */ 17678c2ecf20Sopenharmony_ci if (board_irq & (1 << i)) 17688c2ecf20Sopenharmony_ci kvaser_pciefd_transmit_irq(pcie->can[i]); 17698c2ecf20Sopenharmony_ci } 17708c2ecf20Sopenharmony_ci 17718c2ecf20Sopenharmony_ci iowrite32(board_irq, pcie->reg_base + KVASER_PCIEFD_IRQ_REG); 17728c2ecf20Sopenharmony_ci return IRQ_HANDLED; 17738c2ecf20Sopenharmony_ci} 17748c2ecf20Sopenharmony_ci 17758c2ecf20Sopenharmony_cistatic void kvaser_pciefd_teardown_can_ctrls(struct kvaser_pciefd *pcie) 17768c2ecf20Sopenharmony_ci{ 17778c2ecf20Sopenharmony_ci int i; 17788c2ecf20Sopenharmony_ci struct kvaser_pciefd_can *can; 17798c2ecf20Sopenharmony_ci 17808c2ecf20Sopenharmony_ci for (i = 0; i < pcie->nr_channels; i++) { 17818c2ecf20Sopenharmony_ci can = pcie->can[i]; 17828c2ecf20Sopenharmony_ci if (can) { 17838c2ecf20Sopenharmony_ci iowrite32(0, 17848c2ecf20Sopenharmony_ci can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); 17858c2ecf20Sopenharmony_ci kvaser_pciefd_pwm_stop(can); 17868c2ecf20Sopenharmony_ci free_candev(can->can.dev); 17878c2ecf20Sopenharmony_ci } 17888c2ecf20Sopenharmony_ci } 17898c2ecf20Sopenharmony_ci} 17908c2ecf20Sopenharmony_ci 17918c2ecf20Sopenharmony_cistatic int kvaser_pciefd_probe(struct pci_dev *pdev, 17928c2ecf20Sopenharmony_ci const struct pci_device_id *id) 17938c2ecf20Sopenharmony_ci{ 17948c2ecf20Sopenharmony_ci int err; 17958c2ecf20Sopenharmony_ci struct kvaser_pciefd *pcie; 17968c2ecf20Sopenharmony_ci 17978c2ecf20Sopenharmony_ci pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL); 17988c2ecf20Sopenharmony_ci if (!pcie) 17998c2ecf20Sopenharmony_ci return -ENOMEM; 18008c2ecf20Sopenharmony_ci 18018c2ecf20Sopenharmony_ci pci_set_drvdata(pdev, pcie); 18028c2ecf20Sopenharmony_ci pcie->pci = pdev; 18038c2ecf20Sopenharmony_ci 18048c2ecf20Sopenharmony_ci err = pci_enable_device(pdev); 18058c2ecf20Sopenharmony_ci if (err) 18068c2ecf20Sopenharmony_ci return err; 18078c2ecf20Sopenharmony_ci 18088c2ecf20Sopenharmony_ci err = pci_request_regions(pdev, KVASER_PCIEFD_DRV_NAME); 18098c2ecf20Sopenharmony_ci if (err) 18108c2ecf20Sopenharmony_ci goto err_disable_pci; 18118c2ecf20Sopenharmony_ci 18128c2ecf20Sopenharmony_ci pcie->reg_base = pci_iomap(pdev, 0, 0); 18138c2ecf20Sopenharmony_ci if (!pcie->reg_base) { 18148c2ecf20Sopenharmony_ci err = -ENOMEM; 18158c2ecf20Sopenharmony_ci goto err_release_regions; 18168c2ecf20Sopenharmony_ci } 18178c2ecf20Sopenharmony_ci 18188c2ecf20Sopenharmony_ci err = kvaser_pciefd_setup_board(pcie); 18198c2ecf20Sopenharmony_ci if (err) 18208c2ecf20Sopenharmony_ci goto err_pci_iounmap; 18218c2ecf20Sopenharmony_ci 18228c2ecf20Sopenharmony_ci err = kvaser_pciefd_setup_dma(pcie); 18238c2ecf20Sopenharmony_ci if (err) 18248c2ecf20Sopenharmony_ci goto err_pci_iounmap; 18258c2ecf20Sopenharmony_ci 18268c2ecf20Sopenharmony_ci pci_set_master(pdev); 18278c2ecf20Sopenharmony_ci 18288c2ecf20Sopenharmony_ci err = kvaser_pciefd_setup_can_ctrls(pcie); 18298c2ecf20Sopenharmony_ci if (err) 18308c2ecf20Sopenharmony_ci goto err_teardown_can_ctrls; 18318c2ecf20Sopenharmony_ci 18328c2ecf20Sopenharmony_ci err = request_irq(pcie->pci->irq, kvaser_pciefd_irq_handler, 18338c2ecf20Sopenharmony_ci IRQF_SHARED, KVASER_PCIEFD_DRV_NAME, pcie); 18348c2ecf20Sopenharmony_ci if (err) 18358c2ecf20Sopenharmony_ci goto err_teardown_can_ctrls; 18368c2ecf20Sopenharmony_ci 18378c2ecf20Sopenharmony_ci iowrite32(KVASER_PCIEFD_SRB_IRQ_DPD0 | KVASER_PCIEFD_SRB_IRQ_DPD1, 18388c2ecf20Sopenharmony_ci pcie->reg_base + KVASER_PCIEFD_SRB_IRQ_REG); 18398c2ecf20Sopenharmony_ci 18408c2ecf20Sopenharmony_ci iowrite32(KVASER_PCIEFD_SRB_IRQ_DPD0 | KVASER_PCIEFD_SRB_IRQ_DPD1 | 18418c2ecf20Sopenharmony_ci KVASER_PCIEFD_SRB_IRQ_DOF0 | KVASER_PCIEFD_SRB_IRQ_DOF1 | 18428c2ecf20Sopenharmony_ci KVASER_PCIEFD_SRB_IRQ_DUF0 | KVASER_PCIEFD_SRB_IRQ_DUF1, 18438c2ecf20Sopenharmony_ci pcie->reg_base + KVASER_PCIEFD_SRB_IEN_REG); 18448c2ecf20Sopenharmony_ci 18458c2ecf20Sopenharmony_ci /* Reset IRQ handling, expected to be off before */ 18468c2ecf20Sopenharmony_ci iowrite32(KVASER_PCIEFD_IRQ_ALL_MSK, 18478c2ecf20Sopenharmony_ci pcie->reg_base + KVASER_PCIEFD_IRQ_REG); 18488c2ecf20Sopenharmony_ci iowrite32(KVASER_PCIEFD_IRQ_ALL_MSK, 18498c2ecf20Sopenharmony_ci pcie->reg_base + KVASER_PCIEFD_IEN_REG); 18508c2ecf20Sopenharmony_ci 18518c2ecf20Sopenharmony_ci /* Ready the DMA buffers */ 18528c2ecf20Sopenharmony_ci iowrite32(KVASER_PCIEFD_SRB_CMD_RDB0, 18538c2ecf20Sopenharmony_ci pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG); 18548c2ecf20Sopenharmony_ci iowrite32(KVASER_PCIEFD_SRB_CMD_RDB1, 18558c2ecf20Sopenharmony_ci pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG); 18568c2ecf20Sopenharmony_ci 18578c2ecf20Sopenharmony_ci err = kvaser_pciefd_reg_candev(pcie); 18588c2ecf20Sopenharmony_ci if (err) 18598c2ecf20Sopenharmony_ci goto err_free_irq; 18608c2ecf20Sopenharmony_ci 18618c2ecf20Sopenharmony_ci return 0; 18628c2ecf20Sopenharmony_ci 18638c2ecf20Sopenharmony_cierr_free_irq: 18648c2ecf20Sopenharmony_ci /* Disable PCI interrupts */ 18658c2ecf20Sopenharmony_ci iowrite32(0, pcie->reg_base + KVASER_PCIEFD_IEN_REG); 18668c2ecf20Sopenharmony_ci free_irq(pcie->pci->irq, pcie); 18678c2ecf20Sopenharmony_ci 18688c2ecf20Sopenharmony_cierr_teardown_can_ctrls: 18698c2ecf20Sopenharmony_ci kvaser_pciefd_teardown_can_ctrls(pcie); 18708c2ecf20Sopenharmony_ci iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SRB_CTRL_REG); 18718c2ecf20Sopenharmony_ci pci_clear_master(pdev); 18728c2ecf20Sopenharmony_ci 18738c2ecf20Sopenharmony_cierr_pci_iounmap: 18748c2ecf20Sopenharmony_ci pci_iounmap(pdev, pcie->reg_base); 18758c2ecf20Sopenharmony_ci 18768c2ecf20Sopenharmony_cierr_release_regions: 18778c2ecf20Sopenharmony_ci pci_release_regions(pdev); 18788c2ecf20Sopenharmony_ci 18798c2ecf20Sopenharmony_cierr_disable_pci: 18808c2ecf20Sopenharmony_ci pci_disable_device(pdev); 18818c2ecf20Sopenharmony_ci 18828c2ecf20Sopenharmony_ci return err; 18838c2ecf20Sopenharmony_ci} 18848c2ecf20Sopenharmony_ci 18858c2ecf20Sopenharmony_cistatic void kvaser_pciefd_remove_all_ctrls(struct kvaser_pciefd *pcie) 18868c2ecf20Sopenharmony_ci{ 18878c2ecf20Sopenharmony_ci struct kvaser_pciefd_can *can; 18888c2ecf20Sopenharmony_ci int i; 18898c2ecf20Sopenharmony_ci 18908c2ecf20Sopenharmony_ci for (i = 0; i < pcie->nr_channels; i++) { 18918c2ecf20Sopenharmony_ci can = pcie->can[i]; 18928c2ecf20Sopenharmony_ci if (can) { 18938c2ecf20Sopenharmony_ci iowrite32(0, 18948c2ecf20Sopenharmony_ci can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); 18958c2ecf20Sopenharmony_ci unregister_candev(can->can.dev); 18968c2ecf20Sopenharmony_ci del_timer(&can->bec_poll_timer); 18978c2ecf20Sopenharmony_ci kvaser_pciefd_pwm_stop(can); 18988c2ecf20Sopenharmony_ci free_candev(can->can.dev); 18998c2ecf20Sopenharmony_ci } 19008c2ecf20Sopenharmony_ci } 19018c2ecf20Sopenharmony_ci} 19028c2ecf20Sopenharmony_ci 19038c2ecf20Sopenharmony_cistatic void kvaser_pciefd_remove(struct pci_dev *pdev) 19048c2ecf20Sopenharmony_ci{ 19058c2ecf20Sopenharmony_ci struct kvaser_pciefd *pcie = pci_get_drvdata(pdev); 19068c2ecf20Sopenharmony_ci 19078c2ecf20Sopenharmony_ci kvaser_pciefd_remove_all_ctrls(pcie); 19088c2ecf20Sopenharmony_ci 19098c2ecf20Sopenharmony_ci /* Turn off IRQ generation */ 19108c2ecf20Sopenharmony_ci iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SRB_CTRL_REG); 19118c2ecf20Sopenharmony_ci iowrite32(KVASER_PCIEFD_IRQ_ALL_MSK, 19128c2ecf20Sopenharmony_ci pcie->reg_base + KVASER_PCIEFD_IRQ_REG); 19138c2ecf20Sopenharmony_ci iowrite32(0, pcie->reg_base + KVASER_PCIEFD_IEN_REG); 19148c2ecf20Sopenharmony_ci 19158c2ecf20Sopenharmony_ci free_irq(pcie->pci->irq, pcie); 19168c2ecf20Sopenharmony_ci 19178c2ecf20Sopenharmony_ci pci_clear_master(pdev); 19188c2ecf20Sopenharmony_ci pci_iounmap(pdev, pcie->reg_base); 19198c2ecf20Sopenharmony_ci pci_release_regions(pdev); 19208c2ecf20Sopenharmony_ci pci_disable_device(pdev); 19218c2ecf20Sopenharmony_ci} 19228c2ecf20Sopenharmony_ci 19238c2ecf20Sopenharmony_cistatic struct pci_driver kvaser_pciefd = { 19248c2ecf20Sopenharmony_ci .name = KVASER_PCIEFD_DRV_NAME, 19258c2ecf20Sopenharmony_ci .id_table = kvaser_pciefd_id_table, 19268c2ecf20Sopenharmony_ci .probe = kvaser_pciefd_probe, 19278c2ecf20Sopenharmony_ci .remove = kvaser_pciefd_remove, 19288c2ecf20Sopenharmony_ci}; 19298c2ecf20Sopenharmony_ci 19308c2ecf20Sopenharmony_cimodule_pci_driver(kvaser_pciefd) 1931