Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit abcd7f75 authored by Alexander Stein's avatar Alexander Stein Committed by Marc Kleine-Budde
Browse files

can: c_can: Add support for eg20t (pch_can)

parent 8e964fe2
Loading
Loading
Loading
Loading
+50 −1
Original line number Diff line number Diff line
@@ -19,9 +19,13 @@

#include "c_can.h"

#define PCI_DEVICE_ID_PCH_CAN	0x8818
#define PCH_PCI_SOFT_RESET	0x01fc

enum c_can_pci_reg_align {
	C_CAN_REG_ALIGN_16,
	C_CAN_REG_ALIGN_32,
	C_CAN_REG_32,
};

struct c_can_pci_data {
@@ -31,6 +35,10 @@ struct c_can_pci_data {
	enum c_can_pci_reg_align reg_align;
	/* Set the frequency */
	unsigned int freq;
	/* PCI bar number */
	int bar;
	/* Callback for reset */
	void (*init)(const struct c_can_priv *priv, bool enable);
};

/*
@@ -63,6 +71,29 @@ static void c_can_pci_write_reg_aligned_to_32bit(struct c_can_priv *priv,
	writew(val, priv->base + 2 * priv->regs[index]);
}

static u16 c_can_pci_read_reg_32bit(struct c_can_priv *priv,
				    enum reg index)
{
	return (u16)ioread32(priv->base + 2 * priv->regs[index]);
}

static void c_can_pci_write_reg_32bit(struct c_can_priv *priv,
				      enum reg index, u16 val)
{
	iowrite32((u32)val, priv->base + 2 * priv->regs[index]);
}

static void c_can_pci_reset_pch(const struct c_can_priv *priv, bool enable)
{
	if (enable) {
		u32 __iomem *addr = priv->base + PCH_PCI_SOFT_RESET;

		/* write to sw reset register */
		iowrite32(1, addr);
		iowrite32(0, addr);
	}
}

static int c_can_pci_probe(struct pci_dev *pdev,
			   const struct pci_device_id *ent)
{
@@ -87,7 +118,8 @@ static int c_can_pci_probe(struct pci_dev *pdev,
	pci_set_master(pdev);
	pci_enable_msi(pdev);

	addr = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
	addr = pci_iomap(pdev, c_can_pci_data->bar,
			 pci_resource_len(pdev, c_can_pci_data->bar));
	if (!addr) {
		dev_err(&pdev->dev,
			"device has no PCI memory resources, "
@@ -142,11 +174,17 @@ static int c_can_pci_probe(struct pci_dev *pdev,
		priv->read_reg = c_can_pci_read_reg_aligned_to_16bit;
		priv->write_reg = c_can_pci_write_reg_aligned_to_16bit;
		break;
	case C_CAN_REG_32:
		priv->read_reg = c_can_pci_read_reg_32bit;
		priv->write_reg = c_can_pci_write_reg_32bit;
		break;
	default:
		ret = -EINVAL;
		goto out_free_c_can;
	}

	priv->raminit = c_can_pci_data->init;

	ret = register_c_can_dev(dev);
	if (ret) {
		dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
@@ -193,6 +231,15 @@ static struct c_can_pci_data c_can_sta2x11= {
	.type = BOSCH_C_CAN,
	.reg_align = C_CAN_REG_ALIGN_32,
	.freq = 52000000, /* 52 Mhz */
	.bar = 0,
};

static struct c_can_pci_data c_can_pch = {
	.type = BOSCH_C_CAN,
	.reg_align = C_CAN_REG_32,
	.freq = 50000000, /* 50 MHz */
	.init = c_can_pci_reset_pch,
	.bar = 1,
};

#define C_CAN_ID(_vend, _dev, _driverdata) {		\
@@ -202,6 +249,8 @@ static struct c_can_pci_data c_can_sta2x11= {
static DEFINE_PCI_DEVICE_TABLE(c_can_pci_tbl) = {
	C_CAN_ID(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_CAN,
		 c_can_sta2x11),
	C_CAN_ID(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH_CAN,
		 c_can_pch),
	{},
};
static struct pci_driver c_can_pci_driver = {