Commit 5db15872 authored by David S. Miller's avatar David S. Miller

Merge tag 'linux-can-next-for-4.8-20160623' of...

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

Marc Kleine-Budde says:

====================
pull-request: can-next 2016-06-17

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

Arnd Bergmann's patch fixes a regresseion in af_can introduced in
linux-can-next-for-4.8-20160617. There are two patches by Ramesh
Shanmugasundaram, which add CAN-2.0 support to the rcar_canfd driver.
And a patch by Ed Spiridonov that adds better error diagnoses messages
to the Ed Spiridonov driver.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 810bf110 b63f69d0
...@@ -32,6 +32,12 @@ below properties. ...@@ -32,6 +32,12 @@ below properties.
- assigned-clocks: phandle of canfd clock. - assigned-clocks: phandle of canfd clock.
- assigned-clock-rates: maximum frequency of this clock. - assigned-clock-rates: maximum frequency of this clock.
Optional property:
The controller can operate in either CAN FD only mode (default) or
Classical CAN only mode. The mode is global to both the channels. In order to
enable the later, define the following optional property.
- renesas,no-can-fd: puts the controller in Classical CAN only mode.
Example Example
------- -------
...@@ -63,12 +69,13 @@ SoC common .dtsi file: ...@@ -63,12 +69,13 @@ SoC common .dtsi file:
Board specific .dts file: Board specific .dts file:
E.g. below enables Channel 1 alone in the board. E.g. below enables Channel 1 alone in the board in Classical CAN only mode.
&canfd { &canfd {
pinctrl-0 = <&canfd1_pins>; pinctrl-0 = <&canfd1_pins>;
pinctrl-names = "default"; pinctrl-names = "default";
status = "okay"; renesas,no-can-fd;
status = "okay";
channel1 { channel1 {
status = "okay"; status = "okay";
...@@ -79,9 +86,9 @@ E.g. below enables Channel 0 alone in the board using External clock ...@@ -79,9 +86,9 @@ E.g. below enables Channel 0 alone in the board using External clock
as fCAN clock. as fCAN clock.
&canfd { &canfd {
pinctrl-0 = <&canfd0_pins &can_clk_pins>; pinctrl-0 = <&canfd0_pins &can_clk_pins>;
pinctrl-names = "default"; pinctrl-names = "default";
status = "okay"; status = "okay";
channel0 { channel0 {
status = "okay"; status = "okay";
......
...@@ -16,8 +16,9 @@ ...@@ -16,8 +16,9 @@
* mode, the controller acts as a CAN FD node that can also interoperate with * mode, the controller acts as a CAN FD node that can also interoperate with
* CAN 2.0 nodes. * CAN 2.0 nodes.
* *
* As of now, this driver does not support the Classical CAN (CAN 2.0) mode, * To switch the controller to Classical CAN (CAN 2.0) only mode, add
* which is handled by a different register map compared to CAN FD only mode. * "renesas,no-can-fd" optional property to the device tree node. A h/w reset is
* also required to switch modes.
* *
* Note: The h/w manual register naming convention is clumsy and not acceptable * Note: The h/w manual register naming convention is clumsy and not acceptable
* to use as it is in the driver. However, those names are added as comments * to use as it is in the driver. However, those names are added as comments
...@@ -48,15 +49,16 @@ ...@@ -48,15 +49,16 @@
/* RSCFDnCFDGRMCFG */ /* RSCFDnCFDGRMCFG */
#define RCANFD_GRMCFG_RCMC BIT(0) #define RCANFD_GRMCFG_RCMC BIT(0)
/* RSCFDnCFDGCFG */ /* RSCFDnCFDGCFG / RSCFDnGCFG */
#define RCANFD_GCFG_CMPOC BIT(5) #define RCANFD_GCFG_EEFE BIT(6)
#define RCANFD_GCFG_CMPOC BIT(5) /* CAN FD only */
#define RCANFD_GCFG_DCS BIT(4) #define RCANFD_GCFG_DCS BIT(4)
#define RCANFD_GCFG_DCE BIT(1) #define RCANFD_GCFG_DCE BIT(1)
#define RCANFD_GCFG_TPRI BIT(0) #define RCANFD_GCFG_TPRI BIT(0)
/* RSCFDnCFDGCTR */ /* RSCFDnCFDGCTR / RSCFDnGCTR */
#define RCANFD_GCTR_TSRST BIT(16) #define RCANFD_GCTR_TSRST BIT(16)
#define RCANFD_GCTR_CFMPOFIE BIT(11) #define RCANFD_GCTR_CFMPOFIE BIT(11) /* CAN FD only */
#define RCANFD_GCTR_THLEIE BIT(10) #define RCANFD_GCTR_THLEIE BIT(10)
#define RCANFD_GCTR_MEIE BIT(9) #define RCANFD_GCTR_MEIE BIT(9)
#define RCANFD_GCTR_DEIE BIT(8) #define RCANFD_GCTR_DEIE BIT(8)
...@@ -66,7 +68,7 @@ ...@@ -66,7 +68,7 @@
#define RCANFD_GCTR_GMDC_GRESET (0x1) #define RCANFD_GCTR_GMDC_GRESET (0x1)
#define RCANFD_GCTR_GMDC_GTEST (0x2) #define RCANFD_GCTR_GMDC_GTEST (0x2)
/* RSCFDnCFDGSTS */ /* RSCFDnCFDGSTS / RSCFDnGSTS */
#define RCANFD_GSTS_GRAMINIT BIT(3) #define RCANFD_GSTS_GRAMINIT BIT(3)
#define RCANFD_GSTS_GSLPSTS BIT(2) #define RCANFD_GSTS_GSLPSTS BIT(2)
#define RCANFD_GSTS_GHLTSTS BIT(1) #define RCANFD_GSTS_GHLTSTS BIT(1)
...@@ -74,44 +76,50 @@ ...@@ -74,44 +76,50 @@
/* Non-operational status */ /* Non-operational status */
#define RCANFD_GSTS_GNOPM (BIT(0) | BIT(1) | BIT(2) | BIT(3)) #define RCANFD_GSTS_GNOPM (BIT(0) | BIT(1) | BIT(2) | BIT(3))
/* RSCFDnCFDGERFL */ /* RSCFDnCFDGERFL / RSCFDnGERFL */
#define RCANFD_GERFL_EEF1 BIT(17) #define RCANFD_GERFL_EEF1 BIT(17)
#define RCANFD_GERFL_EEF0 BIT(16) #define RCANFD_GERFL_EEF0 BIT(16)
#define RCANFD_GERFL_CMPOF BIT(3) #define RCANFD_GERFL_CMPOF BIT(3) /* CAN FD only */
#define RCANFD_GERFL_THLES BIT(2) #define RCANFD_GERFL_THLES BIT(2)
#define RCANFD_GERFL_MES BIT(1) #define RCANFD_GERFL_MES BIT(1)
#define RCANFD_GERFL_DEF BIT(0) #define RCANFD_GERFL_DEF BIT(0)
#define RCANFD_GERFL_ERR(x) ((x) & (RCANFD_GERFL_EEF1 |\ #define RCANFD_GERFL_ERR(gpriv, x) ((x) & (RCANFD_GERFL_EEF1 |\
RCANFD_GERFL_EEF0 |\ RCANFD_GERFL_EEF0 | RCANFD_GERFL_MES |\
RCANFD_GERFL_MES |\ (gpriv->fdmode ?\
RCANFD_GERFL_CMPOF)) RCANFD_GERFL_CMPOF : 0)))
/* AFL Rx rules registers */ /* AFL Rx rules registers */
/* RSCFDnCFDGAFLCFG0 */ /* RSCFDnCFDGAFLCFG0 / RSCFDnGAFLCFG0 */
#define RCANFD_GAFLCFG_SETRNC(n, x) (((x) & 0xff) << (24 - n * 8)) #define RCANFD_GAFLCFG_SETRNC(n, x) (((x) & 0xff) << (24 - n * 8))
#define RCANFD_GAFLCFG_GETRNC(n, x) (((x) >> (24 - n * 8)) & 0xff) #define RCANFD_GAFLCFG_GETRNC(n, x) (((x) >> (24 - n * 8)) & 0xff)
/* RSCFDnCFDGAFLECTR */ /* RSCFDnCFDGAFLECTR / RSCFDnGAFLECTR */
#define RCANFD_GAFLECTR_AFLDAE BIT(8) #define RCANFD_GAFLECTR_AFLDAE BIT(8)
#define RCANFD_GAFLECTR_AFLPN(x) ((x) & 0x1f) #define RCANFD_GAFLECTR_AFLPN(x) ((x) & 0x1f)
/* RSCFDnCFDGAFLIDj */ /* RSCFDnCFDGAFLIDj / RSCFDnGAFLIDj */
#define RCANFD_GAFLID_GAFLLB BIT(29) #define RCANFD_GAFLID_GAFLLB BIT(29)
/* RSCFDnCFDGAFLP1_j */ /* RSCFDnCFDGAFLP1_j / RSCFDnGAFLP1_j */
#define RCANFD_GAFLP1_GAFLFDP(x) (1 << (x)) #define RCANFD_GAFLP1_GAFLFDP(x) (1 << (x))
/* Channel register bits */ /* Channel register bits */
/* RSCFDnCFDCmNCFG */ /* RSCFDnCmCFG - Classical CAN only */
#define RCANFD_CFG_SJW(x) (((x) & 0x3) << 24)
#define RCANFD_CFG_TSEG2(x) (((x) & 0x7) << 20)
#define RCANFD_CFG_TSEG1(x) (((x) & 0xf) << 16)
#define RCANFD_CFG_BRP(x) (((x) & 0x3ff) << 0)
/* RSCFDnCFDCmNCFG - CAN FD only */
#define RCANFD_NCFG_NTSEG2(x) (((x) & 0x1f) << 24) #define RCANFD_NCFG_NTSEG2(x) (((x) & 0x1f) << 24)
#define RCANFD_NCFG_NTSEG1(x) (((x) & 0x7f) << 16) #define RCANFD_NCFG_NTSEG1(x) (((x) & 0x7f) << 16)
#define RCANFD_NCFG_NSJW(x) (((x) & 0x1f) << 11) #define RCANFD_NCFG_NSJW(x) (((x) & 0x1f) << 11)
#define RCANFD_NCFG_NBRP(x) (((x) & 0x3ff) << 0) #define RCANFD_NCFG_NBRP(x) (((x) & 0x3ff) << 0)
/* RSCFDnCFDCmCTR */ /* RSCFDnCFDCmCTR / RSCFDnCmCTR */
#define RCANFD_CCTR_CTME BIT(24) #define RCANFD_CCTR_CTME BIT(24)
#define RCANFD_CCTR_ERRD BIT(23) #define RCANFD_CCTR_ERRD BIT(23)
#define RCANFD_CCTR_BOM_MASK (0x3 << 21) #define RCANFD_CCTR_BOM_MASK (0x3 << 21)
...@@ -136,7 +144,7 @@ ...@@ -136,7 +144,7 @@
#define RCANFD_CCTR_CHDMC_CRESET (0x1) #define RCANFD_CCTR_CHDMC_CRESET (0x1)
#define RCANFD_CCTR_CHDMC_CHLT (0x2) #define RCANFD_CCTR_CHDMC_CHLT (0x2)
/* RSCFDnCFDCmSTS */ /* RSCFDnCFDCmSTS / RSCFDnCmSTS */
#define RCANFD_CSTS_COMSTS BIT(7) #define RCANFD_CSTS_COMSTS BIT(7)
#define RCANFD_CSTS_RECSTS BIT(6) #define RCANFD_CSTS_RECSTS BIT(6)
#define RCANFD_CSTS_TRMSTS BIT(5) #define RCANFD_CSTS_TRMSTS BIT(5)
...@@ -149,7 +157,7 @@ ...@@ -149,7 +157,7 @@
#define RCANFD_CSTS_TECCNT(x) (((x) >> 24) & 0xff) #define RCANFD_CSTS_TECCNT(x) (((x) >> 24) & 0xff)
#define RCANFD_CSTS_RECCNT(x) (((x) >> 16) & 0xff) #define RCANFD_CSTS_RECCNT(x) (((x) >> 16) & 0xff)
/* RSCFDnCFDCmERFL */ /* RSCFDnCFDCmERFL / RSCFDnCmERFL */
#define RCANFD_CERFL_ADERR BIT(14) #define RCANFD_CERFL_ADERR BIT(14)
#define RCANFD_CERFL_B0ERR BIT(13) #define RCANFD_CERFL_B0ERR BIT(13)
#define RCANFD_CERFL_B1ERR BIT(12) #define RCANFD_CERFL_B1ERR BIT(12)
...@@ -239,14 +247,14 @@ ...@@ -239,14 +247,14 @@
#define RCANFD_CFFDCSTS_CFBRS BIT(1) #define RCANFD_CFFDCSTS_CFBRS BIT(1)
#define RCANFD_CFFDCSTS_CFESI BIT(0) #define RCANFD_CFFDCSTS_CFESI BIT(0)
/* This controller supports classical CAN only mode or CAN FD only mode. These /* This controller supports either Classical CAN only mode or CAN FD only mode.
* modes are supported in two separate set of register maps & names. However, * These modes are supported in two separate set of register maps & names.
* some of the register offsets are common for both modes. Those offsets are * However, some of the register offsets are common for both modes. Those
* listed below as Common registers. * offsets are listed below as Common registers.
* *
* The CAN FD only specific registers are listed separately and their names * The CAN FD only mode specific registers & Classical CAN only mode specific
* starts with RCANFD_F_xxx names. When classical CAN only specific registers * registers are listed separately. Their register names starts with
* are added, those specific registers can be prefixed as RCANFD_C_xxx. * RCANFD_F_xxx & RCANFD_C_xxx respectively.
*/ */
/* Common registers */ /* Common registers */
...@@ -353,7 +361,7 @@ ...@@ -353,7 +361,7 @@
#define RCANFD_GTSTCTR (0x046c) #define RCANFD_GTSTCTR (0x046c)
/* RSCFDnCFDGLOCKK / RSCFDnGLOCKK */ /* RSCFDnCFDGLOCKK / RSCFDnGLOCKK */
#define RCANFD_GLOCKK (0x047c) #define RCANFD_GLOCKK (0x047c)
/* RSCFDnCFDGRMCFG / RSCFDnGRMCFG */ /* RSCFDnCFDGRMCFG */
#define RCANFD_GRMCFG (0x04fc) #define RCANFD_GRMCFG (0x04fc)
/* RSCFDnCFDGAFLIDj / RSCFDnGAFLIDj */ /* RSCFDnCFDGAFLIDj / RSCFDnGAFLIDj */
...@@ -365,6 +373,46 @@ ...@@ -365,6 +373,46 @@
/* RSCFDnCFDGAFLP1j / RSCFDnGAFLP1j */ /* RSCFDnCFDGAFLP1j / RSCFDnGAFLP1j */
#define RCANFD_GAFLP1(offset, j) ((offset) + 0x0c + (0x10 * (j))) #define RCANFD_GAFLP1(offset, j) ((offset) + 0x0c + (0x10 * (j)))
/* Classical CAN only mode register map */
/* RSCFDnGAFLXXXj offset */
#define RCANFD_C_GAFL_OFFSET (0x0500)
/* RSCFDnRMXXXq -> RCANFD_C_RMXXX(q) */
#define RCANFD_C_RMID(q) (0x0600 + (0x10 * (q)))
#define RCANFD_C_RMPTR(q) (0x0604 + (0x10 * (q)))
#define RCANFD_C_RMDF0(q) (0x0608 + (0x10 * (q)))
#define RCANFD_C_RMDF1(q) (0x060c + (0x10 * (q)))
/* RSCFDnRFXXx -> RCANFD_C_RFXX(x) */
#define RCANFD_C_RFOFFSET (0x0e00)
#define RCANFD_C_RFID(x) (RCANFD_C_RFOFFSET + (0x10 * (x)))
#define RCANFD_C_RFPTR(x) (RCANFD_C_RFOFFSET + 0x04 + \
(0x10 * (x)))
#define RCANFD_C_RFDF(x, df) (RCANFD_C_RFOFFSET + 0x08 + \
(0x10 * (x)) + (0x04 * (df)))
/* RSCFDnCFXXk -> RCANFD_C_CFXX(ch, k) */
#define RCANFD_C_CFOFFSET (0x0e80)
#define RCANFD_C_CFID(ch, idx) (RCANFD_C_CFOFFSET + (0x30 * (ch)) + \
(0x10 * (idx)))
#define RCANFD_C_CFPTR(ch, idx) (RCANFD_C_CFOFFSET + 0x04 + \
(0x30 * (ch)) + (0x10 * (idx)))
#define RCANFD_C_CFDF(ch, idx, df) (RCANFD_C_CFOFFSET + 0x08 + \
(0x30 * (ch)) + (0x10 * (idx)) + \
(0x04 * (df)))
/* RSCFDnTMXXp -> RCANFD_C_TMXX(p) */
#define RCANFD_C_TMID(p) (0x1000 + (0x10 * (p)))
#define RCANFD_C_TMPTR(p) (0x1004 + (0x10 * (p)))
#define RCANFD_C_TMDF0(p) (0x1008 + (0x10 * (p)))
#define RCANFD_C_TMDF1(p) (0x100c + (0x10 * (p)))
/* RSCFDnTHLACCm */
#define RCANFD_C_THLACC(m) (0x1800 + (0x04 * (m)))
/* RSCFDnRPGACCr */
#define RCANFD_C_RPGACC(r) (0x1900 + (0x04 * (r)))
/* CAN FD mode specific regsiter map */ /* CAN FD mode specific regsiter map */
/* RSCFDnCFDCmXXX -> RCANFD_F_XXX(m) */ /* RSCFDnCFDCmXXX -> RCANFD_F_XXX(m) */
...@@ -468,6 +516,7 @@ struct rcar_canfd_global { ...@@ -468,6 +516,7 @@ struct rcar_canfd_global {
struct clk *can_clk; /* fCAN clock */ struct clk *can_clk; /* fCAN clock */
enum rcar_canfd_fcanclk fcan; /* CANFD or Ext clock */ enum rcar_canfd_fcanclk fcan; /* CANFD or Ext clock */
unsigned long channels_mask; /* Enabled channels mask */ unsigned long channels_mask; /* Enabled channels mask */
bool fdmode; /* CAN FD or Classical CAN only mode */
}; };
/* CAN FD mode nominal rate constants */ /* CAN FD mode nominal rate constants */
...@@ -496,6 +545,19 @@ static const struct can_bittiming_const rcar_canfd_data_bittiming_const = { ...@@ -496,6 +545,19 @@ static const struct can_bittiming_const rcar_canfd_data_bittiming_const = {
.brp_inc = 1, .brp_inc = 1,
}; };
/* Classical CAN mode bitrate constants */
static const struct can_bittiming_const rcar_canfd_bittiming_const = {
.name = RCANFD_DRV_NAME,
.tseg1_min = 4,
.tseg1_max = 16,
.tseg2_min = 2,
.tseg2_max = 8,
.sjw_max = 4,
.brp_min = 1,
.brp_max = 1024,
.brp_inc = 1,
};
/* Helper functions */ /* Helper functions */
static inline void rcar_canfd_update(u32 mask, u32 val, u32 __iomem *reg) static inline void rcar_canfd_update(u32 mask, u32 val, u32 __iomem *reg)
{ {
...@@ -593,8 +655,13 @@ static int rcar_canfd_reset_controller(struct rcar_canfd_global *gpriv) ...@@ -593,8 +655,13 @@ static int rcar_canfd_reset_controller(struct rcar_canfd_global *gpriv)
/* Reset Global error flags */ /* Reset Global error flags */
rcar_canfd_write(gpriv->base, RCANFD_GERFL, 0x0); rcar_canfd_write(gpriv->base, RCANFD_GERFL, 0x0);
/* Set the controller into FD mode */ /* Set the controller into appropriate mode */
rcar_canfd_set_bit(gpriv->base, RCANFD_GRMCFG, RCANFD_GRMCFG_RCMC); if (gpriv->fdmode)
rcar_canfd_set_bit(gpriv->base, RCANFD_GRMCFG,
RCANFD_GRMCFG_RCMC);
else
rcar_canfd_clear_bit(gpriv->base, RCANFD_GRMCFG,
RCANFD_GRMCFG_RCMC);
/* Transition all Channels to reset mode */ /* Transition all Channels to reset mode */
for_each_set_bit(ch, &gpriv->channels_mask, RCANFD_NUM_CHANNELS) { for_each_set_bit(ch, &gpriv->channels_mask, RCANFD_NUM_CHANNELS) {
...@@ -624,8 +691,12 @@ static void rcar_canfd_configure_controller(struct rcar_canfd_global *gpriv) ...@@ -624,8 +691,12 @@ static void rcar_canfd_configure_controller(struct rcar_canfd_global *gpriv)
/* Global configuration settings */ /* Global configuration settings */
/* Truncate payload to configured message size RFPLS */ /* ECC Error flag Enable */
cfg = RCANFD_GCFG_CMPOC; cfg = RCANFD_GCFG_EEFE;
if (gpriv->fdmode)
/* Truncate payload to configured message size RFPLS */
cfg |= RCANFD_GCFG_CMPOC;
/* Set External Clock if selected */ /* Set External Clock if selected */
if (gpriv->fcan != RCANFD_CANFDCLK) if (gpriv->fcan != RCANFD_CANFDCLK)
...@@ -647,7 +718,7 @@ static void rcar_canfd_configure_afl_rules(struct rcar_canfd_global *gpriv, ...@@ -647,7 +718,7 @@ static void rcar_canfd_configure_afl_rules(struct rcar_canfd_global *gpriv,
u32 ch) u32 ch)
{ {
u32 cfg; u32 cfg;
int start, page, num_rules = RCANFD_CHANNEL_NUMRULES; int offset, start, page, num_rules = RCANFD_CHANNEL_NUMRULES;
u32 ridx = ch + RCANFD_RFFIFO_IDX; u32 ridx = ch + RCANFD_RFFIFO_IDX;
if (ch == 0) { if (ch == 0) {
...@@ -667,19 +738,19 @@ static void rcar_canfd_configure_afl_rules(struct rcar_canfd_global *gpriv, ...@@ -667,19 +738,19 @@ static void rcar_canfd_configure_afl_rules(struct rcar_canfd_global *gpriv,
/* Write number of rules for channel */ /* Write number of rules for channel */
rcar_canfd_set_bit(gpriv->base, RCANFD_GAFLCFG0, rcar_canfd_set_bit(gpriv->base, RCANFD_GAFLCFG0,
RCANFD_GAFLCFG_SETRNC(ch, num_rules)); RCANFD_GAFLCFG_SETRNC(ch, num_rules));
if (gpriv->fdmode)
offset = RCANFD_F_GAFL_OFFSET;
else
offset = RCANFD_C_GAFL_OFFSET;
/* Accept all IDs */ /* Accept all IDs */
rcar_canfd_write(gpriv->base, rcar_canfd_write(gpriv->base, RCANFD_GAFLID(offset, start), 0);
RCANFD_GAFLID(RCANFD_F_GAFL_OFFSET, start), 0);
/* IDE or RTR is not considered for matching */ /* IDE or RTR is not considered for matching */
rcar_canfd_write(gpriv->base, rcar_canfd_write(gpriv->base, RCANFD_GAFLM(offset, start), 0);
RCANFD_GAFLM(RCANFD_F_GAFL_OFFSET, start), 0);
/* Any data length accepted */ /* Any data length accepted */
rcar_canfd_write(gpriv->base, rcar_canfd_write(gpriv->base, RCANFD_GAFLP0(offset, start), 0);
RCANFD_GAFLP0(RCANFD_F_GAFL_OFFSET, start), 0);
/* Place the msg in corresponding Rx FIFO entry */ /* Place the msg in corresponding Rx FIFO entry */
rcar_canfd_write(gpriv->base, rcar_canfd_write(gpriv->base, RCANFD_GAFLP1(offset, start),
RCANFD_GAFLP1(RCANFD_F_GAFL_OFFSET, start),
RCANFD_GAFLP1_GAFLFDP(ridx)); RCANFD_GAFLP1_GAFLFDP(ridx));
/* Disable write access to page */ /* Disable write access to page */
...@@ -697,7 +768,10 @@ static void rcar_canfd_configure_rx(struct rcar_canfd_global *gpriv, u32 ch) ...@@ -697,7 +768,10 @@ static void rcar_canfd_configure_rx(struct rcar_canfd_global *gpriv, u32 ch)
u32 ridx = ch + RCANFD_RFFIFO_IDX; u32 ridx = ch + RCANFD_RFFIFO_IDX;
rfdc = 2; /* b010 - 8 messages Rx FIFO depth */ rfdc = 2; /* b010 - 8 messages Rx FIFO depth */
rfpls = 7; /* b111 - Max 64 bytes payload */ if (gpriv->fdmode)
rfpls = 7; /* b111 - Max 64 bytes payload */
else
rfpls = 0; /* b000 - Max 8 bytes payload */
cfg = (RCANFD_RFCC_RFIM | RCANFD_RFCC_RFDC(rfdc) | cfg = (RCANFD_RFCC_RFIM | RCANFD_RFCC_RFDC(rfdc) |
RCANFD_RFCC_RFPLS(rfpls) | RCANFD_RFCC_RFIE); RCANFD_RFCC_RFPLS(rfpls) | RCANFD_RFCC_RFIE);
...@@ -718,16 +792,20 @@ static void rcar_canfd_configure_tx(struct rcar_canfd_global *gpriv, u32 ch) ...@@ -718,16 +792,20 @@ static void rcar_canfd_configure_tx(struct rcar_canfd_global *gpriv, u32 ch)
cftml = 0; /* 0th buffer */ cftml = 0; /* 0th buffer */
cfm = 1; /* b01 - Transmit mode */ cfm = 1; /* b01 - Transmit mode */
cfdc = 2; /* b010 - 8 messages Tx FIFO depth */ cfdc = 2; /* b010 - 8 messages Tx FIFO depth */
cfpls = 7; /* b111 - Max 64 bytes payload */ if (gpriv->fdmode)
cfpls = 7; /* b111 - Max 64 bytes payload */
else
cfpls = 0; /* b000 - Max 8 bytes payload */
cfg = (RCANFD_CFCC_CFTML(cftml) | RCANFD_CFCC_CFM(cfm) | cfg = (RCANFD_CFCC_CFTML(cftml) | RCANFD_CFCC_CFM(cfm) |
RCANFD_CFCC_CFIM | RCANFD_CFCC_CFDC(cfdc) | RCANFD_CFCC_CFIM | RCANFD_CFCC_CFDC(cfdc) |
RCANFD_CFCC_CFPLS(cfpls) | RCANFD_CFCC_CFTXIE); RCANFD_CFCC_CFPLS(cfpls) | RCANFD_CFCC_CFTXIE);
rcar_canfd_write(gpriv->base, RCANFD_CFCC(ch, RCANFD_CFFIFO_IDX), cfg); rcar_canfd_write(gpriv->base, RCANFD_CFCC(ch, RCANFD_CFFIFO_IDX), cfg);
/* Clear FD mode specific control/status register */ if (gpriv->fdmode)
rcar_canfd_write(gpriv->base, /* Clear FD mode specific control/status register */
RCANFD_F_CFFDCSTS(ch, RCANFD_CFFIFO_IDX), 0); rcar_canfd_write(gpriv->base,
RCANFD_F_CFFDCSTS(ch, RCANFD_CFFIFO_IDX), 0);
} }
static void rcar_canfd_enable_global_interrupts(struct rcar_canfd_global *gpriv) static void rcar_canfd_enable_global_interrupts(struct rcar_canfd_global *gpriv)
...@@ -739,7 +817,8 @@ static void rcar_canfd_enable_global_interrupts(struct rcar_canfd_global *gpriv) ...@@ -739,7 +817,8 @@ static void rcar_canfd_enable_global_interrupts(struct rcar_canfd_global *gpriv)
/* Global interrupts setup */ /* Global interrupts setup */
ctr = RCANFD_GCTR_MEIE; ctr = RCANFD_GCTR_MEIE;
ctr |= RCANFD_GCTR_CFMPOFIE; if (gpriv->fdmode)
ctr |= RCANFD_GCTR_CFMPOFIE;
rcar_canfd_set_bit(gpriv->base, RCANFD_GCTR, ctr); rcar_canfd_set_bit(gpriv->base, RCANFD_GCTR, ctr);
} }
...@@ -790,6 +869,7 @@ static void rcar_canfd_disable_channel_interrupts(struct rcar_canfd_channel ...@@ -790,6 +869,7 @@ static void rcar_canfd_disable_channel_interrupts(struct rcar_canfd_channel
static void rcar_canfd_global_error(struct net_device *ndev) static void rcar_canfd_global_error(struct net_device *ndev)
{ {
struct rcar_canfd_channel *priv = netdev_priv(ndev); struct rcar_canfd_channel *priv = netdev_priv(ndev);
struct rcar_canfd_global *gpriv = priv->gpriv;
struct net_device_stats *stats = &ndev->stats; struct net_device_stats *stats = &ndev->stats;
u32 ch = priv->channel; u32 ch = priv->channel;
u32 gerfl, sts; u32 gerfl, sts;
...@@ -823,7 +903,7 @@ static void rcar_canfd_global_error(struct net_device *ndev) ...@@ -823,7 +903,7 @@ static void rcar_canfd_global_error(struct net_device *ndev)
sts & ~RCANFD_RFSTS_RFMLT); sts & ~RCANFD_RFSTS_RFMLT);
} }
} }
if (gerfl & RCANFD_GERFL_CMPOF) { if (gpriv->fdmode && gerfl & RCANFD_GERFL_CMPOF) {
/* Message Lost flag will be set for respective channel /* Message Lost flag will be set for respective channel
* when this condition happens with counters and flags * when this condition happens with counters and flags
* already updated. * already updated.
...@@ -837,16 +917,17 @@ static void rcar_canfd_global_error(struct net_device *ndev) ...@@ -837,16 +917,17 @@ static void rcar_canfd_global_error(struct net_device *ndev)
rcar_canfd_write(priv->base, RCANFD_GERFL, 0); rcar_canfd_write(priv->base, RCANFD_GERFL, 0);
} }
static void rcar_canfd_error(struct net_device *ndev) static void rcar_canfd_error(struct net_device *ndev, u32 cerfl,
u16 txerr, u16 rxerr)
{ {
struct rcar_canfd_channel *priv = netdev_priv(ndev); struct rcar_canfd_channel *priv = netdev_priv(ndev);
struct net_device_stats *stats = &ndev->stats; struct net_device_stats *stats = &ndev->stats;
struct can_frame *cf; struct can_frame *cf;
struct sk_buff *skb; struct sk_buff *skb;
u32 cerfl, csts;
u32 txerr = 0, rxerr = 0;
u32 ch = priv->channel; u32 ch = priv->channel;
netdev_dbg(ndev, "ch erfl %x txerr %u rxerr %u\n", cerfl, txerr, rxerr);
/* Propagate the error condition to the CAN stack */ /* Propagate the error condition to the CAN stack */
skb = alloc_can_err_skb(ndev, &cf); skb = alloc_can_err_skb(ndev, &cf);
if (!skb) { if (!skb) {
...@@ -854,15 +935,7 @@ static void rcar_canfd_error(struct net_device *ndev) ...@@ -854,15 +935,7 @@ static void rcar_canfd_error(struct net_device *ndev)
return; return;
} }
/* Channel error interrupt */ /* Channel error interrupts */
cerfl = rcar_canfd_read(priv->base, RCANFD_CERFL(ch));
csts = rcar_canfd_read(priv->base, RCANFD_CSTS(ch));
txerr = RCANFD_CSTS_TECCNT(csts);
rxerr = RCANFD_CSTS_RECCNT(csts);
netdev_dbg(ndev, "ch erfl %x sts %x txerr %u rxerr %u\n",
cerfl, csts, txerr, rxerr);
if (cerfl & RCANFD_CERFL_BEF) { if (cerfl & RCANFD_CERFL_BEF) {
netdev_dbg(ndev, "Bus error\n"); netdev_dbg(ndev, "Bus error\n");
cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_PROT; cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_PROT;
...@@ -952,8 +1025,9 @@ static void rcar_canfd_error(struct net_device *ndev) ...@@ -952,8 +1025,9 @@ static void rcar_canfd_error(struct net_device *ndev)
cf->data[2] |= CAN_ERR_PROT_OVERLOAD; cf->data[2] |= CAN_ERR_PROT_OVERLOAD;
} }
/* Clear all channel error interrupts */ /* Clear channel error interrupts that are handled */
rcar_canfd_write(priv->base, RCANFD_CERFL(ch), 0); rcar_canfd_write(priv->base, RCANFD_CERFL(ch),
RCANFD_CERFL_ERR(~cerfl));
stats->rx_packets++; stats->rx_packets++;
stats->rx_bytes += cf->can_dlc; stats->rx_bytes += cf->can_dlc;
netif_rx(skb); netif_rx(skb);
...@@ -1018,12 +1092,12 @@ static irqreturn_t rcar_canfd_global_interrupt(int irq, void *dev_id) ...@@ -1018,12 +1092,12 @@ static irqreturn_t rcar_canfd_global_interrupt(int irq, void *dev_id)
/* Global error interrupts */ /* Global error interrupts */
gerfl = rcar_canfd_read(priv->base, RCANFD_GERFL); gerfl = rcar_canfd_read(priv->base, RCANFD_GERFL);
if (RCANFD_GERFL_ERR(gerfl)) if (unlikely(RCANFD_GERFL_ERR(gpriv, gerfl)))
rcar_canfd_global_error(ndev); rcar_canfd_global_error(ndev);
/* Handle Rx interrupts */ /* Handle Rx interrupts */
sts = rcar_canfd_read(priv->base, RCANFD_RFSTS(ridx)); sts = rcar_canfd_read(priv->base, RCANFD_RFSTS(ridx));
if (sts & RCANFD_RFSTS_RFIF) { if (likely(sts & RCANFD_RFSTS_RFIF)) {
if (napi_schedule_prep(&priv->napi)) { if (napi_schedule_prep(&priv->napi)) {
/* Disable Rx FIFO interrupts */ /* Disable Rx FIFO interrupts */
rcar_canfd_clear_bit(priv->base, rcar_canfd_clear_bit(priv->base,
...@@ -1036,12 +1110,46 @@ static irqreturn_t rcar_canfd_global_interrupt(int irq, void *dev_id) ...@@ -1036,12 +1110,46 @@ static irqreturn_t rcar_canfd_global_interrupt(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static void rcar_canfd_state_change(struct net_device *ndev,
u16 txerr, u16 rxerr)
{
struct rcar_canfd_channel *priv = netdev_priv(ndev);
struct net_device_stats *stats = &ndev->stats;
enum can_state rx_state, tx_state, state = priv->can.state;
struct can_frame *cf;
struct sk_buff *skb;
/* Handle transition from error to normal states */
if (txerr < 96 && rxerr < 96)
state = CAN_STATE_ERROR_ACTIVE;
else if (txerr < 128 && rxerr < 128)
state = CAN_STATE_ERROR_WARNING;
if (state != priv->can.state) {
netdev_dbg(ndev, "state: new %d, old %d: txerr %u, rxerr %u\n",
state, priv->can.state, txerr, rxerr);
skb = alloc_can_err_skb(ndev, &cf);
if (!skb) {
stats->rx_dropped++;
return;
}
tx_state = txerr >= rxerr ? state : 0;
rx_state = txerr <= rxerr ? state : 0;
can_change_state(ndev, cf, tx_state, rx_state);
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
netif_rx(skb);
}
}
static irqreturn_t rcar_canfd_channel_interrupt(int irq, void *dev_id) static irqreturn_t rcar_canfd_channel_interrupt(int irq, void *dev_id)
{ {
struct rcar_canfd_global *gpriv = dev_id; struct rcar_canfd_global *gpriv = dev_id;
struct net_device *ndev; struct net_device *ndev;
struct rcar_canfd_channel *priv; struct rcar_canfd_channel *priv;
u32 sts, cerfl, ch; u32 sts, ch, cerfl;
u16 txerr, rxerr;
/* Common FIFO is a per channel resource */ /* Common FIFO is a per channel resource */
for_each_set_bit(ch, &gpriv->channels_mask, RCANFD_NUM_CHANNELS) { for_each_set_bit(ch, &gpriv->channels_mask, RCANFD_NUM_CHANNELS) {
...@@ -1050,13 +1158,21 @@ static irqreturn_t rcar_canfd_channel_interrupt(int irq, void *dev_id) ...@@ -1050,13 +1158,21 @@ static irqreturn_t rcar_canfd_channel_interrupt(int irq, void *dev_id)
/* Channel error interrupts */ /* Channel error interrupts */
cerfl = rcar_canfd_read(priv->base, RCANFD_CERFL(ch)); cerfl = rcar_canfd_read(priv->base, RCANFD_CERFL(ch));
if (RCANFD_CERFL_ERR(cerfl)) sts = rcar_canfd_read(priv->base, RCANFD_CSTS(ch));
rcar_canfd_error(ndev); txerr = RCANFD_CSTS_TECCNT(sts);
rxerr = RCANFD_CSTS_RECCNT(sts);
if (unlikely(RCANFD_CERFL_ERR(cerfl)))
rcar_canfd_error(ndev, cerfl, txerr, rxerr);
/* Handle state change to lower states */
if (unlikely((priv->can.state != CAN_STATE_ERROR_ACTIVE) &&
(priv->can.state != CAN_STATE_BUS_OFF)))
rcar_canfd_state_change(ndev, txerr, rxerr);
/* Handle Tx interrupts */ /* Handle Tx interrupts */
sts = rcar_canfd_read(priv->base, sts = rcar_canfd_read(priv->base,
RCANFD_CFSTS(ch, RCANFD_CFFIFO_IDX)); RCANFD_CFSTS(ch, RCANFD_CFFIFO_IDX));
if (sts & RCANFD_CFSTS_CFTXIF) if (likely(sts & RCANFD_CFSTS_CFTXIF))
rcar_canfd_tx_done(ndev); rcar_canfd_tx_done(ndev);
} }
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -1077,25 +1193,37 @@ static void rcar_canfd_set_bittiming(struct net_device *dev) ...@@ -1077,25 +1193,37 @@ static void rcar_canfd_set_bittiming(struct net_device *dev)
tseg1 = bt->prop_seg + bt->phase_seg1 - 1; tseg1 = bt->prop_seg + bt->phase_seg1 - 1;
tseg2 = bt->phase_seg2 - 1; tseg2 = bt->phase_seg2 - 1;
cfg = (RCANFD_NCFG_NTSEG1(tseg1) | RCANFD_NCFG_NBRP(brp) | if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
RCANFD_NCFG_NSJW(sjw) | RCANFD_NCFG_NTSEG2(tseg2)); /* CAN FD only mode */
cfg = (RCANFD_NCFG_NTSEG1(tseg1) | RCANFD_NCFG_NBRP(brp) |
RCANFD_NCFG_NSJW(sjw) | RCANFD_NCFG_NTSEG2(tseg2));
rcar_canfd_write(priv->base, RCANFD_CCFG(ch), cfg); rcar_canfd_write(priv->base, RCANFD_CCFG(ch), cfg);
netdev_dbg(priv->ndev, "nrate: brp %u, sjw %u, tseg1 %u, tseg2 %u\n", netdev_dbg(priv->ndev, "nrate: brp %u, sjw %u, tseg1 %u, tseg2 %u\n",
brp, sjw, tseg1, tseg2); brp, sjw, tseg1, tseg2);
/* Data bit timing settings */ /* Data bit timing settings */
brp = dbt->brp - 1; brp = dbt->brp - 1;
sjw = dbt->sjw - 1; sjw = dbt->sjw - 1;
tseg1 = dbt->prop_seg + dbt->phase_seg1 - 1; tseg1 = dbt->prop_seg + dbt->phase_seg1 - 1;
tseg2 = dbt->phase_seg2 - 1; tseg2 = dbt->phase_seg2 - 1;
cfg = (RCANFD_DCFG_DTSEG1(tseg1) | RCANFD_DCFG_DBRP(brp) | cfg = (RCANFD_DCFG_DTSEG1(tseg1) | RCANFD_DCFG_DBRP(brp) |
RCANFD_DCFG_DSJW(sjw) | RCANFD_DCFG_DTSEG2(tseg2)); RCANFD_DCFG_DSJW(sjw) | RCANFD_DCFG_DTSEG2(tseg2));
rcar_canfd_write(priv->base, RCANFD_F_DCFG(ch), cfg); rcar_canfd_write(priv->base, RCANFD_F_DCFG(ch), cfg);
netdev_dbg(priv->ndev, "drate: brp %u, sjw %u, tseg1 %u, tseg2 %u\n", netdev_dbg(priv->ndev, "drate: brp %u, sjw %u, tseg1 %u, tseg2 %u\n",
brp, sjw, tseg1, tseg2); brp, sjw, tseg1, tseg2);
} else {
/* Classical CAN only mode */
cfg = (RCANFD_CFG_TSEG1(tseg1) | RCANFD_CFG_BRP(brp) |
RCANFD_CFG_SJW(sjw) | RCANFD_CFG_TSEG2(tseg2));
rcar_canfd_write(priv->base, RCANFD_CCFG(ch), cfg);
netdev_dbg(priv->ndev,
"rate: brp %u, sjw %u, tseg1 %u, tseg2 %u\n",
brp, sjw, tseg1, tseg2);
}
} }
static int rcar_canfd_start(struct net_device *ndev) static int rcar_canfd_start(struct net_device *ndev)
...@@ -1233,27 +1361,37 @@ static netdev_tx_t rcar_canfd_start_xmit(struct sk_buff *skb, ...@@ -1233,27 +1361,37 @@ static netdev_tx_t rcar_canfd_start_xmit(struct sk_buff *skb,
if (cf->can_id & CAN_RTR_FLAG) if (cf->can_id & CAN_RTR_FLAG)
id |= RCANFD_CFID_CFRTR; id |= RCANFD_CFID_CFRTR;
rcar_canfd_write(priv->base,
RCANFD_F_CFID(ch, RCANFD_CFFIFO_IDX), id);
dlc = RCANFD_CFPTR_CFDLC(can_len2dlc(cf->len)); dlc = RCANFD_CFPTR_CFDLC(can_len2dlc(cf->len));
rcar_canfd_write(priv->base,
RCANFD_F_CFPTR(ch, RCANFD_CFFIFO_IDX), dlc);
if (can_is_canfd_skb(skb)) { if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
/* CAN FD frame format */ rcar_canfd_write(priv->base,
sts |= RCANFD_CFFDCSTS_CFFDF; RCANFD_F_CFID(ch, RCANFD_CFFIFO_IDX), id);
if (cf->flags & CANFD_BRS) rcar_canfd_write(priv->base,
sts |= RCANFD_CFFDCSTS_CFBRS; RCANFD_F_CFPTR(ch, RCANFD_CFFIFO_IDX), dlc);
if (priv->can.state == CAN_STATE_ERROR_PASSIVE) if (can_is_canfd_skb(skb)) {
sts |= RCANFD_CFFDCSTS_CFESI; /* CAN FD frame format */
} sts |= RCANFD_CFFDCSTS_CFFDF;
if (cf->flags & CANFD_BRS)
sts |= RCANFD_CFFDCSTS_CFBRS;
if (priv->can.state == CAN_STATE_ERROR_PASSIVE)
sts |= RCANFD_CFFDCSTS_CFESI;
}
rcar_canfd_write(priv->base, RCANFD_F_CFFDCSTS(ch, RCANFD_CFFIFO_IDX), rcar_canfd_write(priv->base,
sts); RCANFD_F_CFFDCSTS(ch, RCANFD_CFFIFO_IDX), sts);
rcar_canfd_put_data(priv, cf, rcar_canfd_put_data(priv, cf,
RCANFD_F_CFDF(ch, RCANFD_CFFIFO_IDX, 0)); RCANFD_F_CFDF(ch, RCANFD_CFFIFO_IDX, 0));
} else {
rcar_canfd_write(priv->base,
RCANFD_C_CFID(ch, RCANFD_CFFIFO_IDX), id);
rcar_canfd_write(priv->base,
RCANFD_C_CFPTR(ch, RCANFD_CFFIFO_IDX), dlc);
rcar_canfd_put_data(priv, cf,
RCANFD_C_CFDF(ch, RCANFD_CFFIFO_IDX, 0));
}
priv->tx_len[priv->tx_head % RCANFD_FIFO_DEPTH] = cf->len; priv->tx_len[priv->tx_head % RCANFD_FIFO_DEPTH] = cf->len;
can_put_echo_skb(skb, ndev, priv->tx_head % RCANFD_FIFO_DEPTH); can_put_echo_skb(skb, ndev, priv->tx_head % RCANFD_FIFO_DEPTH);
...@@ -1280,47 +1418,61 @@ static void rcar_canfd_rx_pkt(struct rcar_canfd_channel *priv) ...@@ -1280,47 +1418,61 @@ static void rcar_canfd_rx_pkt(struct rcar_canfd_channel *priv)
struct net_device_stats *stats = &priv->ndev->stats; struct net_device_stats *stats = &priv->ndev->stats;
struct canfd_frame *cf; struct canfd_frame *cf;
struct sk_buff *skb; struct sk_buff *skb;
u32 sts = 0, id, ptr; u32 sts = 0, id, dlc;
u32 ch = priv->channel; u32 ch = priv->channel;
u32 ridx = ch + RCANFD_RFFIFO_IDX; u32 ridx = ch + RCANFD_RFFIFO_IDX;
id = rcar_canfd_read(priv->base, RCANFD_F_RFID(ridx)); if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
ptr = rcar_canfd_read(priv->base, RCANFD_F_RFPTR(ridx)); id = rcar_canfd_read(priv->base, RCANFD_F_RFID(ridx));
dlc = rcar_canfd_read(priv->base, RCANFD_F_RFPTR(ridx));
sts = rcar_canfd_read(priv->base, RCANFD_F_RFFDSTS(ridx)); sts = rcar_canfd_read(priv->base, RCANFD_F_RFFDSTS(ridx));
if (sts & RCANFD_RFFDSTS_RFFDF) if (sts & RCANFD_RFFDSTS_RFFDF)
skb = alloc_canfd_skb(priv->ndev, &cf); skb = alloc_canfd_skb(priv->ndev, &cf);
else else
skb = alloc_can_skb(priv->ndev, skb = alloc_can_skb(priv->ndev,
(struct can_frame **)&cf); (struct can_frame **)&cf);
} else {
id = rcar_canfd_read(priv->base, RCANFD_C_RFID(ridx));
dlc = rcar_canfd_read(priv->base, RCANFD_C_RFPTR(ridx));
skb = alloc_can_skb(priv->ndev, (struct can_frame **)&cf);
}
if (!skb) { if (!skb) {
stats->rx_dropped++; stats->rx_dropped++;
return; return;
} }
if (sts & RCANFD_RFFDSTS_RFFDF)
cf->len = can_dlc2len(RCANFD_RFPTR_RFDLC(ptr));
else
cf->len = get_can_dlc(RCANFD_RFPTR_RFDLC(ptr));
if (sts & RCANFD_RFFDSTS_RFESI) {
cf->flags |= CANFD_ESI;
netdev_dbg(priv->ndev, "ESI Error\n");
}
if (id & RCANFD_RFID_RFIDE) if (id & RCANFD_RFID_RFIDE)
cf->can_id = (id & CAN_EFF_MASK) | CAN_EFF_FLAG; cf->can_id = (id & CAN_EFF_MASK) | CAN_EFF_FLAG;
else else
cf->can_id = id & CAN_SFF_MASK; cf->can_id = id & CAN_SFF_MASK;
if (!(sts & RCANFD_RFFDSTS_RFFDF) && (id & RCANFD_RFID_RFRTR)) { if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
cf->can_id |= CAN_RTR_FLAG; if (sts & RCANFD_RFFDSTS_RFFDF)
} else { cf->len = can_dlc2len(RCANFD_RFPTR_RFDLC(dlc));
if (sts & RCANFD_RFFDSTS_RFBRS) else
cf->flags |= CANFD_BRS; cf->len = get_can_dlc(RCANFD_RFPTR_RFDLC(dlc));
if (sts & RCANFD_RFFDSTS_RFESI) {
cf->flags |= CANFD_ESI;
netdev_dbg(priv->ndev, "ESI Error\n");
}
rcar_canfd_get_data(priv, cf, RCANFD_F_RFDF(ridx, 0)); if (!(sts & RCANFD_RFFDSTS_RFFDF) && (id & RCANFD_RFID_RFRTR)) {
cf->can_id |= CAN_RTR_FLAG;
} else {
if (sts & RCANFD_RFFDSTS_RFBRS)
cf->flags |= CANFD_BRS;
rcar_canfd_get_data(priv, cf, RCANFD_F_RFDF(ridx, 0));
}
} else {
cf->len = get_can_dlc(RCANFD_RFPTR_RFDLC(dlc));
if (id & RCANFD_RFID_RFRTR)
cf->can_id |= CAN_RTR_FLAG;
else
rcar_canfd_get_data(priv, cf, RCANFD_C_RFDF(ridx, 0));
} }
/* Write 0xff to RFPC to increment the CPU-side /* Write 0xff to RFPC to increment the CPU-side
...@@ -1428,13 +1580,19 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch, ...@@ -1428,13 +1580,19 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch,
priv->can.clock.freq = fcan_freq; priv->can.clock.freq = fcan_freq;
dev_info(&pdev->dev, "can_clk rate is %u\n", priv->can.clock.freq); dev_info(&pdev->dev, "can_clk rate is %u\n", priv->can.clock.freq);
priv->can.bittiming_const = &rcar_canfd_nom_bittiming_const; if (gpriv->fdmode) {
priv->can.data_bittiming_const = priv->can.bittiming_const = &rcar_canfd_nom_bittiming_const;
&rcar_canfd_data_bittiming_const; priv->can.data_bittiming_const =
&rcar_canfd_data_bittiming_const;
/* Controller starts in CAN FD only mode */ /* Controller starts in CAN FD only mode */
can_set_static_ctrlmode(ndev, CAN_CTRLMODE_FD); can_set_static_ctrlmode(ndev, CAN_CTRLMODE_FD);
priv->can.ctrlmode_supported = CAN_CTRLMODE_BERR_REPORTING; priv->can.ctrlmode_supported = CAN_CTRLMODE_BERR_REPORTING;
} else {
/* Controller starts in Classical CAN only mode */
priv->can.bittiming_const = &rcar_canfd_bittiming_const;
priv->can.ctrlmode_supported = CAN_CTRLMODE_BERR_REPORTING;
}
priv->can.do_set_mode = rcar_canfd_do_set_mode; priv->can.do_set_mode = rcar_canfd_do_set_mode;
priv->can.do_get_berr_counter = rcar_canfd_get_berr_counter; priv->can.do_get_berr_counter = rcar_canfd_get_berr_counter;
...@@ -1482,6 +1640,10 @@ static int rcar_canfd_probe(struct platform_device *pdev) ...@@ -1482,6 +1640,10 @@ static int rcar_canfd_probe(struct platform_device *pdev)
struct device_node *of_child; struct device_node *of_child;
unsigned long channels_mask = 0; unsigned long channels_mask = 0;
int err, ch_irq, g_irq; int err, ch_irq, g_irq;
bool fdmode = true; /* CAN FD only mode - default */
if (of_property_read_bool(pdev->dev.of_node, "renesas,no-can-fd"))
fdmode = false; /* Classical CAN only mode */
of_child = of_get_child_by_name(pdev->dev.of_node, "channel0"); of_child = of_get_child_by_name(pdev->dev.of_node, "channel0");
if (of_child && of_device_is_available(of_child)) if (of_child && of_device_is_available(of_child))
...@@ -1513,6 +1675,7 @@ static int rcar_canfd_probe(struct platform_device *pdev) ...@@ -1513,6 +1675,7 @@ static int rcar_canfd_probe(struct platform_device *pdev)
} }
gpriv->pdev = pdev; gpriv->pdev = pdev;
gpriv->channels_mask = channels_mask; gpriv->channels_mask = channels_mask;
gpriv->fdmode = fdmode;
/* Peripheral clock */ /* Peripheral clock */
gpriv->clkp = devm_clk_get(&pdev->dev, "fck"); gpriv->clkp = devm_clk_get(&pdev->dev, "fck");
...@@ -1623,8 +1786,8 @@ static int rcar_canfd_probe(struct platform_device *pdev) ...@@ -1623,8 +1786,8 @@ static int rcar_canfd_probe(struct platform_device *pdev)
} }
platform_set_drvdata(pdev, gpriv); platform_set_drvdata(pdev, gpriv);
dev_info(&pdev->dev, "global operational state (clk %d)\n", dev_info(&pdev->dev, "global operational state (clk %d, fdmode %d)\n",
gpriv->fcan); gpriv->fcan, gpriv->fdmode);
return 0; return 0;
fail_channel: fail_channel:
......
...@@ -1145,8 +1145,11 @@ static int mcp251x_can_probe(struct spi_device *spi) ...@@ -1145,8 +1145,11 @@ static int mcp251x_can_probe(struct spi_device *spi)
/* Here is OK to not lock the MCP, no one knows about it yet */ /* Here is OK to not lock the MCP, no one knows about it yet */
ret = mcp251x_hw_probe(spi); ret = mcp251x_hw_probe(spi);
if (ret) if (ret) {
if (ret == -ENODEV)
dev_err(&spi->dev, "Cannot initialize MCP%x. Wrong wiring?\n", priv->model);
goto error_probe; goto error_probe;
}
mcp251x_hw_sleep(spi); mcp251x_hw_sleep(spi);
...@@ -1156,6 +1159,7 @@ static int mcp251x_can_probe(struct spi_device *spi) ...@@ -1156,6 +1159,7 @@ static int mcp251x_can_probe(struct spi_device *spi)
devm_can_led_init(net); devm_can_led_init(net);
netdev_info(net, "MCP%x successfully initialized.\n", priv->model);
return 0; return 0;
error_probe: error_probe:
...@@ -1168,6 +1172,7 @@ static int mcp251x_can_probe(struct spi_device *spi) ...@@ -1168,6 +1172,7 @@ static int mcp251x_can_probe(struct spi_device *spi)
out_free: out_free:
free_candev(net); free_candev(net);
dev_err(&spi->dev, "Probe failed, err=%d\n", -ret);
return ret; return ret;
} }
......
...@@ -911,14 +911,14 @@ static __init int can_init(void) ...@@ -911,14 +911,14 @@ static __init int can_init(void)
if (!rcv_cache) if (!rcv_cache)
return -ENOMEM; return -ENOMEM;
if (stats_timer) { if (IS_ENABLED(CONFIG_PROC_FS)) {
if (stats_timer) {
/* the statistics are updated every second (timer triggered) */ /* the statistics are updated every second (timer triggered) */
setup_timer(&can_stattimer, can_stat_update, 0); setup_timer(&can_stattimer, can_stat_update, 0);
mod_timer(&can_stattimer, round_jiffies(jiffies + HZ)); mod_timer(&can_stattimer, round_jiffies(jiffies + HZ));
} else }
can_stattimer.function = NULL; can_init_proc();
}
can_init_proc();
/* protocol register */ /* protocol register */
sock_register(&can_family_ops); sock_register(&can_family_ops);
...@@ -933,10 +933,12 @@ static __exit void can_exit(void) ...@@ -933,10 +933,12 @@ static __exit void can_exit(void)
{ {
struct net_device *dev; struct net_device *dev;
if (stats_timer) if (IS_ENABLED(CONFIG_PROC_FS)) {
del_timer_sync(&can_stattimer); if (stats_timer)
del_timer_sync(&can_stattimer);
can_remove_proc(); can_remove_proc();
}
/* protocol unregister */ /* protocol unregister */
dev_remove_pack(&canfd_packet); dev_remove_pack(&canfd_packet);
......
...@@ -113,19 +113,8 @@ struct s_pstats { ...@@ -113,19 +113,8 @@ struct s_pstats {
extern struct dev_rcv_lists can_rx_alldev_list; extern struct dev_rcv_lists can_rx_alldev_list;
/* function prototypes for the CAN networklayer procfs (proc.c) */ /* function prototypes for the CAN networklayer procfs (proc.c) */
#ifdef CONFIG_PROC_FS
void can_init_proc(void); void can_init_proc(void);
void can_remove_proc(void); void can_remove_proc(void);
#else
static inline void can_init_proc(void)
{
pr_info("can: Can't create /proc/net/can. CONFIG_PROC_FS missing!\n");
}
static inline void can_remove_proc(void)
{
}
#endif
void can_stat_update(unsigned long data); void can_stat_update(unsigned long data);
/* structures and variables from af_can.c needed in proc.c for reading */ /* structures and variables from af_can.c needed in proc.c for reading */
......
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