Commit f876a784 authored by David S. Miller's avatar David S. Miller

Merge tag 'linux-can-next-for-5.4-20190724' of...

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

Marc Kleine-Budde says:

====================
pull-request: can-next 2019-07-24

this is a pull request for net-next/master consisting of 26 patches.

The first two patches are by me. One adds missing files of the CAN
subsystem to the MAINTAINERS file, while the other sorts the
Makefile/Kconfig of the sja1000 drivers sub directory. In the next patch
Ji-Ze Hong (Peter Hong) provides a driver for the "Fintek PCIE to 2 CAN"
controller, based on the the sja1000 IP core.

Gustavo A. R. Silva's patch for the kvaser_usb driver introduces the use
of struct_size() instead of open coding it. Henning Colliander's patch
adds a driver for the "Kvaser PCIEcan" devices.

Another patch by Gustavo A. R. Silva marks expected switch fall-throughs
properly.

Dan Murphy provides 5 patches for the m_can. After cleanups a framework
is introduced so that the driver can be used from memory mapped IO as
well as SPI attached devices. Finally he adds a driver for the tcan4x5x
which uses this framework.

A series of 5 patches by Appana Durga Kedareswara rao for the xilinx_can
driver, first clean up,then add support for CANFD. Colin Ian King
contributes another cleanup for the xilinx_can driver.

Robert P. J. Day's patch corrects the brief history of the CAN protocol
given in the Kconfig menu entry.

2 patches by Dong Aisheng for the flexcan driver provide PE clock source
select support and dt-bindings description.
2 patches by Sean Nyekjaer for the flexcan driver provide add CAN
wakeup-source property and dt-bindings description.

Jeroen Hofstee's patch converts the ti_hecc driver to make use of the
rx-offload helper fixing a number of outstanding bugs.

The first patch of Oliver Hartkopp removes the now obsolete empty
ioctl() handler for the CAN protocols. The second patch adds SPDX
license identifiers for CAN subsystem.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 570d785b fba76a58
...@@ -32,6 +32,15 @@ Optional properties: ...@@ -32,6 +32,15 @@ Optional properties:
ack_gpr is the gpr register offset of CAN stop acknowledge. ack_gpr is the gpr register offset of CAN stop acknowledge.
ack_bit is the bit offset of CAN stop acknowledge. ack_bit is the bit offset of CAN stop acknowledge.
- fsl,clk-source: Select the clock source to the CAN Protocol Engine (PE).
It's SoC Implementation dependent. Refer to RM for detailed
definition. If this property is not set in device tree node
then driver selects clock source 1 by default.
0: clock source 0 (oscillator clock)
1: clock source 1 (peripheral clock)
- wakeup-source: enable CAN remote wakeup
Example: Example:
can@1c000 { can@1c000 {
...@@ -40,4 +49,5 @@ Example: ...@@ -40,4 +49,5 @@ Example:
interrupts = <48 0x2>; interrupts = <48 0x2>;
interrupt-parent = <&mpic>; interrupt-parent = <&mpic>;
clock-frequency = <200000000>; // filled in by bootloader clock-frequency = <200000000>; // filled in by bootloader
fsl,clk-source = <0>; // select clock source 0 for PE
}; };
Texas Instruments TCAN4x5x CAN Controller
================================================
This file provides device node information for the TCAN4x5x interface contains.
Required properties:
- compatible: "ti,tcan4x5x"
- reg: 0
- #address-cells: 1
- #size-cells: 0
- spi-max-frequency: Maximum frequency of the SPI bus the chip can
operate at should be less than or equal to 18 MHz.
- data-ready-gpios: Interrupt GPIO for data and error reporting.
- device-wake-gpios: Wake up GPIO to wake up the TCAN device.
See Documentation/devicetree/bindings/net/can/m_can.txt for additional
required property details.
Optional properties:
- reset-gpios: Hardwired output GPIO. If not defined then software
reset.
- device-state-gpios: Input GPIO that indicates if the device is in
a sleep state or if the device is active.
Example:
tcan4x5x: tcan4x5x@0 {
compatible = "ti,tcan4x5x";
reg = <0>;
#address-cells = <1>;
#size-cells = <1>;
spi-max-frequency = <10000000>;
bosch,mram-cfg = <0x0 0 0 32 0 0 1 1>;
data-ready-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
device-state-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
device-wake-gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>;
reset-gpios = <&gpio1 27 GPIO_ACTIVE_LOW>;
};
...@@ -3631,9 +3631,12 @@ S: Maintained ...@@ -3631,9 +3631,12 @@ S: Maintained
F: Documentation/devicetree/bindings/net/can/ F: Documentation/devicetree/bindings/net/can/
F: drivers/net/can/ F: drivers/net/can/
F: include/linux/can/dev.h F: include/linux/can/dev.h
F: include/linux/can/led.h
F: include/linux/can/rx-offload.h
F: include/linux/can/platform/ F: include/linux/can/platform/
F: include/uapi/linux/can/error.h F: include/uapi/linux/can/error.h
F: include/uapi/linux/can/netlink.h F: include/uapi/linux/can/netlink.h
F: include/uapi/linux/can/vxcan.h
CAN NETWORK LAYER CAN NETWORK LAYER
M: Oliver Hartkopp <socketcan@hartkopp.net> M: Oliver Hartkopp <socketcan@hartkopp.net>
...@@ -3646,6 +3649,8 @@ S: Maintained ...@@ -3646,6 +3649,8 @@ S: Maintained
F: Documentation/networking/can.rst F: Documentation/networking/can.rst
F: net/can/ F: net/can/
F: include/linux/can/core.h F: include/linux/can/core.h
F: include/linux/can/skb.h
F: include/net/netns/can.h
F: include/uapi/linux/can.h F: include/uapi/linux/can.h
F: include/uapi/linux/can/bcm.h F: include/uapi/linux/can/bcm.h
F: include/uapi/linux/can/raw.h F: include/uapi/linux/can/raw.h
......
...@@ -120,6 +120,19 @@ config CAN_JANZ_ICAN3 ...@@ -120,6 +120,19 @@ config CAN_JANZ_ICAN3
This driver can also be built as a module. If so, the module will be This driver can also be built as a module. If so, the module will be
called janz-ican3.ko. called janz-ican3.ko.
config CAN_KVASER_PCIEFD
depends on PCI
tristate "Kvaser PCIe FD cards"
help
This is a driver for the Kvaser PCI Express CAN FD family.
Supported devices:
Kvaser PCIEcan 4xHS
Kvaser PCIEcan 2xHS v2
Kvaser PCIEcan HS v2
Kvaser Mini PCI Express HS v2
Kvaser Mini PCI Express 2xHS v2
config CAN_SUN4I config CAN_SUN4I
tristate "Allwinner A10 CAN controller" tristate "Allwinner A10 CAN controller"
depends on MACH_SUN4I || MACH_SUN7I || COMPILE_TEST depends on MACH_SUN4I || MACH_SUN7I || COMPILE_TEST
......
...@@ -25,6 +25,7 @@ obj-$(CONFIG_CAN_FLEXCAN) += flexcan.o ...@@ -25,6 +25,7 @@ obj-$(CONFIG_CAN_FLEXCAN) += flexcan.o
obj-$(CONFIG_CAN_GRCAN) += grcan.o obj-$(CONFIG_CAN_GRCAN) += grcan.o
obj-$(CONFIG_CAN_IFI_CANFD) += ifi_canfd/ obj-$(CONFIG_CAN_IFI_CANFD) += ifi_canfd/
obj-$(CONFIG_CAN_JANZ_ICAN3) += janz-ican3.o obj-$(CONFIG_CAN_JANZ_ICAN3) += janz-ican3.o
obj-$(CONFIG_CAN_KVASER_PCIEFD) += kvaser_pciefd.o
obj-$(CONFIG_CAN_MSCAN) += mscan/ obj-$(CONFIG_CAN_MSCAN) += mscan/
obj-$(CONFIG_CAN_M_CAN) += m_can/ obj-$(CONFIG_CAN_M_CAN) += m_can/
obj-$(CONFIG_CAN_PEAK_PCIEFD) += peak_canfd/ obj-$(CONFIG_CAN_PEAK_PCIEFD) += peak_canfd/
......
...@@ -898,7 +898,8 @@ static void at91_irq_err_state(struct net_device *dev, ...@@ -898,7 +898,8 @@ static void at91_irq_err_state(struct net_device *dev,
CAN_ERR_CRTL_TX_WARNING : CAN_ERR_CRTL_TX_WARNING :
CAN_ERR_CRTL_RX_WARNING; CAN_ERR_CRTL_RX_WARNING;
} }
case CAN_STATE_ERROR_WARNING: /* fallthrough */ /* fall through */
case CAN_STATE_ERROR_WARNING:
/* /*
* from: ERROR_ACTIVE, ERROR_WARNING * from: ERROR_ACTIVE, ERROR_WARNING
* to : ERROR_PASSIVE, BUS_OFF * to : ERROR_PASSIVE, BUS_OFF
...@@ -947,7 +948,8 @@ static void at91_irq_err_state(struct net_device *dev, ...@@ -947,7 +948,8 @@ static void at91_irq_err_state(struct net_device *dev,
netdev_dbg(dev, "Error Active\n"); netdev_dbg(dev, "Error Active\n");
cf->can_id |= CAN_ERR_PROT; cf->can_id |= CAN_ERR_PROT;
cf->data[2] = CAN_ERR_PROT_ACTIVE; cf->data[2] = CAN_ERR_PROT_ACTIVE;
case CAN_STATE_ERROR_WARNING: /* fallthrough */ /* fall through */
case CAN_STATE_ERROR_WARNING:
reg_idr = AT91_IRQ_ERRA | AT91_IRQ_WARN | AT91_IRQ_BOFF; reg_idr = AT91_IRQ_ERRA | AT91_IRQ_WARN | AT91_IRQ_BOFF;
reg_ier = AT91_IRQ_ERRP; reg_ier = AT91_IRQ_ERRP;
break; break;
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/regmap.h> #include <linux/regmap.h>
...@@ -266,6 +267,7 @@ struct flexcan_stop_mode { ...@@ -266,6 +267,7 @@ struct flexcan_stop_mode {
struct flexcan_priv { struct flexcan_priv {
struct can_priv can; struct can_priv can;
struct can_rx_offload offload; struct can_rx_offload offload;
struct device *dev;
struct flexcan_regs __iomem *regs; struct flexcan_regs __iomem *regs;
struct flexcan_mb __iomem *tx_mb; struct flexcan_mb __iomem *tx_mb;
...@@ -273,6 +275,8 @@ struct flexcan_priv { ...@@ -273,6 +275,8 @@ struct flexcan_priv {
u8 tx_mb_idx; u8 tx_mb_idx;
u8 mb_count; u8 mb_count;
u8 mb_size; u8 mb_size;
u8 clk_src; /* clock source of CAN Protocol Engine */
u32 reg_ctrl_default; u32 reg_ctrl_default;
u32 reg_imask1_default; u32 reg_imask1_default;
u32 reg_imask2_default; u32 reg_imask2_default;
...@@ -444,6 +448,27 @@ static inline void flexcan_error_irq_disable(const struct flexcan_priv *priv) ...@@ -444,6 +448,27 @@ static inline void flexcan_error_irq_disable(const struct flexcan_priv *priv)
priv->write(reg_ctrl, &regs->ctrl); priv->write(reg_ctrl, &regs->ctrl);
} }
static int flexcan_clks_enable(const struct flexcan_priv *priv)
{
int err;
err = clk_prepare_enable(priv->clk_ipg);
if (err)
return err;
err = clk_prepare_enable(priv->clk_per);
if (err)
clk_disable_unprepare(priv->clk_ipg);
return err;
}
static void flexcan_clks_disable(const struct flexcan_priv *priv)
{
clk_disable_unprepare(priv->clk_per);
clk_disable_unprepare(priv->clk_ipg);
}
static inline int flexcan_transceiver_enable(const struct flexcan_priv *priv) static inline int flexcan_transceiver_enable(const struct flexcan_priv *priv)
{ {
if (!priv->reg_xceiver) if (!priv->reg_xceiver)
...@@ -570,19 +595,13 @@ static int flexcan_get_berr_counter(const struct net_device *dev, ...@@ -570,19 +595,13 @@ static int flexcan_get_berr_counter(const struct net_device *dev,
const struct flexcan_priv *priv = netdev_priv(dev); const struct flexcan_priv *priv = netdev_priv(dev);
int err; int err;
err = clk_prepare_enable(priv->clk_ipg); err = pm_runtime_get_sync(priv->dev);
if (err) if (err < 0)
return err; return err;
err = clk_prepare_enable(priv->clk_per);
if (err)
goto out_disable_ipg;
err = __flexcan_get_berr_counter(dev, bec); err = __flexcan_get_berr_counter(dev, bec);
clk_disable_unprepare(priv->clk_per); pm_runtime_put(priv->dev);
out_disable_ipg:
clk_disable_unprepare(priv->clk_ipg);
return err; return err;
} }
...@@ -1215,17 +1234,13 @@ static int flexcan_open(struct net_device *dev) ...@@ -1215,17 +1234,13 @@ static int flexcan_open(struct net_device *dev)
struct flexcan_priv *priv = netdev_priv(dev); struct flexcan_priv *priv = netdev_priv(dev);
int err; int err;
err = clk_prepare_enable(priv->clk_ipg); err = pm_runtime_get_sync(priv->dev);
if (err) if (err < 0)
return err; return err;
err = clk_prepare_enable(priv->clk_per);
if (err)
goto out_disable_ipg;
err = open_candev(dev); err = open_candev(dev);
if (err) if (err)
goto out_disable_per; goto out_runtime_put;
err = request_irq(dev->irq, flexcan_irq, IRQF_SHARED, dev->name, dev); err = request_irq(dev->irq, flexcan_irq, IRQF_SHARED, dev->name, dev);
if (err) if (err)
...@@ -1288,10 +1303,8 @@ static int flexcan_open(struct net_device *dev) ...@@ -1288,10 +1303,8 @@ static int flexcan_open(struct net_device *dev)
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
out_close: out_close:
close_candev(dev); close_candev(dev);
out_disable_per: out_runtime_put:
clk_disable_unprepare(priv->clk_per); pm_runtime_put(priv->dev);
out_disable_ipg:
clk_disable_unprepare(priv->clk_ipg);
return err; return err;
} }
...@@ -1306,10 +1319,9 @@ static int flexcan_close(struct net_device *dev) ...@@ -1306,10 +1319,9 @@ static int flexcan_close(struct net_device *dev)
can_rx_offload_del(&priv->offload); can_rx_offload_del(&priv->offload);
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
clk_disable_unprepare(priv->clk_per);
clk_disable_unprepare(priv->clk_ipg);
close_candev(dev); close_candev(dev);
pm_runtime_put(priv->dev);
can_led_event(dev, CAN_LED_EVENT_STOP); can_led_event(dev, CAN_LED_EVENT_STOP);
...@@ -1349,20 +1361,20 @@ static int register_flexcandev(struct net_device *dev) ...@@ -1349,20 +1361,20 @@ static int register_flexcandev(struct net_device *dev)
struct flexcan_regs __iomem *regs = priv->regs; struct flexcan_regs __iomem *regs = priv->regs;
u32 reg, err; u32 reg, err;
err = clk_prepare_enable(priv->clk_ipg); err = flexcan_clks_enable(priv);
if (err) if (err)
return err; return err;
err = clk_prepare_enable(priv->clk_per);
if (err)
goto out_disable_ipg;
/* select "bus clock", chip must be disabled */ /* select "bus clock", chip must be disabled */
err = flexcan_chip_disable(priv); err = flexcan_chip_disable(priv);
if (err) if (err)
goto out_disable_per; goto out_clks_disable;
reg = priv->read(&regs->ctrl); reg = priv->read(&regs->ctrl);
reg |= FLEXCAN_CTRL_CLK_SRC; if (priv->clk_src)
reg |= FLEXCAN_CTRL_CLK_SRC;
else
reg &= ~FLEXCAN_CTRL_CLK_SRC;
priv->write(reg, &regs->ctrl); priv->write(reg, &regs->ctrl);
err = flexcan_chip_enable(priv); err = flexcan_chip_enable(priv);
...@@ -1388,15 +1400,21 @@ static int register_flexcandev(struct net_device *dev) ...@@ -1388,15 +1400,21 @@ static int register_flexcandev(struct net_device *dev)
} }
err = register_candev(dev); err = register_candev(dev);
if (err)
goto out_chip_disable;
/* disable core and turn off clocks */ /* Disable core and let pm_runtime_put() disable the clocks.
out_chip_disable: * If CONFIG_PM is not enabled, the clocks will stay powered.
*/
flexcan_chip_disable(priv); flexcan_chip_disable(priv);
out_disable_per: pm_runtime_put(priv->dev);
clk_disable_unprepare(priv->clk_per);
out_disable_ipg: return 0;
clk_disable_unprepare(priv->clk_ipg);
out_chip_disable:
flexcan_chip_disable(priv);
out_clks_disable:
flexcan_clks_disable(priv);
return err; return err;
} }
...@@ -1455,6 +1473,9 @@ static int flexcan_setup_stop_mode(struct platform_device *pdev) ...@@ -1455,6 +1473,9 @@ static int flexcan_setup_stop_mode(struct platform_device *pdev)
device_set_wakeup_capable(&pdev->dev, true); device_set_wakeup_capable(&pdev->dev, true);
if (of_property_read_bool(np, "wakeup-source"))
device_set_wakeup_enable(&pdev->dev, true);
return 0; return 0;
} }
...@@ -1488,6 +1509,7 @@ static int flexcan_probe(struct platform_device *pdev) ...@@ -1488,6 +1509,7 @@ static int flexcan_probe(struct platform_device *pdev)
struct clk *clk_ipg = NULL, *clk_per = NULL; struct clk *clk_ipg = NULL, *clk_per = NULL;
struct flexcan_regs __iomem *regs; struct flexcan_regs __iomem *regs;
int err, irq; int err, irq;
u8 clk_src = 1;
u32 clock_freq = 0; u32 clock_freq = 0;
reg_xceiver = devm_regulator_get(&pdev->dev, "xceiver"); reg_xceiver = devm_regulator_get(&pdev->dev, "xceiver");
...@@ -1496,9 +1518,12 @@ static int flexcan_probe(struct platform_device *pdev) ...@@ -1496,9 +1518,12 @@ static int flexcan_probe(struct platform_device *pdev)
else if (IS_ERR(reg_xceiver)) else if (IS_ERR(reg_xceiver))
reg_xceiver = NULL; reg_xceiver = NULL;
if (pdev->dev.of_node) if (pdev->dev.of_node) {
of_property_read_u32(pdev->dev.of_node, of_property_read_u32(pdev->dev.of_node,
"clock-frequency", &clock_freq); "clock-frequency", &clock_freq);
of_property_read_u8(pdev->dev.of_node,
"fsl,clk-source", &clk_src);
}
if (!clock_freq) { if (!clock_freq) {
clk_ipg = devm_clk_get(&pdev->dev, "ipg"); clk_ipg = devm_clk_get(&pdev->dev, "ipg");
...@@ -1556,6 +1581,7 @@ static int flexcan_probe(struct platform_device *pdev) ...@@ -1556,6 +1581,7 @@ static int flexcan_probe(struct platform_device *pdev)
priv->write = flexcan_write_le; priv->write = flexcan_write_le;
} }
priv->dev = &pdev->dev;
priv->can.clock.freq = clock_freq; priv->can.clock.freq = clock_freq;
priv->can.bittiming_const = &flexcan_bittiming_const; priv->can.bittiming_const = &flexcan_bittiming_const;
priv->can.do_set_mode = flexcan_set_mode; priv->can.do_set_mode = flexcan_set_mode;
...@@ -1566,9 +1592,14 @@ static int flexcan_probe(struct platform_device *pdev) ...@@ -1566,9 +1592,14 @@ static int flexcan_probe(struct platform_device *pdev)
priv->regs = regs; priv->regs = regs;
priv->clk_ipg = clk_ipg; priv->clk_ipg = clk_ipg;
priv->clk_per = clk_per; priv->clk_per = clk_per;
priv->clk_src = clk_src;
priv->devtype_data = devtype_data; priv->devtype_data = devtype_data;
priv->reg_xceiver = reg_xceiver; priv->reg_xceiver = reg_xceiver;
pm_runtime_get_noresume(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
err = register_flexcandev(dev); err = register_flexcandev(dev);
if (err) { if (err) {
dev_err(&pdev->dev, "registering netdev failed\n"); dev_err(&pdev->dev, "registering netdev failed\n");
...@@ -1595,6 +1626,7 @@ static int flexcan_remove(struct platform_device *pdev) ...@@ -1595,6 +1626,7 @@ static int flexcan_remove(struct platform_device *pdev)
struct net_device *dev = platform_get_drvdata(pdev); struct net_device *dev = platform_get_drvdata(pdev);
unregister_flexcandev(dev); unregister_flexcandev(dev);
pm_runtime_disable(&pdev->dev);
free_candev(dev); free_candev(dev);
return 0; return 0;
...@@ -1604,7 +1636,7 @@ static int __maybe_unused flexcan_suspend(struct device *device) ...@@ -1604,7 +1636,7 @@ static int __maybe_unused flexcan_suspend(struct device *device)
{ {
struct net_device *dev = dev_get_drvdata(device); struct net_device *dev = dev_get_drvdata(device);
struct flexcan_priv *priv = netdev_priv(dev); struct flexcan_priv *priv = netdev_priv(dev);
int err; int err = 0;
if (netif_running(dev)) { if (netif_running(dev)) {
/* if wakeup is enabled, enter stop mode /* if wakeup is enabled, enter stop mode
...@@ -1617,20 +1649,22 @@ static int __maybe_unused flexcan_suspend(struct device *device) ...@@ -1617,20 +1649,22 @@ static int __maybe_unused flexcan_suspend(struct device *device)
err = flexcan_chip_disable(priv); err = flexcan_chip_disable(priv);
if (err) if (err)
return err; return err;
err = pm_runtime_force_suspend(device);
} }
netif_stop_queue(dev); netif_stop_queue(dev);
netif_device_detach(dev); netif_device_detach(dev);
} }
priv->can.state = CAN_STATE_SLEEPING; priv->can.state = CAN_STATE_SLEEPING;
return 0; return err;
} }
static int __maybe_unused flexcan_resume(struct device *device) static int __maybe_unused flexcan_resume(struct device *device)
{ {
struct net_device *dev = dev_get_drvdata(device); struct net_device *dev = dev_get_drvdata(device);
struct flexcan_priv *priv = netdev_priv(dev); struct flexcan_priv *priv = netdev_priv(dev);
int err; int err = 0;
priv->can.state = CAN_STATE_ERROR_ACTIVE; priv->can.state = CAN_STATE_ERROR_ACTIVE;
if (netif_running(dev)) { if (netif_running(dev)) {
...@@ -1639,14 +1673,35 @@ static int __maybe_unused flexcan_resume(struct device *device) ...@@ -1639,14 +1673,35 @@ static int __maybe_unused flexcan_resume(struct device *device)
if (device_may_wakeup(device)) { if (device_may_wakeup(device)) {
disable_irq_wake(dev->irq); disable_irq_wake(dev->irq);
} else { } else {
err = flexcan_chip_enable(priv); err = pm_runtime_force_resume(device);
if (err) if (err)
return err; return err;
err = flexcan_chip_enable(priv);
} }
} }
return err;
}
static int __maybe_unused flexcan_runtime_suspend(struct device *device)
{
struct net_device *dev = dev_get_drvdata(device);
struct flexcan_priv *priv = netdev_priv(dev);
flexcan_clks_disable(priv);
return 0; return 0;
} }
static int __maybe_unused flexcan_runtime_resume(struct device *device)
{
struct net_device *dev = dev_get_drvdata(device);
struct flexcan_priv *priv = netdev_priv(dev);
return flexcan_clks_enable(priv);
}
static int __maybe_unused flexcan_noirq_suspend(struct device *device) static int __maybe_unused flexcan_noirq_suspend(struct device *device)
{ {
struct net_device *dev = dev_get_drvdata(device); struct net_device *dev = dev_get_drvdata(device);
...@@ -1673,6 +1728,7 @@ static int __maybe_unused flexcan_noirq_resume(struct device *device) ...@@ -1673,6 +1728,7 @@ static int __maybe_unused flexcan_noirq_resume(struct device *device)
static const struct dev_pm_ops flexcan_pm_ops = { static const struct dev_pm_ops flexcan_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(flexcan_suspend, flexcan_resume) SET_SYSTEM_SLEEP_PM_OPS(flexcan_suspend, flexcan_resume)
SET_RUNTIME_PM_OPS(flexcan_runtime_suspend, flexcan_runtime_resume, NULL)
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(flexcan_noirq_suspend, flexcan_noirq_resume) SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(flexcan_noirq_suspend, flexcan_noirq_resume)
}; };
......
This diff is collapsed.
# SPDX-License-Identifier: GPL-2.0-only # SPDX-License-Identifier: GPL-2.0-only
config CAN_M_CAN config CAN_M_CAN
tristate "Bosch M_CAN support"
---help---
Say Y here if you want support for Bosch M_CAN controller framework.
This is common support for devices that embed the Bosch M_CAN IP.
config CAN_M_CAN_PLATFORM
tristate "Bosch M_CAN support for io-mapped devices"
depends on HAS_IOMEM depends on HAS_IOMEM
tristate "Bosch M_CAN devices" depends on CAN_M_CAN
---help---
Say Y here if you want support for IO Mapped Bosch M_CAN controller.
This support is for devices that have the Bosch M_CAN controller
IP embedded into the device and the IP is IO Mapped to the processor.
config CAN_M_CAN_TCAN4X5X
depends on CAN_M_CAN
depends on REGMAP_SPI
tristate "TCAN4X5X M_CAN device"
---help--- ---help---
Say Y here if you want to support for Bosch M_CAN controller. Say Y here if you want support for Texas Instruments TCAN4x5x
M_CAN controller. This device is a peripherial device that uses the
SPI bus for communication.
...@@ -4,3 +4,5 @@ ...@@ -4,3 +4,5 @@
# #
obj-$(CONFIG_CAN_M_CAN) += m_can.o obj-$(CONFIG_CAN_M_CAN) += m_can.o
obj-$(CONFIG_CAN_M_CAN_PLATFORM) += m_can_platform.o
obj-$(CONFIG_CAN_M_CAN_TCAN4X5X) += tcan4x5x.o
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0 */
/* CAN bus driver for Bosch M_CAN controller
* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
*/
#ifndef _CAN_M_CAN_H_
#define _CAN_M_CAN_H_
#include <linux/can/core.h>
#include <linux/can/led.h>
#include <linux/completion.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/freezer.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pm_runtime.h>
#include <linux/iopoll.h>
#include <linux/can/dev.h>
#include <linux/pinctrl/consumer.h>
/* m_can lec values */
enum m_can_lec_type {
LEC_NO_ERROR = 0,
LEC_STUFF_ERROR,
LEC_FORM_ERROR,
LEC_ACK_ERROR,
LEC_BIT1_ERROR,
LEC_BIT0_ERROR,
LEC_CRC_ERROR,
LEC_UNUSED,
};
enum m_can_mram_cfg {
MRAM_SIDF = 0,
MRAM_XIDF,
MRAM_RXF0,
MRAM_RXF1,
MRAM_RXB,
MRAM_TXE,
MRAM_TXB,
MRAM_CFG_NUM,
};
/* address offset and element number for each FIFO/Buffer in the Message RAM */
struct mram_cfg {
u16 off;
u8 num;
};
struct m_can_classdev;
struct m_can_ops {
/* Device specific call backs */
int (*clear_interrupts)(struct m_can_classdev *cdev);
u32 (*read_reg)(struct m_can_classdev *cdev, int reg);
int (*write_reg)(struct m_can_classdev *cdev, int reg, int val);
u32 (*read_fifo)(struct m_can_classdev *cdev, int addr_offset);
int (*write_fifo)(struct m_can_classdev *cdev, int addr_offset,
int val);
int (*init)(struct m_can_classdev *cdev);
};
struct m_can_classdev {
struct can_priv can;
struct napi_struct napi;
struct net_device *net;
struct device *dev;
struct clk *hclk;
struct clk *cclk;
struct workqueue_struct *tx_wq;
struct work_struct tx_work;
struct sk_buff *tx_skb;
struct can_bittiming_const *bit_timing;
struct can_bittiming_const *data_timing;
struct m_can_ops *ops;
void *device_data;
int version;
int freq;
u32 irqstatus;
int pm_clock_support;
int is_peripheral;
struct mram_cfg mcfg[MRAM_CFG_NUM];
};
struct m_can_classdev *m_can_class_allocate_dev(struct device *dev);
int m_can_class_register(struct m_can_classdev *cdev);
void m_can_class_unregister(struct m_can_classdev *cdev);
int m_can_class_get_clocks(struct m_can_classdev *cdev);
void m_can_init_ram(struct m_can_classdev *priv);
void m_can_config_endisable(struct m_can_classdev *priv, bool enable);
int m_can_class_suspend(struct device *dev);
int m_can_class_resume(struct device *dev);
#endif /* _CAN_M_H_ */
// SPDX-License-Identifier: GPL-2.0
// IOMapped CAN bus driver for Bosch M_CAN controller
// Copyright (C) 2014 Freescale Semiconductor, Inc.
// Dong Aisheng <b29396@freescale.com>
//
// Copyright (C) 2018-19 Texas Instruments Incorporated - http://www.ti.com/
#include <linux/platform_device.h>
#include "m_can.h"
struct m_can_plat_priv {
void __iomem *base;
void __iomem *mram_base;
};
static u32 iomap_read_reg(struct m_can_classdev *cdev, int reg)
{
struct m_can_plat_priv *priv =
(struct m_can_plat_priv *)cdev->device_data;
return readl(priv->base + reg);
}
static u32 iomap_read_fifo(struct m_can_classdev *cdev, int offset)
{
struct m_can_plat_priv *priv =
(struct m_can_plat_priv *)cdev->device_data;
return readl(priv->mram_base + offset);
}
static int iomap_write_reg(struct m_can_classdev *cdev, int reg, int val)
{
struct m_can_plat_priv *priv =
(struct m_can_plat_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_plat_priv *priv =
(struct m_can_plat_priv *)cdev->device_data;
writel(val, priv->mram_base + offset);
return 0;
}
static struct m_can_ops m_can_plat_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_plat_probe(struct platform_device *pdev)
{
struct m_can_classdev *mcan_class;
struct m_can_plat_priv *priv;
struct resource *res;
void __iomem *addr;
void __iomem *mram_addr;
int irq, ret = 0;
mcan_class = m_can_class_allocate_dev(&pdev->dev);
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
mcan_class->device_data = priv;
m_can_class_get_clocks(mcan_class);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "m_can");
addr = devm_ioremap_resource(&pdev->dev, res);
irq = platform_get_irq_byname(pdev, "int0");
if (IS_ERR(addr) || irq < 0) {
ret = -EINVAL;
goto failed_ret;
}
/* message ram could be shared */
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "message_ram");
if (!res) {
ret = -ENODEV;
goto failed_ret;
}
mram_addr = devm_ioremap(&pdev->dev, res->start, resource_size(res));
if (!mram_addr) {
ret = -ENOMEM;
goto failed_ret;
}
priv->base = addr;
priv->mram_base = mram_addr;
mcan_class->net->irq = irq;
mcan_class->pm_clock_support = 1;
mcan_class->can.clock.freq = clk_get_rate(mcan_class->cclk);
mcan_class->dev = &pdev->dev;
mcan_class->ops = &m_can_plat_ops;
mcan_class->is_peripheral = false;
platform_set_drvdata(pdev, mcan_class->dev);
m_can_init_ram(mcan_class);
ret = m_can_class_register(mcan_class);
failed_ret:
return ret;
}
static __maybe_unused int m_can_suspend(struct device *dev)
{
return m_can_class_suspend(dev);
}
static __maybe_unused int m_can_resume(struct device *dev)
{
return m_can_class_resume(dev);
}
static int m_can_plat_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct m_can_classdev *mcan_class = netdev_priv(dev);
m_can_class_unregister(mcan_class);
platform_set_drvdata(pdev, NULL);
return 0;
}
static int __maybe_unused m_can_runtime_suspend(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
struct m_can_classdev *mcan_class = netdev_priv(ndev);
m_can_class_suspend(dev);
clk_disable_unprepare(mcan_class->cclk);
clk_disable_unprepare(mcan_class->hclk);
return 0;
}
static int __maybe_unused m_can_runtime_resume(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
struct m_can_classdev *mcan_class = netdev_priv(ndev);
int err;
err = clk_prepare_enable(mcan_class->hclk);
if (err)
return err;
err = clk_prepare_enable(mcan_class->cclk);
if (err)
clk_disable_unprepare(mcan_class->hclk);
m_can_class_resume(dev);
return err;
}
static const struct dev_pm_ops m_can_pmops = {
SET_RUNTIME_PM_OPS(m_can_runtime_suspend,
m_can_runtime_resume, NULL)
SET_SYSTEM_SLEEP_PM_OPS(m_can_suspend, m_can_resume)
};
static const struct of_device_id m_can_of_table[] = {
{ .compatible = "bosch,m_can", .data = NULL },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, m_can_of_table);
static struct platform_driver m_can_plat_driver = {
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = m_can_of_table,
.pm = &m_can_pmops,
},
.probe = m_can_plat_probe,
.remove = m_can_plat_remove,
};
module_platform_driver(m_can_plat_driver);
MODULE_AUTHOR("Dong Aisheng <b29396@freescale.com>");
MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("M_CAN driver for IO Mapped Bosch controllers");
This diff is collapsed.
...@@ -660,7 +660,7 @@ static int pciefd_can_probe(struct pciefd_board *pciefd) ...@@ -660,7 +660,7 @@ static int pciefd_can_probe(struct pciefd_board *pciefd)
pciefd_can_writereg(priv, CANFD_CLK_SEL_80MHZ, pciefd_can_writereg(priv, CANFD_CLK_SEL_80MHZ,
PCIEFD_REG_CAN_CLK_SEL); PCIEFD_REG_CAN_CLK_SEL);
/* fallthough */ /* fall through */
case CANFD_CLK_SEL_80MHZ: case CANFD_CLK_SEL_80MHZ:
priv->ucan.can.clock.freq = 80 * 1000 * 1000; priv->ucan.can.clock.freq = 80 * 1000 * 1000;
break; break;
......
This diff is collapsed.
...@@ -3,13 +3,14 @@ ...@@ -3,13 +3,14 @@
# Makefile for the SJA1000 CAN controller drivers. # Makefile for the SJA1000 CAN controller drivers.
# #
obj-$(CONFIG_CAN_SJA1000) += sja1000.o
obj-$(CONFIG_CAN_SJA1000_ISA) += sja1000_isa.o
obj-$(CONFIG_CAN_SJA1000_PLATFORM) += sja1000_platform.o
obj-$(CONFIG_CAN_EMS_PCMCIA) += ems_pcmcia.o
obj-$(CONFIG_CAN_EMS_PCI) += ems_pci.o obj-$(CONFIG_CAN_EMS_PCI) += ems_pci.o
obj-$(CONFIG_CAN_EMS_PCMCIA) += ems_pcmcia.o
obj-$(CONFIG_CAN_F81601) += f81601.o
obj-$(CONFIG_CAN_KVASER_PCI) += kvaser_pci.o obj-$(CONFIG_CAN_KVASER_PCI) += kvaser_pci.o
obj-$(CONFIG_CAN_PEAK_PCMCIA) += peak_pcmcia.o
obj-$(CONFIG_CAN_PEAK_PCI) += peak_pci.o obj-$(CONFIG_CAN_PEAK_PCI) += peak_pci.o
obj-$(CONFIG_CAN_PEAK_PCMCIA) += peak_pcmcia.o
obj-$(CONFIG_CAN_PLX_PCI) += plx_pci.o obj-$(CONFIG_CAN_PLX_PCI) += plx_pci.o
obj-$(CONFIG_CAN_SJA1000) += sja1000.o
obj-$(CONFIG_CAN_SJA1000_ISA) += sja1000_isa.o
obj-$(CONFIG_CAN_SJA1000_PLATFORM) += sja1000_platform.o
obj-$(CONFIG_CAN_TSCAN1) += tscan1.o obj-$(CONFIG_CAN_TSCAN1) += tscan1.o
This diff is collapsed.
...@@ -860,7 +860,8 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id) ...@@ -860,7 +860,8 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
if (new_state >= CAN_STATE_ERROR_WARNING && if (new_state >= CAN_STATE_ERROR_WARNING &&
new_state <= CAN_STATE_BUS_OFF) new_state <= CAN_STATE_BUS_OFF)
priv->can.can_stats.error_warning++; priv->can.can_stats.error_warning++;
case CAN_STATE_ERROR_WARNING: /* fallthrough */ /* fall through */
case CAN_STATE_ERROR_WARNING:
if (new_state >= CAN_STATE_ERROR_PASSIVE && if (new_state >= CAN_STATE_ERROR_PASSIVE &&
new_state <= CAN_STATE_BUS_OFF) new_state <= CAN_STATE_BUS_OFF)
priv->can.can_stats.error_passive++; priv->can.can_stats.error_passive++;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment