Commit f33ad677 authored by Jimmy Assarsson's avatar Jimmy Assarsson Committed by Marc Kleine-Budde
Browse files

can: kvaser_pciefd: Add support for new Kvaser pciefd devices



Add support for new Kvaser pciefd devices, based on SmartFusion2 SoC.

Signed-off-by: default avatarJimmy Assarsson <extja@kvaser.com>
Link: https://lore.kernel.org/all/20230622151153.294844-3-extja@kvaser.com


[mkl: mark structs as static]
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent c2ad8129
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -160,8 +160,13 @@ config CAN_KVASER_PCIEFD
	    Kvaser PCIEcan 4xHS
	    Kvaser PCIEcan 2xHS v2
	    Kvaser PCIEcan HS v2
	    Kvaser PCIEcan 1xCAN v3
	    Kvaser PCIEcan 2xCAN v3
	    Kvaser PCIEcan 4xCAN v2
	    Kvaser Mini PCI Express HS v2
	    Kvaser Mini PCI Express 2xHS v2
	    Kvaser Mini PCI Express 1xCAN v3
	    Kvaser Mini PCI Express 2xCAN v3

config CAN_SLCAN
	tristate "Serial / USB serial CAN Adaptors (slcan)"
+76 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
/* Copyright (C) 2018 KVASER AB, Sweden. All rights reserved.
 * Parts of this driver are based on the following:
 *  - Kvaser linux pciefd driver (version 5.25)
 *  - Kvaser linux pciefd driver (version 5.42)
 *  - PEAK linux canfd driver
 */

@@ -40,9 +40,19 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices");
#define KVASER_PCIEFD_MINIPCIE_HS_V2_DEVICE_ID 0x0010
#define KVASER_PCIEFD_MINIPCIE_2HS_V2_DEVICE_ID 0x0011

/* SmartFusion2 based devices */
#define KVASER_PCIEFD_2CAN_V3_DEVICE_ID 0x0012
#define KVASER_PCIEFD_1CAN_V3_DEVICE_ID 0x0013
#define KVASER_PCIEFD_4CAN_V2_DEVICE_ID 0x0014
#define KVASER_PCIEFD_MINIPCIE_2CAN_V3_DEVICE_ID 0x0015
#define KVASER_PCIEFD_MINIPCIE_1CAN_V3_DEVICE_ID 0x0016

/* Altera SerDes Enable 64-bit DMA address translation */
#define KVASER_PCIEFD_ALTERA_DMA_64BIT BIT(0)

/* SmartFusion2 SerDes LSB address translation mask */
#define KVASER_PCIEFD_SF2_DMA_LSB_MASK GENMASK(31, 12)

/* Kvaser KCAN CAN controller registers */
#define KVASER_PCIEFD_KCAN_FIFO_REG 0x100
#define KVASER_PCIEFD_KCAN_FIFO_LAST_REG 0x180
@@ -269,6 +279,8 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices");
struct kvaser_pciefd;
static void kvaser_pciefd_write_dma_map_altera(struct kvaser_pciefd *pcie,
					       dma_addr_t addr, int index);
static void kvaser_pciefd_write_dma_map_sf2(struct kvaser_pciefd *pcie,
					    dma_addr_t addr, int index);

struct kvaser_pciefd_address_offset {
	u32 serdes;
@@ -311,22 +323,50 @@ static const struct kvaser_pciefd_address_offset kvaser_pciefd_altera_address_of
	.kcan_ch1 = 0x11000,
};

static const struct kvaser_pciefd_address_offset kvaser_pciefd_sf2_address_offset = {
	.serdes = 0x280c8,
	.pci_ien = 0x102004,
	.pci_irq = 0x102008,
	.sysid = 0x100000,
	.loopback = 0x103000,
	.kcan_srb_fifo = 0x120000,
	.kcan_srb = 0x121000,
	.kcan_ch0 = 0x140000,
	.kcan_ch1 = 0x142000,
};

static const struct kvaser_pciefd_irq_mask kvaser_pciefd_altera_irq_mask = {
	.kcan_rx0 = BIT(4),
	.kcan_tx = { BIT(0), BIT(1), BIT(2), BIT(3) },
	.all = GENMASK(4, 0),
};

static const struct kvaser_pciefd_irq_mask kvaser_pciefd_sf2_irq_mask = {
	.kcan_rx0 = BIT(4),
	.kcan_tx = { BIT(16), BIT(17), BIT(18), BIT(19) },
	.all = GENMASK(19, 16) | BIT(4),
};

static const struct kvaser_pciefd_dev_ops kvaser_pciefd_altera_dev_ops = {
	.kvaser_pciefd_write_dma_map = kvaser_pciefd_write_dma_map_altera,
};

static const struct kvaser_pciefd_dev_ops kvaser_pciefd_sf2_dev_ops = {
	.kvaser_pciefd_write_dma_map = kvaser_pciefd_write_dma_map_sf2,
};

static const struct kvaser_pciefd_driver_data kvaser_pciefd_altera_driver_data = {
	.address_offset = &kvaser_pciefd_altera_address_offset,
	.irq_mask = &kvaser_pciefd_altera_irq_mask,
	.ops = &kvaser_pciefd_altera_dev_ops,
};

static const struct kvaser_pciefd_driver_data kvaser_pciefd_sf2_driver_data = {
	.address_offset = &kvaser_pciefd_sf2_address_offset,
	.irq_mask = &kvaser_pciefd_sf2_irq_mask,
	.ops = &kvaser_pciefd_sf2_dev_ops,
};

struct kvaser_pciefd_can {
	struct can_priv can;
	struct kvaser_pciefd *kv_pcie;
@@ -396,6 +436,26 @@ static struct pci_device_id kvaser_pciefd_id_table[] = {
		PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_2HS_V2_DEVICE_ID),
		.driver_data = (kernel_ulong_t)&kvaser_pciefd_altera_driver_data,
	},
	{
		PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_2CAN_V3_DEVICE_ID),
		.driver_data = (kernel_ulong_t)&kvaser_pciefd_sf2_driver_data,
	},
	{
		PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_1CAN_V3_DEVICE_ID),
		.driver_data = (kernel_ulong_t)&kvaser_pciefd_sf2_driver_data,
	},
	{
		PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_4CAN_V2_DEVICE_ID),
		.driver_data = (kernel_ulong_t)&kvaser_pciefd_sf2_driver_data,
	},
	{
		PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_2CAN_V3_DEVICE_ID),
		.driver_data = (kernel_ulong_t)&kvaser_pciefd_sf2_driver_data,
	},
	{
		PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_1CAN_V3_DEVICE_ID),
		.driver_data = (kernel_ulong_t)&kvaser_pciefd_sf2_driver_data,
	},
	{
		0,
	},
@@ -960,6 +1020,21 @@ static void kvaser_pciefd_write_dma_map_altera(struct kvaser_pciefd *pcie,
	iowrite32(word2, serdes_base + 0x4);
}

static void kvaser_pciefd_write_dma_map_sf2(struct kvaser_pciefd *pcie,
					    dma_addr_t addr, int index)
{
	void __iomem *serdes_base;
	u32 lsb = addr & KVASER_PCIEFD_SF2_DMA_LSB_MASK;
	u32 msb = 0x0;

#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
	msb = addr >> 32;
#endif
	serdes_base = KVASER_PCIEFD_SERDES_ADDR(pcie) + 0x10 * index;
	iowrite32(lsb, serdes_base);
	iowrite32(msb, serdes_base + 0x4);
}

static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie)
{
	int i;