Commit c7dd2220 authored by David S. Miller's avatar David S. Miller
Browse files

Merge tag 'linux-can-next-for-5.11-20201210' of...

Merge tag 'linux-can-next-for-5.11-20201210' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next



Marc Kleine-Budde says:

====================
pull-request: can-next 2020-12-10

here's a pull request of 7 patches for net-next/master.

The first patch is by Oliver Hartkopp for the CAN ISOTP, which adds support for
functional addressing.

A patch by Antonio Quartulli removes an unneeded unlikely() annotation from the
rx-offload helper.

The next three patches target the m_can driver. Sean Nyekjaers's patch removes
a double clearing of clock stop request bit, Patrik Flykt's patch moves the
runtime PM enable/disable to m_can_platform and Jarkko Nikula's patch adds a
PCI glue code driver.

Fabio Estevam's patch converts the flexcan driver to DT only.

And Manivannan Sadhasivam's patchd for the mcp251xfd driver adds internal
loopback mode support.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents a10b24b8 ee42bedc
Loading
Loading
Loading
Loading
+1 −17
Original line number Diff line number Diff line
@@ -1940,15 +1940,8 @@ static const struct of_device_id flexcan_of_match[] = {
};
MODULE_DEVICE_TABLE(of, flexcan_of_match);

static const struct platform_device_id flexcan_id_table[] = {
	{ .name = "flexcan", .driver_data = (kernel_ulong_t)&fsl_p1010_devtype_data, },
	{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(platform, flexcan_id_table);

static int flexcan_probe(struct platform_device *pdev)
{
	const struct of_device_id *of_id;
	const struct flexcan_devtype_data *devtype_data;
	struct net_device *dev;
	struct flexcan_priv *priv;
@@ -1997,15 +1990,7 @@ static int flexcan_probe(struct platform_device *pdev)
	if (IS_ERR(regs))
		return PTR_ERR(regs);

	of_id = of_match_device(flexcan_of_match, &pdev->dev);
	if (of_id) {
		devtype_data = of_id->data;
	} else if (platform_get_device_id(pdev)->driver_data) {
		devtype_data = (struct flexcan_devtype_data *)
			platform_get_device_id(pdev)->driver_data;
	} else {
		return -ENODEV;
	}
	devtype_data = of_device_get_match_data(&pdev->dev);

	if ((devtype_data->quirks & FLEXCAN_QUIRK_SUPPORT_FD) &&
	    !(devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP)) {
@@ -2235,7 +2220,6 @@ static struct platform_driver flexcan_driver = {
	},
	.probe = flexcan_probe,
	.remove = flexcan_remove,
	.id_table = flexcan_id_table,
};

module_platform_driver(flexcan_driver);
+7 −0
Original line number Diff line number Diff line
@@ -7,6 +7,13 @@ menuconfig CAN_M_CAN

if CAN_M_CAN

config CAN_M_CAN_PCI
	tristate "Generic PCI Bus based M_CAN driver"
	depends on PCI
	help
	  Say Y here if you want to support Bosch M_CAN controller connected
	  to the pci bus.

config CAN_M_CAN_PLATFORM
	tristate "Bosch M_CAN support for io-mapped devices"
	depends on HAS_IOMEM
+1 −0
Original line number Diff line number Diff line
@@ -4,5 +4,6 @@
#

obj-$(CONFIG_CAN_M_CAN) += m_can.o
obj-$(CONFIG_CAN_M_CAN_PCI) += m_can_pci.o
obj-$(CONFIG_CAN_M_CAN_PLATFORM) += m_can_platform.o
obj-$(CONFIG_CAN_M_CAN_TCAN4X5X) += tcan4x5x.o
+1 −11
Original line number Diff line number Diff line
@@ -380,10 +380,6 @@ void m_can_config_endisable(struct m_can_classdev *cdev, bool enable)
		cccr &= ~CCCR_CSR;

	if (enable) {
		/* Clear the Clock stop request if it was set */
		if (cccr & CCCR_CSR)
			cccr &= ~CCCR_CSR;

		/* enable m_can configuration */
		m_can_write(cdev, M_CAN_CCCR, cccr | CCCR_INIT);
		udelay(5);
@@ -1830,10 +1826,9 @@ int m_can_class_register(struct m_can_classdev *m_can_dev)
	int ret;

	if (m_can_dev->pm_clock_support) {
		pm_runtime_enable(m_can_dev->dev);
		ret = m_can_clk_start(m_can_dev);
		if (ret)
			goto pm_runtime_fail;
			return ret;
	}

	ret = m_can_dev_setup(m_can_dev);
@@ -1859,11 +1854,6 @@ int m_can_class_register(struct m_can_classdev *m_can_dev)
	 */
clk_disable:
	m_can_clk_stop(m_can_dev);
pm_runtime_fail:
	if (ret) {
		if (m_can_dev->pm_clock_support)
			pm_runtime_disable(m_can_dev->dev);
	}

	return ret;
}
+186 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/*
 * PCI Specific M_CAN Glue
 *
 * Copyright (C) 2018-2020 Intel Corporation
 * Author: Felipe Balbi (Intel)
 * Author: Jarkko Nikula <jarkko.nikula@linux.intel.com>
 * Author: Raymond Tan <raymond.tan@intel.com>
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/pci.h>
#include <linux/pm_runtime.h>

#include "m_can.h"

#define M_CAN_PCI_MMIO_BAR		0

#define M_CAN_CLOCK_FREQ_EHL		100000000
#define CTL_CSR_INT_CTL_OFFSET		0x508

struct m_can_pci_priv {
	void __iomem *base;
};

static u32 iomap_read_reg(struct m_can_classdev *cdev, int reg)
{
	struct m_can_pci_priv *priv = cdev->device_data;

	return readl(priv->base + reg);
}

static u32 iomap_read_fifo(struct m_can_classdev *cdev, int offset)
{
	struct m_can_pci_priv *priv = cdev->device_data;

	return readl(priv->base + offset);
}

static int iomap_write_reg(struct m_can_classdev *cdev, int reg, int val)
{
	struct m_can_pci_priv *priv = cdev->device_data;

	writel(val, priv->base + reg);

	return 0;
}

static int iomap_write_fifo(struct m_can_classdev *cdev, int offset, int val)
{
	struct m_can_pci_priv *priv = cdev->device_data;

	writel(val, priv->base + offset);

	return 0;
}

static struct m_can_ops m_can_pci_ops = {
	.read_reg = iomap_read_reg,
	.write_reg = iomap_write_reg,
	.write_fifo = iomap_write_fifo,
	.read_fifo = iomap_read_fifo,
};

static int m_can_pci_probe(struct pci_dev *pci, const struct pci_device_id *id)
{
	struct device *dev = &pci->dev;
	struct m_can_classdev *mcan_class;
	struct m_can_pci_priv *priv;
	void __iomem *base;
	int ret;

	ret = pcim_enable_device(pci);
	if (ret)
		return ret;

	pci_set_master(pci);

	ret = pcim_iomap_regions(pci, BIT(M_CAN_PCI_MMIO_BAR), pci_name(pci));
	if (ret)
		return ret;

	base = pcim_iomap_table(pci)[M_CAN_PCI_MMIO_BAR];

	if (!base) {
		dev_err(dev, "failed to map BARs\n");
		return -ENOMEM;
	}

	priv = devm_kzalloc(&pci->dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;

	mcan_class = m_can_class_allocate_dev(&pci->dev);
	if (!mcan_class)
		return -ENOMEM;

	priv->base = base;

	ret = pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_ALL_TYPES);
	if (ret < 0)
		return ret;

	mcan_class->device_data = priv;
	mcan_class->dev = &pci->dev;
	mcan_class->net->irq = pci_irq_vector(pci, 0);
	mcan_class->pm_clock_support = 1;
	mcan_class->can.clock.freq = id->driver_data;
	mcan_class->ops = &m_can_pci_ops;

	pci_set_drvdata(pci, mcan_class->net);

	ret = m_can_class_register(mcan_class);
	if (ret)
		goto err;

	/* Enable interrupt control at CAN wrapper IP */
	writel(0x1, base + CTL_CSR_INT_CTL_OFFSET);

	pm_runtime_set_autosuspend_delay(dev, 1000);
	pm_runtime_use_autosuspend(dev);
	pm_runtime_put_noidle(dev);
	pm_runtime_allow(dev);

	return 0;

err:
	pci_free_irq_vectors(pci);
	return ret;
}

static void m_can_pci_remove(struct pci_dev *pci)
{
	struct net_device *dev = pci_get_drvdata(pci);
	struct m_can_classdev *mcan_class = netdev_priv(dev);
	struct m_can_pci_priv *priv = mcan_class->device_data;

	pm_runtime_forbid(&pci->dev);
	pm_runtime_get_noresume(&pci->dev);

	/* Disable interrupt control at CAN wrapper IP */
	writel(0x0, priv->base + CTL_CSR_INT_CTL_OFFSET);

	m_can_class_unregister(mcan_class);
	pci_free_irq_vectors(pci);
}

static __maybe_unused int m_can_pci_suspend(struct device *dev)
{
	return m_can_class_suspend(dev);
}

static __maybe_unused int m_can_pci_resume(struct device *dev)
{
	return m_can_class_resume(dev);
}

static SIMPLE_DEV_PM_OPS(m_can_pci_pm_ops,
			 m_can_pci_suspend, m_can_pci_resume);

static const struct pci_device_id m_can_pci_id_table[] = {
	{ PCI_VDEVICE(INTEL, 0x4bc1), M_CAN_CLOCK_FREQ_EHL, },
	{ PCI_VDEVICE(INTEL, 0x4bc2), M_CAN_CLOCK_FREQ_EHL, },
	{  }	/* Terminating Entry */
};
MODULE_DEVICE_TABLE(pci, m_can_pci_id_table);

static struct pci_driver m_can_pci_driver = {
	.name = "m_can_pci",
	.probe = m_can_pci_probe,
	.remove = m_can_pci_remove,
	.id_table = m_can_pci_id_table,
	.driver = {
		.pm = &m_can_pci_pm_ops,
	},
};

module_pci_driver(m_can_pci_driver);

MODULE_AUTHOR("Felipe Balbi (Intel)");
MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@linux.intel.com>");
MODULE_AUTHOR("Raymond Tan <raymond.tan@intel.com>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("CAN bus driver for Bosch M_CAN controller on PCI bus");
Loading