Commit 3f8a2b74 authored by David S. Miller's avatar David S. Miller

Merge tag 'linux-can-next-for-3.18-20140820' of git://gitorious.org/linux-can/linux-can-next

Marc Kleine-Budde says:

====================
pull-request: can-next 2014-08-20

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

There is one patch by Wolfram Sang to clean up the build system.
Two patches by Stefan Agner that add vf610 support to the flexcan
driver. Dong Aisheng add support for bosch's m_can core, which is found
in the new freescale ARM SoCs. Sergei Shtylyov improves the rcar_can
driver by supporting all input clocks and adding device tree support.
The next patch is a small cleanup for the bit rate calculation function
by Lad, Prabhakar. And finally a patch by Himangi Saraogi, which
converts the mcp251x driver to use dmam_alloc_coherent.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 13322f2e 3a73aeff
Bosch MCAN controller Device Tree Bindings
-------------------------------------------------
Required properties:
- compatible : Should be "bosch,m_can" for M_CAN controllers
- reg : physical base address and size of the M_CAN
registers map and Message RAM
- reg-names : Should be "m_can" and "message_ram"
- interrupts : Should be the interrupt number of M_CAN interrupt
line 0 and line 1, could be same if sharing
the same interrupt.
- interrupt-names : Should contain "int0" and "int1"
- clocks : Clocks used by controller, should be host clock
and CAN clock.
- clock-names : Should contain "hclk" and "cclk"
- pinctrl-<n> : Pinctrl states as described in bindings/pinctrl/pinctrl-bindings.txt
- pinctrl-names : Names corresponding to the numbered pinctrl states
- bosch,mram-cfg : Message RAM configuration data.
Multiple M_CAN instances can share the same Message
RAM and each element(e.g Rx FIFO or Tx Buffer and etc)
number in Message RAM is also configurable,
so this property is telling driver how the shared or
private Message RAM are used by this M_CAN controller.
The format should be as follows:
<offset sidf_elems xidf_elems rxf0_elems rxf1_elems
rxb_elems txe_elems txb_elems>
The 'offset' is an address offset of the Message RAM
where the following elements start from. This is
usually set to 0x0 if you're using a private Message
RAM. The remain cells are used to specify how many
elements are used for each FIFO/Buffer.
M_CAN includes the following elements according to user manual:
11-bit Filter 0-128 elements / 0-128 words
29-bit Filter 0-64 elements / 0-128 words
Rx FIFO 0 0-64 elements / 0-1152 words
Rx FIFO 1 0-64 elements / 0-1152 words
Rx Buffers 0-64 elements / 0-1152 words
Tx Event FIFO 0-32 elements / 0-64 words
Tx Buffers 0-32 elements / 0-576 words
Please refer to 2.4.1 Message RAM Configuration in
Bosch M_CAN user manual for details.
Example:
SoC dtsi:
m_can1: can@020e8000 {
compatible = "bosch,m_can";
reg = <0x020e8000 0x4000>, <0x02298000 0x4000>;
reg-names = "m_can", "message_ram";
interrupts = <0 114 0x04>,
<0 114 0x04>;
interrupt-names = "int0", "int1";
clocks = <&clks IMX6SX_CLK_CANFD>,
<&clks IMX6SX_CLK_CANFD>;
clock-names = "hclk", "cclk";
bosch,mram-cfg = <0x0 0 0 32 0 0 0 1>;
status = "disabled";
};
Board dts:
&m_can1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_m_can1>;
status = "enabled";
};
Renesas R-Car CAN controller Device Tree Bindings
-------------------------------------------------
Required properties:
- compatible: "renesas,can-r8a7778" if CAN controller is a part of R8A7778 SoC.
"renesas,can-r8a7779" if CAN controller is a part of R8A7779 SoC.
"renesas,can-r8a7790" if CAN controller is a part of R8A7790 SoC.
"renesas,can-r8a7791" if CAN controller is a part of R8A7791 SoC.
- reg: physical base address and size of the R-Car CAN register map.
- interrupts: interrupt specifier for the sole interrupt.
- clocks: phandles and clock specifiers for 3 CAN clock inputs.
- clock-names: 3 clock input name strings: "clkp1", "clkp2", "can_clk".
- pinctrl-0: pin control group to be used for this controller.
- pinctrl-names: must be "default".
Optional properties:
- renesas,can-clock-select: R-Car CAN Clock Source Select. Valid values are:
<0x0> (default) : Peripheral clock (clkp1)
<0x1> : Peripheral clock (clkp2)
<0x3> : Externally input clock
Example
-------
SoC common .dtsi file:
can0: can@e6e80000 {
compatible = "renesas,can-r8a7791";
reg = <0 0xe6e80000 0 0x1000>;
interrupts = <0 186 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp9_clks R8A7791_CLK_RCAN0>,
<&cpg_clocks R8A7791_CLK_RCAN>, <&can_clk>;
clock-names = "clkp1", "clkp2", "can_clk";
status = "disabled";
};
Board specific .dts file:
&can0 {
pinctrl-0 = <&can0_pins>;
pinctrl-names = "default";
status = "okay";
};
...@@ -143,6 +143,8 @@ source "drivers/net/can/sja1000/Kconfig" ...@@ -143,6 +143,8 @@ source "drivers/net/can/sja1000/Kconfig"
source "drivers/net/can/c_can/Kconfig" source "drivers/net/can/c_can/Kconfig"
source "drivers/net/can/m_can/Kconfig"
source "drivers/net/can/cc770/Kconfig" source "drivers/net/can/cc770/Kconfig"
source "drivers/net/can/spi/Kconfig" source "drivers/net/can/spi/Kconfig"
......
...@@ -17,6 +17,7 @@ obj-y += softing/ ...@@ -17,6 +17,7 @@ obj-y += softing/
obj-$(CONFIG_CAN_SJA1000) += sja1000/ obj-$(CONFIG_CAN_SJA1000) += sja1000/
obj-$(CONFIG_CAN_MSCAN) += mscan/ obj-$(CONFIG_CAN_MSCAN) += mscan/
obj-$(CONFIG_CAN_C_CAN) += c_can/ obj-$(CONFIG_CAN_C_CAN) += c_can/
obj-$(CONFIG_CAN_M_CAN) += m_can/
obj-$(CONFIG_CAN_CC770) += cc770/ obj-$(CONFIG_CAN_CC770) += cc770/
obj-$(CONFIG_CAN_AT91) += at91_can.o obj-$(CONFIG_CAN_AT91) += at91_can.o
obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o
...@@ -28,4 +29,4 @@ obj-$(CONFIG_CAN_GRCAN) += grcan.o ...@@ -28,4 +29,4 @@ obj-$(CONFIG_CAN_GRCAN) += grcan.o
obj-$(CONFIG_CAN_RCAR) += rcar_can.o obj-$(CONFIG_CAN_RCAR) += rcar_can.o
obj-$(CONFIG_CAN_XILINXCAN) += xilinx_can.o obj-$(CONFIG_CAN_XILINXCAN) += xilinx_can.o
ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG subdir-ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
...@@ -5,5 +5,3 @@ ...@@ -5,5 +5,3 @@
obj-$(CONFIG_CAN_C_CAN) += c_can.o obj-$(CONFIG_CAN_C_CAN) += c_can.o
obj-$(CONFIG_CAN_C_CAN_PLATFORM) += c_can_platform.o obj-$(CONFIG_CAN_C_CAN_PLATFORM) += c_can_platform.o
obj-$(CONFIG_CAN_C_CAN_PCI) += c_can_pci.o obj-$(CONFIG_CAN_C_CAN_PCI) += c_can_pci.o
ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
...@@ -5,5 +5,3 @@ ...@@ -5,5 +5,3 @@
obj-$(CONFIG_CAN_CC770) += cc770.o obj-$(CONFIG_CAN_CC770) += cc770.o
obj-$(CONFIG_CAN_CC770_ISA) += cc770_isa.o obj-$(CONFIG_CAN_CC770_ISA) += cc770_isa.o
obj-$(CONFIG_CAN_CC770_PLATFORM) += cc770_platform.o obj-$(CONFIG_CAN_CC770_PLATFORM) += cc770_platform.o
ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
...@@ -103,11 +103,11 @@ static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt, ...@@ -103,11 +103,11 @@ static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
const struct can_bittiming_const *btc) const struct can_bittiming_const *btc)
{ {
struct can_priv *priv = netdev_priv(dev); struct can_priv *priv = netdev_priv(dev);
long rate, best_rate = 0;
long best_error = 1000000000, error = 0; long best_error = 1000000000, error = 0;
int best_tseg = 0, best_brp = 0, brp = 0; int best_tseg = 0, best_brp = 0, brp = 0;
int tsegall, tseg = 0, tseg1 = 0, tseg2 = 0; int tsegall, tseg = 0, tseg1 = 0, tseg2 = 0;
int spt_error = 1000, spt = 0, sampl_pt; int spt_error = 1000, spt = 0, sampl_pt;
long rate;
u64 v64; u64 v64;
/* Use CIA recommended sample points */ /* Use CIA recommended sample points */
...@@ -152,7 +152,6 @@ static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt, ...@@ -152,7 +152,6 @@ static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
} }
best_tseg = tseg / 2; best_tseg = tseg / 2;
best_brp = brp; best_brp = brp;
best_rate = rate;
if (error == 0) if (error == 0)
break; break;
} }
......
...@@ -92,6 +92,27 @@ ...@@ -92,6 +92,27 @@
#define FLEXCAN_CTRL_ERR_ALL \ #define FLEXCAN_CTRL_ERR_ALL \
(FLEXCAN_CTRL_ERR_BUS | FLEXCAN_CTRL_ERR_STATE) (FLEXCAN_CTRL_ERR_BUS | FLEXCAN_CTRL_ERR_STATE)
/* FLEXCAN control register 2 (CTRL2) bits */
#define FLEXCAN_CRL2_ECRWRE BIT(29)
#define FLEXCAN_CRL2_WRMFRZ BIT(28)
#define FLEXCAN_CRL2_RFFN(x) (((x) & 0x0f) << 24)
#define FLEXCAN_CRL2_TASD(x) (((x) & 0x1f) << 19)
#define FLEXCAN_CRL2_MRP BIT(18)
#define FLEXCAN_CRL2_RRS BIT(17)
#define FLEXCAN_CRL2_EACEN BIT(16)
/* FLEXCAN memory error control register (MECR) bits */
#define FLEXCAN_MECR_ECRWRDIS BIT(31)
#define FLEXCAN_MECR_HANCEI_MSK BIT(19)
#define FLEXCAN_MECR_FANCEI_MSK BIT(18)
#define FLEXCAN_MECR_CEI_MSK BIT(16)
#define FLEXCAN_MECR_HAERRIE BIT(15)
#define FLEXCAN_MECR_FAERRIE BIT(14)
#define FLEXCAN_MECR_EXTERRIE BIT(13)
#define FLEXCAN_MECR_RERRDIS BIT(9)
#define FLEXCAN_MECR_ECCDIS BIT(8)
#define FLEXCAN_MECR_NCEFAFRZ BIT(7)
/* FLEXCAN error and status register (ESR) bits */ /* FLEXCAN error and status register (ESR) bits */
#define FLEXCAN_ESR_TWRN_INT BIT(17) #define FLEXCAN_ESR_TWRN_INT BIT(17)
#define FLEXCAN_ESR_RWRN_INT BIT(16) #define FLEXCAN_ESR_RWRN_INT BIT(16)
...@@ -150,18 +171,20 @@ ...@@ -150,18 +171,20 @@
* FLEXCAN hardware feature flags * FLEXCAN hardware feature flags
* *
* Below is some version info we got: * Below is some version info we got:
* SOC Version IP-Version Glitch- [TR]WRN_INT * SOC Version IP-Version Glitch- [TR]WRN_INT Memory err
* Filter? connected? * Filter? connected? detection
* MX25 FlexCAN2 03.00.00.00 no no * MX25 FlexCAN2 03.00.00.00 no no no
* MX28 FlexCAN2 03.00.04.00 yes yes * MX28 FlexCAN2 03.00.04.00 yes yes no
* MX35 FlexCAN2 03.00.00.00 no no * MX35 FlexCAN2 03.00.00.00 no no no
* MX53 FlexCAN2 03.00.00.00 yes no * MX53 FlexCAN2 03.00.00.00 yes no no
* MX6s FlexCAN3 10.00.12.00 yes yes * MX6s FlexCAN3 10.00.12.00 yes yes no
* VF610 FlexCAN3 ? no yes yes
* *
* Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected. * Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected.
*/ */
#define FLEXCAN_HAS_V10_FEATURES BIT(1) /* For core version >= 10 */ #define FLEXCAN_HAS_V10_FEATURES BIT(1) /* For core version >= 10 */
#define FLEXCAN_HAS_BROKEN_ERR_STATE BIT(2) /* [TR]WRN_INT not connected */ #define FLEXCAN_HAS_BROKEN_ERR_STATE BIT(2) /* [TR]WRN_INT not connected */
#define FLEXCAN_HAS_MECR_FEATURES BIT(3) /* Memory error detection */
/* Structure of the message buffer */ /* Structure of the message buffer */
struct flexcan_mb { struct flexcan_mb {
...@@ -192,8 +215,17 @@ struct flexcan_regs { ...@@ -192,8 +215,17 @@ struct flexcan_regs {
u32 crcr; /* 0x44 */ u32 crcr; /* 0x44 */
u32 rxfgmask; /* 0x48 */ u32 rxfgmask; /* 0x48 */
u32 rxfir; /* 0x4c */ u32 rxfir; /* 0x4c */
u32 _reserved3[12]; u32 _reserved3[12]; /* 0x50 */
struct flexcan_mb cantxfg[64]; struct flexcan_mb cantxfg[64]; /* 0x80 */
u32 _reserved4[408];
u32 mecr; /* 0xae0 */
u32 erriar; /* 0xae4 */
u32 erridpr; /* 0xae8 */
u32 errippr; /* 0xaec */
u32 rerrar; /* 0xaf0 */
u32 rerrdr; /* 0xaf4 */
u32 rerrsynr; /* 0xaf8 */
u32 errsr; /* 0xafc */
}; };
struct flexcan_devtype_data { struct flexcan_devtype_data {
...@@ -223,6 +255,9 @@ static struct flexcan_devtype_data fsl_imx28_devtype_data; ...@@ -223,6 +255,9 @@ static struct flexcan_devtype_data fsl_imx28_devtype_data;
static struct flexcan_devtype_data fsl_imx6q_devtype_data = { static struct flexcan_devtype_data fsl_imx6q_devtype_data = {
.features = FLEXCAN_HAS_V10_FEATURES, .features = FLEXCAN_HAS_V10_FEATURES,
}; };
static struct flexcan_devtype_data fsl_vf610_devtype_data = {
.features = FLEXCAN_HAS_V10_FEATURES | FLEXCAN_HAS_MECR_FEATURES,
};
static const struct can_bittiming_const flexcan_bittiming_const = { static const struct can_bittiming_const flexcan_bittiming_const = {
.name = DRV_NAME, .name = DRV_NAME,
...@@ -378,8 +413,9 @@ static int flexcan_chip_softreset(struct flexcan_priv *priv) ...@@ -378,8 +413,9 @@ static int flexcan_chip_softreset(struct flexcan_priv *priv)
return 0; return 0;
} }
static int flexcan_get_berr_counter(const struct net_device *dev,
struct can_berr_counter *bec) static int __flexcan_get_berr_counter(const struct net_device *dev,
struct can_berr_counter *bec)
{ {
const struct flexcan_priv *priv = netdev_priv(dev); const struct flexcan_priv *priv = netdev_priv(dev);
struct flexcan_regs __iomem *regs = priv->base; struct flexcan_regs __iomem *regs = priv->base;
...@@ -391,6 +427,29 @@ static int flexcan_get_berr_counter(const struct net_device *dev, ...@@ -391,6 +427,29 @@ static int flexcan_get_berr_counter(const struct net_device *dev,
return 0; return 0;
} }
static int flexcan_get_berr_counter(const struct net_device *dev,
struct can_berr_counter *bec)
{
const struct flexcan_priv *priv = netdev_priv(dev);
int err;
err = clk_prepare_enable(priv->clk_ipg);
if (err)
return err;
err = clk_prepare_enable(priv->clk_per);
if (err)
goto out_disable_ipg;
err = __flexcan_get_berr_counter(dev, bec);
clk_disable_unprepare(priv->clk_per);
out_disable_ipg:
clk_disable_unprepare(priv->clk_ipg);
return err;
}
static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev) static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
{ {
const struct flexcan_priv *priv = netdev_priv(dev); const struct flexcan_priv *priv = netdev_priv(dev);
...@@ -503,7 +562,7 @@ static void do_state(struct net_device *dev, ...@@ -503,7 +562,7 @@ static void do_state(struct net_device *dev,
struct flexcan_priv *priv = netdev_priv(dev); struct flexcan_priv *priv = netdev_priv(dev);
struct can_berr_counter bec; struct can_berr_counter bec;
flexcan_get_berr_counter(dev, &bec); __flexcan_get_berr_counter(dev, &bec);
switch (priv->can.state) { switch (priv->can.state) {
case CAN_STATE_ERROR_ACTIVE: case CAN_STATE_ERROR_ACTIVE:
...@@ -793,7 +852,7 @@ static int flexcan_chip_start(struct net_device *dev) ...@@ -793,7 +852,7 @@ static int flexcan_chip_start(struct net_device *dev)
struct flexcan_priv *priv = netdev_priv(dev); struct flexcan_priv *priv = netdev_priv(dev);
struct flexcan_regs __iomem *regs = priv->base; struct flexcan_regs __iomem *regs = priv->base;
int err; int err;
u32 reg_mcr, reg_ctrl; u32 reg_mcr, reg_ctrl, reg_crl2, reg_mecr;
/* enable module */ /* enable module */
err = flexcan_chip_enable(priv); err = flexcan_chip_enable(priv);
...@@ -870,6 +929,31 @@ static int flexcan_chip_start(struct net_device *dev) ...@@ -870,6 +929,31 @@ static int flexcan_chip_start(struct net_device *dev)
if (priv->devtype_data->features & FLEXCAN_HAS_V10_FEATURES) if (priv->devtype_data->features & FLEXCAN_HAS_V10_FEATURES)
flexcan_write(0x0, &regs->rxfgmask); flexcan_write(0x0, &regs->rxfgmask);
/*
* On Vybrid, disable memory error detection interrupts
* and freeze mode.
* This also works around errata e5295 which generates
* false positive memory errors and put the device in
* freeze mode.
*/
if (priv->devtype_data->features & FLEXCAN_HAS_MECR_FEATURES) {
/*
* Follow the protocol as described in "Detection
* and Correction of Memory Errors" to write to
* MECR register
*/
reg_crl2 = flexcan_read(&regs->crl2);
reg_crl2 |= FLEXCAN_CRL2_ECRWRE;
flexcan_write(reg_crl2, &regs->crl2);
reg_mecr = flexcan_read(&regs->mecr);
reg_mecr &= ~FLEXCAN_MECR_ECRWRDIS;
flexcan_write(reg_mecr, &regs->mecr);
reg_mecr &= ~(FLEXCAN_MECR_NCEFAFRZ | FLEXCAN_MECR_HANCEI_MSK |
FLEXCAN_MECR_FANCEI_MSK);
flexcan_write(reg_mecr, &regs->mecr);
}
err = flexcan_transceiver_enable(priv); err = flexcan_transceiver_enable(priv);
if (err) if (err)
goto out_chip_disable; goto out_chip_disable;
...@@ -1080,6 +1164,7 @@ static const struct of_device_id flexcan_of_match[] = { ...@@ -1080,6 +1164,7 @@ static const struct of_device_id flexcan_of_match[] = {
{ .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, }, { .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, },
{ .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, }, { .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, },
{ .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, }, { .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, },
{ .compatible = "fsl,vf610-flexcan", .data = &fsl_vf610_devtype_data, },
{ /* sentinel */ }, { /* sentinel */ },
}; };
MODULE_DEVICE_TABLE(of, flexcan_of_match); MODULE_DEVICE_TABLE(of, flexcan_of_match);
......
config CAN_M_CAN
tristate "Bosch M_CAN devices"
---help---
Say Y here if you want to support for Bosch M_CAN controller.
#
# Makefile for the Bosch M_CAN controller driver.
#
obj-$(CONFIG_CAN_M_CAN) += m_can.o
/*
* CAN bus driver for Bosch M_CAN controller
*
* Copyright (C) 2014 Freescale Semiconductor, Inc.
* Dong Aisheng <b29396@freescale.com>
*
* Bosch M_CAN user manual can be obtained from:
* http://www.bosch-semiconductors.de/media/pdf_1/ipmodules_1/m_can/
* mcan_users_manual_v302.pdf
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#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/platform_device.h>
#include <linux/can/dev.h>
/* napi related */
#define M_CAN_NAPI_WEIGHT 64
/* message ram configuration data length */
#define MRAM_CFG_LEN 8
/* registers definition */
enum m_can_reg {
M_CAN_CREL = 0x0,
M_CAN_ENDN = 0x4,
M_CAN_CUST = 0x8,
M_CAN_FBTP = 0xc,
M_CAN_TEST = 0x10,
M_CAN_RWD = 0x14,
M_CAN_CCCR = 0x18,
M_CAN_BTP = 0x1c,
M_CAN_TSCC = 0x20,
M_CAN_TSCV = 0x24,
M_CAN_TOCC = 0x28,
M_CAN_TOCV = 0x2c,
M_CAN_ECR = 0x40,
M_CAN_PSR = 0x44,
M_CAN_IR = 0x50,
M_CAN_IE = 0x54,
M_CAN_ILS = 0x58,
M_CAN_ILE = 0x5c,
M_CAN_GFC = 0x80,
M_CAN_SIDFC = 0x84,
M_CAN_XIDFC = 0x88,
M_CAN_XIDAM = 0x90,
M_CAN_HPMS = 0x94,
M_CAN_NDAT1 = 0x98,
M_CAN_NDAT2 = 0x9c,
M_CAN_RXF0C = 0xa0,
M_CAN_RXF0S = 0xa4,
M_CAN_RXF0A = 0xa8,
M_CAN_RXBC = 0xac,
M_CAN_RXF1C = 0xb0,
M_CAN_RXF1S = 0xb4,
M_CAN_RXF1A = 0xb8,
M_CAN_RXESC = 0xbc,
M_CAN_TXBC = 0xc0,
M_CAN_TXFQS = 0xc4,
M_CAN_TXESC = 0xc8,
M_CAN_TXBRP = 0xcc,
M_CAN_TXBAR = 0xd0,
M_CAN_TXBCR = 0xd4,
M_CAN_TXBTO = 0xd8,
M_CAN_TXBCF = 0xdc,
M_CAN_TXBTIE = 0xe0,
M_CAN_TXBCIE = 0xe4,
M_CAN_TXEFC = 0xf0,
M_CAN_TXEFS = 0xf4,
M_CAN_TXEFA = 0xf8,
};
/* 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,
};
/* Test Register (TEST) */
#define TEST_LBCK BIT(4)
/* CC Control Register(CCCR) */
#define CCCR_TEST BIT(7)
#define CCCR_MON BIT(5)
#define CCCR_CCE BIT(1)
#define CCCR_INIT BIT(0)
/* Bit Timing & Prescaler Register (BTP) */
#define BTR_BRP_MASK 0x3ff
#define BTR_BRP_SHIFT 16
#define BTR_TSEG1_SHIFT 8
#define BTR_TSEG1_MASK (0x3f << BTR_TSEG1_SHIFT)
#define BTR_TSEG2_SHIFT 4
#define BTR_TSEG2_MASK (0xf << BTR_TSEG2_SHIFT)
#define BTR_SJW_SHIFT 0
#define BTR_SJW_MASK 0xf
/* Error Counter Register(ECR) */
#define ECR_RP BIT(15)
#define ECR_REC_SHIFT 8
#define ECR_REC_MASK (0x7f << ECR_REC_SHIFT)
#define ECR_TEC_SHIFT 0
#define ECR_TEC_MASK 0xff
/* Protocol Status Register(PSR) */
#define PSR_BO BIT(7)
#define PSR_EW BIT(6)
#define PSR_EP BIT(5)
#define PSR_LEC_MASK 0x7
/* Interrupt Register(IR) */
#define IR_ALL_INT 0xffffffff
#define IR_STE BIT(31)
#define IR_FOE BIT(30)
#define IR_ACKE BIT(29)
#define IR_BE BIT(28)
#define IR_CRCE BIT(27)
#define IR_WDI BIT(26)
#define IR_BO BIT(25)
#define IR_EW BIT(24)
#define IR_EP BIT(23)
#define IR_ELO BIT(22)
#define IR_BEU BIT(21)
#define IR_BEC BIT(20)
#define IR_DRX BIT(19)
#define IR_TOO BIT(18)
#define IR_MRAF BIT(17)
#define IR_TSW BIT(16)
#define IR_TEFL BIT(15)
#define IR_TEFF BIT(14)
#define IR_TEFW BIT(13)
#define IR_TEFN BIT(12)
#define IR_TFE BIT(11)
#define IR_TCF BIT(10)
#define IR_TC BIT(9)
#define IR_HPM BIT(8)
#define IR_RF1L BIT(7)
#define IR_RF1F BIT(6)
#define IR_RF1W BIT(5)
#define IR_RF1N BIT(4)
#define IR_RF0L BIT(3)
#define IR_RF0F BIT(2)
#define IR_RF0W BIT(1)
#define IR_RF0N BIT(0)
#define IR_ERR_STATE (IR_BO | IR_EW | IR_EP)
#define IR_ERR_LEC (IR_STE | IR_FOE | IR_ACKE | IR_BE | IR_CRCE)
#define IR_ERR_BUS (IR_ERR_LEC | IR_WDI | IR_ELO | IR_BEU | \
IR_BEC | IR_TOO | IR_MRAF | IR_TSW | IR_TEFL | \
IR_RF1L | IR_RF0L)
#define IR_ERR_ALL (IR_ERR_STATE | IR_ERR_BUS)
/* Interrupt Line Select (ILS) */
#define ILS_ALL_INT0 0x0
#define ILS_ALL_INT1 0xFFFFFFFF
/* Interrupt Line Enable (ILE) */
#define ILE_EINT0 BIT(0)
#define ILE_EINT1 BIT(1)
/* Rx FIFO 0/1 Configuration (RXF0C/RXF1C) */
#define RXFC_FWM_OFF 24
#define RXFC_FWM_MASK 0x7f
#define RXFC_FWM_1 (1 << RXFC_FWM_OFF)
#define RXFC_FS_OFF 16
#define RXFC_FS_MASK 0x7f
/* Rx FIFO 0/1 Status (RXF0S/RXF1S) */
#define RXFS_RFL BIT(25)
#define RXFS_FF BIT(24)
#define RXFS_FPI_OFF 16
#define RXFS_FPI_MASK 0x3f0000
#define RXFS_FGI_OFF 8
#define RXFS_FGI_MASK 0x3f00
#define RXFS_FFL_MASK 0x7f
/* Rx Buffer / FIFO Element Size Configuration (RXESC) */
#define M_CAN_RXESC_8BYTES 0x0
/* Tx Buffer Configuration(TXBC) */
#define TXBC_NDTB_OFF 16
#define TXBC_NDTB_MASK 0x3f
/* Tx Buffer Element Size Configuration(TXESC) */
#define TXESC_TBDS_8BYTES 0x0
/* Tx Event FIFO Con.guration (TXEFC) */
#define TXEFC_EFS_OFF 16
#define TXEFC_EFS_MASK 0x3f
/* Message RAM Configuration (in bytes) */
#define SIDF_ELEMENT_SIZE 4
#define XIDF_ELEMENT_SIZE 8
#define RXF0_ELEMENT_SIZE 16
#define RXF1_ELEMENT_SIZE 16
#define RXB_ELEMENT_SIZE 16
#define TXE_ELEMENT_SIZE 8
#define TXB_ELEMENT_SIZE 16
/* Message RAM Elements */
#define M_CAN_FIFO_ID 0x0
#define M_CAN_FIFO_DLC 0x4
#define M_CAN_FIFO_DATA(n) (0x8 + ((n) << 2))
/* Rx Buffer Element */
#define RX_BUF_ESI BIT(31)
#define RX_BUF_XTD BIT(30)
#define RX_BUF_RTR BIT(29)
/* Tx Buffer Element */
#define TX_BUF_XTD BIT(30)
#define TX_BUF_RTR BIT(29)
/* address offset and element number for each FIFO/Buffer in the Message RAM */
struct mram_cfg {
u16 off;
u8 num;
};
/* m_can private data structure */
struct m_can_priv {
struct can_priv can; /* must be the first member */
struct napi_struct napi;
struct net_device *dev;
struct device *device;
struct clk *hclk;
struct clk *cclk;
void __iomem *base;
u32 irqstatus;
/* message ram configuration */
void __iomem *mram_base;
struct mram_cfg mcfg[MRAM_CFG_NUM];
};
static inline u32 m_can_read(const struct m_can_priv *priv, enum m_can_reg reg)
{
return readl(priv->base + reg);
}
static inline void m_can_write(const struct m_can_priv *priv,
enum m_can_reg reg, u32 val)
{
writel(val, priv->base + reg);
}
static inline u32 m_can_fifo_read(const struct m_can_priv *priv,
u32 fgi, unsigned int offset)
{
return readl(priv->mram_base + priv->mcfg[MRAM_RXF0].off +
fgi * RXF0_ELEMENT_SIZE + offset);
}
static inline void m_can_fifo_write(const struct m_can_priv *priv,
u32 fpi, unsigned int offset, u32 val)
{
return writel(val, priv->mram_base + priv->mcfg[MRAM_TXB].off +
fpi * TXB_ELEMENT_SIZE + offset);
}
static inline void m_can_config_endisable(const struct m_can_priv *priv,
bool enable)
{
u32 cccr = m_can_read(priv, M_CAN_CCCR);
u32 timeout = 10;
u32 val = 0;
if (enable) {
/* enable m_can configuration */
m_can_write(priv, M_CAN_CCCR, cccr | CCCR_INIT);
/* CCCR.CCE can only be set/reset while CCCR.INIT = '1' */
m_can_write(priv, M_CAN_CCCR, cccr | CCCR_INIT | CCCR_CCE);
} else {
m_can_write(priv, M_CAN_CCCR, cccr & ~(CCCR_INIT | CCCR_CCE));
}
/* there's a delay for module initialization */
if (enable)
val = CCCR_INIT | CCCR_CCE;
while ((m_can_read(priv, M_CAN_CCCR) & (CCCR_INIT | CCCR_CCE)) != val) {
if (timeout == 0) {
netdev_warn(priv->dev, "Failed to init module\n");
return;
}
timeout--;
udelay(1);
}
}
static inline void m_can_enable_all_interrupts(const struct m_can_priv *priv)
{
m_can_write(priv, M_CAN_ILE, ILE_EINT0 | ILE_EINT1);
}
static inline void m_can_disable_all_interrupts(const struct m_can_priv *priv)
{
m_can_write(priv, M_CAN_ILE, 0x0);
}
static void m_can_read_fifo(const struct net_device *dev, struct can_frame *cf,
u32 rxfs)
{
struct m_can_priv *priv = netdev_priv(dev);
u32 id, fgi;
/* calculate the fifo get index for where to read data */
fgi = (rxfs & RXFS_FGI_MASK) >> RXFS_FGI_OFF;
id = m_can_fifo_read(priv, fgi, M_CAN_FIFO_ID);
if (id & RX_BUF_XTD)
cf->can_id = (id & CAN_EFF_MASK) | CAN_EFF_FLAG;
else
cf->can_id = (id >> 18) & CAN_SFF_MASK;
if (id & RX_BUF_RTR) {
cf->can_id |= CAN_RTR_FLAG;
} else {
id = m_can_fifo_read(priv, fgi, M_CAN_FIFO_DLC);
cf->can_dlc = get_can_dlc((id >> 16) & 0x0F);
*(u32 *)(cf->data + 0) = m_can_fifo_read(priv, fgi,
M_CAN_FIFO_DATA(0));
*(u32 *)(cf->data + 4) = m_can_fifo_read(priv, fgi,
M_CAN_FIFO_DATA(1));
}
/* acknowledge rx fifo 0 */
m_can_write(priv, M_CAN_RXF0A, fgi);
}
static int m_can_do_rx_poll(struct net_device *dev, int quota)
{
struct m_can_priv *priv = netdev_priv(dev);
struct net_device_stats *stats = &dev->stats;
struct sk_buff *skb;
struct can_frame *frame;
u32 pkts = 0;
u32 rxfs;
rxfs = m_can_read(priv, M_CAN_RXF0S);
if (!(rxfs & RXFS_FFL_MASK)) {
netdev_dbg(dev, "no messages in fifo0\n");
return 0;
}
while ((rxfs & RXFS_FFL_MASK) && (quota > 0)) {
if (rxfs & RXFS_RFL)
netdev_warn(dev, "Rx FIFO 0 Message Lost\n");
skb = alloc_can_skb(dev, &frame);
if (!skb) {
stats->rx_dropped++;
return pkts;
}
m_can_read_fifo(dev, frame, rxfs);
stats->rx_packets++;
stats->rx_bytes += frame->can_dlc;
netif_receive_skb(skb);
quota--;
pkts++;
rxfs = m_can_read(priv, M_CAN_RXF0S);
}
if (pkts)
can_led_event(dev, CAN_LED_EVENT_RX);
return pkts;
}
static int m_can_handle_lost_msg(struct net_device *dev)
{
struct net_device_stats *stats = &dev->stats;
struct sk_buff *skb;
struct can_frame *frame;
netdev_err(dev, "msg lost in rxf0\n");
stats->rx_errors++;
stats->rx_over_errors++;
skb = alloc_can_err_skb(dev, &frame);
if (unlikely(!skb))
return 0;
frame->can_id |= CAN_ERR_CRTL;
frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
netif_receive_skb(skb);
return 1;
}
static int m_can_handle_lec_err(struct net_device *dev,
enum m_can_lec_type lec_type)
{
struct m_can_priv *priv = netdev_priv(dev);
struct net_device_stats *stats = &dev->stats;
struct can_frame *cf;
struct sk_buff *skb;
priv->can.can_stats.bus_error++;
stats->rx_errors++;
/* propagate the error condition to the CAN stack */
skb = alloc_can_err_skb(dev, &cf);
if (unlikely(!skb))
return 0;
/* check for 'last error code' which tells us the
* type of the last error to occur on the CAN bus
*/
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
cf->data[2] |= CAN_ERR_PROT_UNSPEC;
switch (lec_type) {
case LEC_STUFF_ERROR:
netdev_dbg(dev, "stuff error\n");
cf->data[2] |= CAN_ERR_PROT_STUFF;
break;
case LEC_FORM_ERROR:
netdev_dbg(dev, "form error\n");
cf->data[2] |= CAN_ERR_PROT_FORM;
break;
case LEC_ACK_ERROR:
netdev_dbg(dev, "ack error\n");
cf->data[3] |= (CAN_ERR_PROT_LOC_ACK |
CAN_ERR_PROT_LOC_ACK_DEL);
break;
case LEC_BIT1_ERROR:
netdev_dbg(dev, "bit1 error\n");
cf->data[2] |= CAN_ERR_PROT_BIT1;
break;
case LEC_BIT0_ERROR:
netdev_dbg(dev, "bit0 error\n");
cf->data[2] |= CAN_ERR_PROT_BIT0;
break;
case LEC_CRC_ERROR:
netdev_dbg(dev, "CRC error\n");
cf->data[3] |= (CAN_ERR_PROT_LOC_CRC_SEQ |
CAN_ERR_PROT_LOC_CRC_DEL);
break;
default:
break;
}
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
netif_receive_skb(skb);
return 1;
}
static int m_can_get_berr_counter(const struct net_device *dev,
struct can_berr_counter *bec)
{
struct m_can_priv *priv = netdev_priv(dev);
unsigned int ecr;
int err;
err = clk_prepare_enable(priv->hclk);
if (err)
return err;
err = clk_prepare_enable(priv->cclk);
if (err) {
clk_disable_unprepare(priv->hclk);
return err;
}
ecr = m_can_read(priv, M_CAN_ECR);
bec->rxerr = (ecr & ECR_REC_MASK) >> ECR_REC_SHIFT;
bec->txerr = ecr & ECR_TEC_MASK;
clk_disable_unprepare(priv->cclk);
clk_disable_unprepare(priv->hclk);
return 0;
}
static int m_can_handle_state_change(struct net_device *dev,
enum can_state new_state)
{
struct m_can_priv *priv = netdev_priv(dev);
struct net_device_stats *stats = &dev->stats;
struct can_frame *cf;
struct sk_buff *skb;
struct can_berr_counter bec;
unsigned int ecr;
switch (new_state) {
case CAN_STATE_ERROR_ACTIVE:
/* error warning state */
priv->can.can_stats.error_warning++;
priv->can.state = CAN_STATE_ERROR_WARNING;
break;
case CAN_STATE_ERROR_PASSIVE:
/* error passive state */
priv->can.can_stats.error_passive++;
priv->can.state = CAN_STATE_ERROR_PASSIVE;
break;
case CAN_STATE_BUS_OFF:
/* bus-off state */
priv->can.state = CAN_STATE_BUS_OFF;
m_can_disable_all_interrupts(priv);
can_bus_off(dev);
break;
default:
break;
}
/* propagate the error condition to the CAN stack */
skb = alloc_can_err_skb(dev, &cf);
if (unlikely(!skb))
return 0;
m_can_get_berr_counter(dev, &bec);
switch (new_state) {
case CAN_STATE_ERROR_ACTIVE:
/* error warning state */
cf->can_id |= CAN_ERR_CRTL;
cf->data[1] = (bec.txerr > bec.rxerr) ?
CAN_ERR_CRTL_TX_WARNING :
CAN_ERR_CRTL_RX_WARNING;
cf->data[6] = bec.txerr;
cf->data[7] = bec.rxerr;
break;
case CAN_STATE_ERROR_PASSIVE:
/* error passive state */
cf->can_id |= CAN_ERR_CRTL;
ecr = m_can_read(priv, M_CAN_ECR);
if (ecr & ECR_RP)
cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
if (bec.txerr > 127)
cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE;
cf->data[6] = bec.txerr;
cf->data[7] = bec.rxerr;
break;
case CAN_STATE_BUS_OFF:
/* bus-off state */
cf->can_id |= CAN_ERR_BUSOFF;
break;
default:
break;
}
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
netif_receive_skb(skb);
return 1;
}
static int m_can_handle_state_errors(struct net_device *dev, u32 psr)
{
struct m_can_priv *priv = netdev_priv(dev);
int work_done = 0;
if ((psr & PSR_EW) &&
(priv->can.state != CAN_STATE_ERROR_WARNING)) {
netdev_dbg(dev, "entered error warning state\n");
work_done += m_can_handle_state_change(dev,
CAN_STATE_ERROR_WARNING);
}
if ((psr & PSR_EP) &&
(priv->can.state != CAN_STATE_ERROR_PASSIVE)) {
netdev_dbg(dev, "entered error warning state\n");
work_done += m_can_handle_state_change(dev,
CAN_STATE_ERROR_PASSIVE);
}
if ((psr & PSR_BO) &&
(priv->can.state != CAN_STATE_BUS_OFF)) {
netdev_dbg(dev, "entered error warning state\n");
work_done += m_can_handle_state_change(dev,
CAN_STATE_BUS_OFF);
}
return work_done;
}
static void m_can_handle_other_err(struct net_device *dev, u32 irqstatus)
{
if (irqstatus & IR_WDI)
netdev_err(dev, "Message RAM Watchdog event due to missing READY\n");
if (irqstatus & IR_BEU)
netdev_err(dev, "Error Logging Overflow\n");
if (irqstatus & IR_BEU)
netdev_err(dev, "Bit Error Uncorrected\n");
if (irqstatus & IR_BEC)
netdev_err(dev, "Bit Error Corrected\n");
if (irqstatus & IR_TOO)
netdev_err(dev, "Timeout reached\n");
if (irqstatus & IR_MRAF)
netdev_err(dev, "Message RAM access failure occurred\n");
}
static inline bool is_lec_err(u32 psr)
{
psr &= LEC_UNUSED;
return psr && (psr != LEC_UNUSED);
}
static int m_can_handle_bus_errors(struct net_device *dev, u32 irqstatus,
u32 psr)
{
struct m_can_priv *priv = netdev_priv(dev);
int work_done = 0;
if (irqstatus & IR_RF0L)
work_done += m_can_handle_lost_msg(dev);
/* handle lec errors on the bus */
if ((priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) &&
is_lec_err(psr))
work_done += m_can_handle_lec_err(dev, psr & LEC_UNUSED);
/* other unproccessed error interrupts */
m_can_handle_other_err(dev, irqstatus);
return work_done;
}
static int m_can_poll(struct napi_struct *napi, int quota)
{
struct net_device *dev = napi->dev;
struct m_can_priv *priv = netdev_priv(dev);
int work_done = 0;
u32 irqstatus, psr;
irqstatus = priv->irqstatus | m_can_read(priv, M_CAN_IR);
if (!irqstatus)
goto end;
psr = m_can_read(priv, M_CAN_PSR);
if (irqstatus & IR_ERR_STATE)
work_done += m_can_handle_state_errors(dev, psr);
if (irqstatus & IR_ERR_BUS)
work_done += m_can_handle_bus_errors(dev, irqstatus, psr);
if (irqstatus & IR_RF0N)
work_done += m_can_do_rx_poll(dev, (quota - work_done));
if (work_done < quota) {
napi_complete(napi);
m_can_enable_all_interrupts(priv);
}
end:
return work_done;
}
static irqreturn_t m_can_isr(int irq, void *dev_id)
{
struct net_device *dev = (struct net_device *)dev_id;
struct m_can_priv *priv = netdev_priv(dev);
struct net_device_stats *stats = &dev->stats;
u32 ir;
ir = m_can_read(priv, M_CAN_IR);
if (!ir)
return IRQ_NONE;
/* ACK all irqs */
if (ir & IR_ALL_INT)
m_can_write(priv, M_CAN_IR, ir);
/* schedule NAPI in case of
* - rx IRQ
* - state change IRQ
* - bus error IRQ and bus error reporting
*/
if ((ir & IR_RF0N) || (ir & IR_ERR_ALL)) {
priv->irqstatus = ir;
m_can_disable_all_interrupts(priv);
napi_schedule(&priv->napi);
}
/* transmission complete interrupt */
if (ir & IR_TC) {
stats->tx_bytes += can_get_echo_skb(dev, 0);
stats->tx_packets++;
can_led_event(dev, CAN_LED_EVENT_TX);
netif_wake_queue(dev);
}
return IRQ_HANDLED;
}
static const struct can_bittiming_const m_can_bittiming_const = {
.name = KBUILD_MODNAME,
.tseg1_min = 2, /* Time segment 1 = prop_seg + phase_seg1 */
.tseg1_max = 64,
.tseg2_min = 1, /* Time segment 2 = phase_seg2 */
.tseg2_max = 16,
.sjw_max = 16,
.brp_min = 1,
.brp_max = 1024,
.brp_inc = 1,
};
static int m_can_set_bittiming(struct net_device *dev)
{
struct m_can_priv *priv = netdev_priv(dev);
const struct can_bittiming *bt = &priv->can.bittiming;
u16 brp, sjw, tseg1, tseg2;
u32 reg_btp;
brp = bt->brp - 1;
sjw = bt->sjw - 1;
tseg1 = bt->prop_seg + bt->phase_seg1 - 1;
tseg2 = bt->phase_seg2 - 1;
reg_btp = (brp << BTR_BRP_SHIFT) | (sjw << BTR_SJW_SHIFT) |
(tseg1 << BTR_TSEG1_SHIFT) | (tseg2 << BTR_TSEG2_SHIFT);
m_can_write(priv, M_CAN_BTP, reg_btp);
netdev_dbg(dev, "setting BTP 0x%x\n", reg_btp);
return 0;
}
/* Configure M_CAN chip:
* - set rx buffer/fifo element size
* - configure rx fifo
* - accept non-matching frame into fifo 0
* - configure tx buffer
* - configure mode
* - setup bittiming
*/
static void m_can_chip_config(struct net_device *dev)
{
struct m_can_priv *priv = netdev_priv(dev);
u32 cccr, test;
m_can_config_endisable(priv, true);
/* RX Buffer/FIFO Element Size 8 bytes data field */
m_can_write(priv, M_CAN_RXESC, M_CAN_RXESC_8BYTES);
/* Accept Non-matching Frames Into FIFO 0 */
m_can_write(priv, M_CAN_GFC, 0x0);
/* only support one Tx Buffer currently */
m_can_write(priv, M_CAN_TXBC, (1 << TXBC_NDTB_OFF) |
priv->mcfg[MRAM_TXB].off);
/* only support 8 bytes firstly */
m_can_write(priv, M_CAN_TXESC, TXESC_TBDS_8BYTES);
m_can_write(priv, M_CAN_TXEFC, (1 << TXEFC_EFS_OFF) |
priv->mcfg[MRAM_TXE].off);
/* rx fifo configuration, blocking mode, fifo size 1 */
m_can_write(priv, M_CAN_RXF0C,
(priv->mcfg[MRAM_RXF0].num << RXFC_FS_OFF) |
RXFC_FWM_1 | priv->mcfg[MRAM_RXF0].off);
m_can_write(priv, M_CAN_RXF1C,
(priv->mcfg[MRAM_RXF1].num << RXFC_FS_OFF) |
RXFC_FWM_1 | priv->mcfg[MRAM_RXF1].off);
cccr = m_can_read(priv, M_CAN_CCCR);
cccr &= ~(CCCR_TEST | CCCR_MON);
test = m_can_read(priv, M_CAN_TEST);
test &= ~TEST_LBCK;
if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
cccr |= CCCR_MON;
if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
cccr |= CCCR_TEST;
test |= TEST_LBCK;
}
m_can_write(priv, M_CAN_CCCR, cccr);
m_can_write(priv, M_CAN_TEST, test);
/* enable interrupts */
m_can_write(priv, M_CAN_IR, IR_ALL_INT);
if (!(priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING))
m_can_write(priv, M_CAN_IE, IR_ALL_INT & ~IR_ERR_LEC);
else
m_can_write(priv, M_CAN_IE, IR_ALL_INT);
/* route all interrupts to INT0 */
m_can_write(priv, M_CAN_ILS, ILS_ALL_INT0);
/* set bittiming params */
m_can_set_bittiming(dev);
m_can_config_endisable(priv, false);
}
static void m_can_start(struct net_device *dev)
{
struct m_can_priv *priv = netdev_priv(dev);
/* basic m_can configuration */
m_can_chip_config(dev);
priv->can.state = CAN_STATE_ERROR_ACTIVE;
m_can_enable_all_interrupts(priv);
}
static int m_can_set_mode(struct net_device *dev, enum can_mode mode)
{
switch (mode) {
case CAN_MODE_START:
m_can_start(dev);
netif_wake_queue(dev);
break;
default:
return -EOPNOTSUPP;
}
return 0;
}
static void free_m_can_dev(struct net_device *dev)
{
free_candev(dev);
}
static struct net_device *alloc_m_can_dev(void)
{
struct net_device *dev;
struct m_can_priv *priv;
dev = alloc_candev(sizeof(*priv), 1);
if (!dev)
return NULL;
priv = netdev_priv(dev);
netif_napi_add(dev, &priv->napi, m_can_poll, M_CAN_NAPI_WEIGHT);
priv->dev = dev;
priv->can.bittiming_const = &m_can_bittiming_const;
priv->can.do_set_mode = m_can_set_mode;
priv->can.do_get_berr_counter = m_can_get_berr_counter;
priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
CAN_CTRLMODE_LISTENONLY |
CAN_CTRLMODE_BERR_REPORTING;
return dev;
}
static int m_can_open(struct net_device *dev)
{
struct m_can_priv *priv = netdev_priv(dev);
int err;
err = clk_prepare_enable(priv->hclk);
if (err)
return err;
err = clk_prepare_enable(priv->cclk);
if (err)
goto exit_disable_hclk;
/* open the can device */
err = open_candev(dev);
if (err) {
netdev_err(dev, "failed to open can device\n");
goto exit_disable_cclk;
}
/* register interrupt handler */
err = request_irq(dev->irq, m_can_isr, IRQF_SHARED, dev->name,
dev);
if (err < 0) {
netdev_err(dev, "failed to request interrupt\n");
goto exit_irq_fail;
}
/* start the m_can controller */
m_can_start(dev);
can_led_event(dev, CAN_LED_EVENT_OPEN);
napi_enable(&priv->napi);
netif_start_queue(dev);
return 0;
exit_irq_fail:
close_candev(dev);
exit_disable_cclk:
clk_disable_unprepare(priv->cclk);
exit_disable_hclk:
clk_disable_unprepare(priv->hclk);
return err;
}
static void m_can_stop(struct net_device *dev)
{
struct m_can_priv *priv = netdev_priv(dev);
/* disable all interrupts */
m_can_disable_all_interrupts(priv);
clk_disable_unprepare(priv->hclk);
clk_disable_unprepare(priv->cclk);
/* set the state as STOPPED */
priv->can.state = CAN_STATE_STOPPED;
}
static int m_can_close(struct net_device *dev)
{
struct m_can_priv *priv = netdev_priv(dev);
netif_stop_queue(dev);
napi_disable(&priv->napi);
m_can_stop(dev);
free_irq(dev->irq, dev);
close_candev(dev);
can_led_event(dev, CAN_LED_EVENT_STOP);
return 0;
}
static netdev_tx_t m_can_start_xmit(struct sk_buff *skb,
struct net_device *dev)
{
struct m_can_priv *priv = netdev_priv(dev);
struct can_frame *cf = (struct can_frame *)skb->data;
u32 id;
if (can_dropped_invalid_skb(dev, skb))
return NETDEV_TX_OK;
netif_stop_queue(dev);
if (cf->can_id & CAN_EFF_FLAG) {
id = cf->can_id & CAN_EFF_MASK;
id |= TX_BUF_XTD;
} else {
id = ((cf->can_id & CAN_SFF_MASK) << 18);
}
if (cf->can_id & CAN_RTR_FLAG)
id |= TX_BUF_RTR;
/* message ram configuration */
m_can_fifo_write(priv, 0, M_CAN_FIFO_ID, id);
m_can_fifo_write(priv, 0, M_CAN_FIFO_DLC, cf->can_dlc << 16);
m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(0), *(u32 *)(cf->data + 0));
m_can_fifo_write(priv, 0, M_CAN_FIFO_DATA(1), *(u32 *)(cf->data + 4));
can_put_echo_skb(skb, dev, 0);
/* enable first TX buffer to start transfer */
m_can_write(priv, M_CAN_TXBTIE, 0x1);
m_can_write(priv, M_CAN_TXBAR, 0x1);
return NETDEV_TX_OK;
}
static const struct net_device_ops m_can_netdev_ops = {
.ndo_open = m_can_open,
.ndo_stop = m_can_close,
.ndo_start_xmit = m_can_start_xmit,
};
static int register_m_can_dev(struct net_device *dev)
{
dev->flags |= IFF_ECHO; /* we support local echo */
dev->netdev_ops = &m_can_netdev_ops;
return register_candev(dev);
}
static int m_can_of_parse_mram(struct platform_device *pdev,
struct m_can_priv *priv)
{
struct device_node *np = pdev->dev.of_node;
struct resource *res;
void __iomem *addr;
u32 out_val[MRAM_CFG_LEN];
int ret;
/* message ram could be shared */
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "message_ram");
if (!res)
return -ENODEV;
addr = devm_ioremap(&pdev->dev, res->start, resource_size(res));
if (!addr)
return -ENOMEM;
/* get message ram configuration */
ret = of_property_read_u32_array(np, "bosch,mram-cfg",
out_val, sizeof(out_val) / 4);
if (ret) {
dev_err(&pdev->dev, "can not get message ram configuration\n");
return -ENODEV;
}
priv->mram_base = addr;
priv->mcfg[MRAM_SIDF].off = out_val[0];
priv->mcfg[MRAM_SIDF].num = out_val[1];
priv->mcfg[MRAM_XIDF].off = priv->mcfg[MRAM_SIDF].off +
priv->mcfg[MRAM_SIDF].num * SIDF_ELEMENT_SIZE;
priv->mcfg[MRAM_XIDF].num = out_val[2];
priv->mcfg[MRAM_RXF0].off = priv->mcfg[MRAM_XIDF].off +
priv->mcfg[MRAM_XIDF].num * XIDF_ELEMENT_SIZE;
priv->mcfg[MRAM_RXF0].num = out_val[3] & RXFC_FS_MASK;
priv->mcfg[MRAM_RXF1].off = priv->mcfg[MRAM_RXF0].off +
priv->mcfg[MRAM_RXF0].num * RXF0_ELEMENT_SIZE;
priv->mcfg[MRAM_RXF1].num = out_val[4] & RXFC_FS_MASK;
priv->mcfg[MRAM_RXB].off = priv->mcfg[MRAM_RXF1].off +
priv->mcfg[MRAM_RXF1].num * RXF1_ELEMENT_SIZE;
priv->mcfg[MRAM_RXB].num = out_val[5];
priv->mcfg[MRAM_TXE].off = priv->mcfg[MRAM_RXB].off +
priv->mcfg[MRAM_RXB].num * RXB_ELEMENT_SIZE;
priv->mcfg[MRAM_TXE].num = out_val[6];
priv->mcfg[MRAM_TXB].off = priv->mcfg[MRAM_TXE].off +
priv->mcfg[MRAM_TXE].num * TXE_ELEMENT_SIZE;
priv->mcfg[MRAM_TXB].num = out_val[7] & TXBC_NDTB_MASK;
dev_dbg(&pdev->dev, "mram_base %p sidf 0x%x %d xidf 0x%x %d rxf0 0x%x %d rxf1 0x%x %d rxb 0x%x %d txe 0x%x %d txb 0x%x %d\n",
priv->mram_base,
priv->mcfg[MRAM_SIDF].off, priv->mcfg[MRAM_SIDF].num,
priv->mcfg[MRAM_XIDF].off, priv->mcfg[MRAM_XIDF].num,
priv->mcfg[MRAM_RXF0].off, priv->mcfg[MRAM_RXF0].num,
priv->mcfg[MRAM_RXF1].off, priv->mcfg[MRAM_RXF1].num,
priv->mcfg[MRAM_RXB].off, priv->mcfg[MRAM_RXB].num,
priv->mcfg[MRAM_TXE].off, priv->mcfg[MRAM_TXE].num,
priv->mcfg[MRAM_TXB].off, priv->mcfg[MRAM_TXB].num);
return 0;
}
static int m_can_plat_probe(struct platform_device *pdev)
{
struct net_device *dev;
struct m_can_priv *priv;
struct resource *res;
void __iomem *addr;
struct clk *hclk, *cclk;
int irq, ret;
hclk = devm_clk_get(&pdev->dev, "hclk");
cclk = devm_clk_get(&pdev->dev, "cclk");
if (IS_ERR(hclk) || IS_ERR(cclk)) {
dev_err(&pdev->dev, "no clock find\n");
return -ENODEV;
}
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)
return -EINVAL;
/* allocate the m_can device */
dev = alloc_m_can_dev();
if (!dev)
return -ENOMEM;
priv = netdev_priv(dev);
dev->irq = irq;
priv->base = addr;
priv->device = &pdev->dev;
priv->hclk = hclk;
priv->cclk = cclk;
priv->can.clock.freq = clk_get_rate(cclk);
ret = m_can_of_parse_mram(pdev, priv);
if (ret)
goto failed_free_dev;
platform_set_drvdata(pdev, dev);
SET_NETDEV_DEV(dev, &pdev->dev);
ret = register_m_can_dev(dev);
if (ret) {
dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
KBUILD_MODNAME, ret);
goto failed_free_dev;
}
devm_can_led_init(dev);
dev_info(&pdev->dev, "%s device registered (regs=%p, irq=%d)\n",
KBUILD_MODNAME, priv->base, dev->irq);
return 0;
failed_free_dev:
free_m_can_dev(dev);
return ret;
}
static __maybe_unused int m_can_suspend(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
struct m_can_priv *priv = netdev_priv(ndev);
if (netif_running(ndev)) {
netif_stop_queue(ndev);
netif_device_detach(ndev);
}
/* TODO: enter low power */
priv->can.state = CAN_STATE_SLEEPING;
return 0;
}
static __maybe_unused int m_can_resume(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
struct m_can_priv *priv = netdev_priv(ndev);
/* TODO: exit low power */
priv->can.state = CAN_STATE_ERROR_ACTIVE;
if (netif_running(ndev)) {
netif_device_attach(ndev);
netif_start_queue(ndev);
}
return 0;
}
static void unregister_m_can_dev(struct net_device *dev)
{
unregister_candev(dev);
}
static int m_can_plat_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
unregister_m_can_dev(dev);
platform_set_drvdata(pdev, NULL);
free_m_can_dev(dev);
return 0;
}
static const struct dev_pm_ops m_can_pmops = {
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_LICENSE("GPL v2");
MODULE_DESCRIPTION("CAN bus driver for Bosch M_CAN controller");
obj-$(CONFIG_CAN_MPC5XXX) += mscan-mpc5xxx.o obj-$(CONFIG_CAN_MPC5XXX) += mscan-mpc5xxx.o
mscan-mpc5xxx-objs := mscan.o mpc5xxx_can.o mscan-mpc5xxx-objs := mscan.o mpc5xxx_can.o
ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/can/dev.h> #include <linux/can/dev.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/can/platform/rcar_can.h> #include <linux/can/platform/rcar_can.h>
#include <linux/of.h>
#define RCAR_CAN_DRV_NAME "rcar_can" #define RCAR_CAN_DRV_NAME "rcar_can"
...@@ -87,6 +88,7 @@ struct rcar_can_priv { ...@@ -87,6 +88,7 @@ struct rcar_can_priv {
struct napi_struct napi; struct napi_struct napi;
struct rcar_can_regs __iomem *regs; struct rcar_can_regs __iomem *regs;
struct clk *clk; struct clk *clk;
struct clk *can_clk;
u8 tx_dlc[RCAR_CAN_FIFO_DEPTH]; u8 tx_dlc[RCAR_CAN_FIFO_DEPTH];
u32 tx_head; u32 tx_head;
u32 tx_tail; u32 tx_tail;
...@@ -505,14 +507,20 @@ static int rcar_can_open(struct net_device *ndev) ...@@ -505,14 +507,20 @@ static int rcar_can_open(struct net_device *ndev)
err = clk_prepare_enable(priv->clk); err = clk_prepare_enable(priv->clk);
if (err) { if (err) {
netdev_err(ndev, "clk_prepare_enable() failed, error %d\n", netdev_err(ndev, "failed to enable periperal clock, error %d\n",
err); err);
goto out; goto out;
} }
err = clk_prepare_enable(priv->can_clk);
if (err) {
netdev_err(ndev, "failed to enable CAN clock, error %d\n",
err);
goto out_clock;
}
err = open_candev(ndev); err = open_candev(ndev);
if (err) { if (err) {
netdev_err(ndev, "open_candev() failed, error %d\n", err); netdev_err(ndev, "open_candev() failed, error %d\n", err);
goto out_clock; goto out_can_clock;
} }
napi_enable(&priv->napi); napi_enable(&priv->napi);
err = request_irq(ndev->irq, rcar_can_interrupt, 0, ndev->name, ndev); err = request_irq(ndev->irq, rcar_can_interrupt, 0, ndev->name, ndev);
...@@ -527,6 +535,8 @@ static int rcar_can_open(struct net_device *ndev) ...@@ -527,6 +535,8 @@ static int rcar_can_open(struct net_device *ndev)
out_close: out_close:
napi_disable(&priv->napi); napi_disable(&priv->napi);
close_candev(ndev); close_candev(ndev);
out_can_clock:
clk_disable_unprepare(priv->can_clk);
out_clock: out_clock:
clk_disable_unprepare(priv->clk); clk_disable_unprepare(priv->clk);
out: out:
...@@ -565,6 +575,7 @@ static int rcar_can_close(struct net_device *ndev) ...@@ -565,6 +575,7 @@ static int rcar_can_close(struct net_device *ndev)
rcar_can_stop(ndev); rcar_can_stop(ndev);
free_irq(ndev->irq, ndev); free_irq(ndev->irq, ndev);
napi_disable(&priv->napi); napi_disable(&priv->napi);
clk_disable_unprepare(priv->can_clk);
clk_disable_unprepare(priv->clk); clk_disable_unprepare(priv->clk);
close_candev(ndev); close_candev(ndev);
can_led_event(ndev, CAN_LED_EVENT_STOP); can_led_event(ndev, CAN_LED_EVENT_STOP);
...@@ -715,6 +726,12 @@ static int rcar_can_get_berr_counter(const struct net_device *dev, ...@@ -715,6 +726,12 @@ static int rcar_can_get_berr_counter(const struct net_device *dev,
return 0; return 0;
} }
static const char * const clock_names[] = {
[CLKR_CLKP1] = "clkp1",
[CLKR_CLKP2] = "clkp2",
[CLKR_CLKEXT] = "can_clk",
};
static int rcar_can_probe(struct platform_device *pdev) static int rcar_can_probe(struct platform_device *pdev)
{ {
struct rcar_can_platform_data *pdata; struct rcar_can_platform_data *pdata;
...@@ -722,13 +739,20 @@ static int rcar_can_probe(struct platform_device *pdev) ...@@ -722,13 +739,20 @@ static int rcar_can_probe(struct platform_device *pdev)
struct net_device *ndev; struct net_device *ndev;
struct resource *mem; struct resource *mem;
void __iomem *addr; void __iomem *addr;
u32 clock_select = CLKR_CLKP1;
int err = -ENODEV; int err = -ENODEV;
int irq; int irq;
pdata = dev_get_platdata(&pdev->dev); if (pdev->dev.of_node) {
if (!pdata) { of_property_read_u32(pdev->dev.of_node,
dev_err(&pdev->dev, "No platform data provided!\n"); "renesas,can-clock-select", &clock_select);
goto fail; } else {
pdata = dev_get_platdata(&pdev->dev);
if (!pdata) {
dev_err(&pdev->dev, "No platform data provided!\n");
goto fail;
}
clock_select = pdata->clock_select;
} }
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
...@@ -753,10 +777,22 @@ static int rcar_can_probe(struct platform_device *pdev) ...@@ -753,10 +777,22 @@ static int rcar_can_probe(struct platform_device *pdev)
priv = netdev_priv(ndev); priv = netdev_priv(ndev);
priv->clk = devm_clk_get(&pdev->dev, NULL); priv->clk = devm_clk_get(&pdev->dev, "clkp1");
if (IS_ERR(priv->clk)) { if (IS_ERR(priv->clk)) {
err = PTR_ERR(priv->clk); err = PTR_ERR(priv->clk);
dev_err(&pdev->dev, "cannot get clock: %d\n", err); dev_err(&pdev->dev, "cannot get peripheral clock: %d\n", err);
goto fail_clk;
}
if (clock_select >= ARRAY_SIZE(clock_names)) {
err = -EINVAL;
dev_err(&pdev->dev, "invalid CAN clock selected\n");
goto fail_clk;
}
priv->can_clk = devm_clk_get(&pdev->dev, clock_names[clock_select]);
if (IS_ERR(priv->can_clk)) {
err = PTR_ERR(priv->can_clk);
dev_err(&pdev->dev, "cannot get CAN clock: %d\n", err);
goto fail_clk; goto fail_clk;
} }
...@@ -765,8 +801,8 @@ static int rcar_can_probe(struct platform_device *pdev) ...@@ -765,8 +801,8 @@ static int rcar_can_probe(struct platform_device *pdev)
ndev->flags |= IFF_ECHO; ndev->flags |= IFF_ECHO;
priv->ndev = ndev; priv->ndev = ndev;
priv->regs = addr; priv->regs = addr;
priv->clock_select = pdata->clock_select; priv->clock_select = clock_select;
priv->can.clock.freq = clk_get_rate(priv->clk); priv->can.clock.freq = clk_get_rate(priv->can_clk);
priv->can.bittiming_const = &rcar_can_bittiming_const; priv->can.bittiming_const = &rcar_can_bittiming_const;
priv->can.do_set_mode = rcar_can_do_set_mode; priv->can.do_set_mode = rcar_can_do_set_mode;
priv->can.do_get_berr_counter = rcar_can_get_berr_counter; priv->can.do_get_berr_counter = rcar_can_get_berr_counter;
...@@ -858,10 +894,20 @@ static int __maybe_unused rcar_can_resume(struct device *dev) ...@@ -858,10 +894,20 @@ static int __maybe_unused rcar_can_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(rcar_can_pm_ops, rcar_can_suspend, rcar_can_resume); static SIMPLE_DEV_PM_OPS(rcar_can_pm_ops, rcar_can_suspend, rcar_can_resume);
static const struct of_device_id rcar_can_of_table[] __maybe_unused = {
{ .compatible = "renesas,can-r8a7778" },
{ .compatible = "renesas,can-r8a7779" },
{ .compatible = "renesas,can-r8a7790" },
{ .compatible = "renesas,can-r8a7791" },
{ }
};
MODULE_DEVICE_TABLE(of, rcar_can_of_table);
static struct platform_driver rcar_can_driver = { static struct platform_driver rcar_can_driver = {
.driver = { .driver = {
.name = RCAR_CAN_DRV_NAME, .name = RCAR_CAN_DRV_NAME,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.of_match_table = of_match_ptr(rcar_can_of_table),
.pm = &rcar_can_pm_ops, .pm = &rcar_can_pm_ops,
}, },
.probe = rcar_can_probe, .probe = rcar_can_probe,
......
...@@ -12,5 +12,3 @@ obj-$(CONFIG_CAN_PEAK_PCMCIA) += peak_pcmcia.o ...@@ -12,5 +12,3 @@ 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_PLX_PCI) += plx_pci.o obj-$(CONFIG_CAN_PLX_PCI) += plx_pci.o
obj-$(CONFIG_CAN_TSCAN1) += tscan1.o obj-$(CONFIG_CAN_TSCAN1) += tscan1.o
ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
...@@ -2,5 +2,3 @@ ...@@ -2,5 +2,3 @@
softing-y := softing_main.o softing_fw.o softing-y := softing_main.o softing_fw.o
obj-$(CONFIG_CAN_SOFTING) += softing.o obj-$(CONFIG_CAN_SOFTING) += softing.o
obj-$(CONFIG_CAN_SOFTING_CS) += softing_cs.o obj-$(CONFIG_CAN_SOFTING_CS) += softing_cs.o
ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
...@@ -4,5 +4,3 @@ ...@@ -4,5 +4,3 @@
obj-$(CONFIG_CAN_MCP251X) += mcp251x.o obj-$(CONFIG_CAN_MCP251X) += mcp251x.o
ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
...@@ -1107,10 +1107,10 @@ static int mcp251x_can_probe(struct spi_device *spi) ...@@ -1107,10 +1107,10 @@ static int mcp251x_can_probe(struct spi_device *spi)
* Minimum coherent DMA allocation is PAGE_SIZE, so allocate * Minimum coherent DMA allocation is PAGE_SIZE, so allocate
* that much and share it between Tx and Rx DMA buffers. * that much and share it between Tx and Rx DMA buffers.
*/ */
priv->spi_tx_buf = dma_alloc_coherent(&spi->dev, priv->spi_tx_buf = dmam_alloc_coherent(&spi->dev,
PAGE_SIZE, PAGE_SIZE,
&priv->spi_tx_dma, &priv->spi_tx_dma,
GFP_DMA); GFP_DMA);
if (priv->spi_tx_buf) { if (priv->spi_tx_buf) {
priv->spi_rx_buf = (priv->spi_tx_buf + (PAGE_SIZE / 2)); priv->spi_rx_buf = (priv->spi_tx_buf + (PAGE_SIZE / 2));
...@@ -1156,9 +1156,6 @@ static int mcp251x_can_probe(struct spi_device *spi) ...@@ -1156,9 +1156,6 @@ static int mcp251x_can_probe(struct spi_device *spi)
return 0; return 0;
error_probe: error_probe:
if (mcp251x_enable_dma)
dma_free_coherent(&spi->dev, PAGE_SIZE,
priv->spi_tx_buf, priv->spi_tx_dma);
mcp251x_power_enable(priv->power, 0); mcp251x_power_enable(priv->power, 0);
out_clk: out_clk:
...@@ -1178,11 +1175,6 @@ static int mcp251x_can_remove(struct spi_device *spi) ...@@ -1178,11 +1175,6 @@ static int mcp251x_can_remove(struct spi_device *spi)
unregister_candev(net); unregister_candev(net);
if (mcp251x_enable_dma) {
dma_free_coherent(&spi->dev, PAGE_SIZE,
priv->spi_tx_buf, priv->spi_tx_dma);
}
mcp251x_power_enable(priv->power, 0); mcp251x_power_enable(priv->power, 0);
if (!IS_ERR(priv->clk)) if (!IS_ERR(priv->clk))
......
...@@ -8,5 +8,3 @@ obj-$(CONFIG_CAN_GS_USB) += gs_usb.o ...@@ -8,5 +8,3 @@ obj-$(CONFIG_CAN_GS_USB) += gs_usb.o
obj-$(CONFIG_CAN_KVASER_USB) += kvaser_usb.o obj-$(CONFIG_CAN_KVASER_USB) += kvaser_usb.o
obj-$(CONFIG_CAN_PEAK_USB) += peak_usb/ obj-$(CONFIG_CAN_PEAK_USB) += peak_usb/
obj-$(CONFIG_CAN_8DEV_USB) += usb_8dev.o obj-$(CONFIG_CAN_8DEV_USB) += usb_8dev.o
ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
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