1
0
Fork 0

linux-can-next-for-4.8-20160623

-----BEGIN PGP SIGNATURE-----
 
 iQEcBAABCgAGBQJXa6rGAAoJED07qiWsqSVqzwsH/0g/blikQuNNAB7LzXGTEMn8
 ipWCODaYxgWE/V/1A0JjsKpxB1ZL3HE0/xg/OmZ10SRNlz5LJTLkoYZa7xYmyxtT
 a89mT9vdnWxwfwbeIhSSjG9W9g44vqrhMIPxffIu5yqSqdIJak0HIiuQizJ0/xjx
 xQVx4AykWKQ3u0/Tiyz3ez5yhyMMNEmHxKyDWpgrR6+zXlofwP/Em3NFPwk9gh32
 ECAagOUOEvdjXeRs1Yn/CV0FC7Wgs4Hzr048JJ5wOteawBLr+sPOnuWZtDhNrwDK
 Eceh7aEeAiFfIW+jCMEe5qrpFHi8hqyqBo4L9TDYsE7T/Z6BPyh+5OUh8+5dtaw=
 =TZew
 -----END PGP SIGNATURE-----

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: David S. Miller <davem@davemloft.net>
hifive-unleashed-5.1
David S. Miller 2016-06-27 10:33:42 -04:00
commit 5db15872c5
5 changed files with 329 additions and 163 deletions

View File

@ -32,6 +32,12 @@ below properties.
- assigned-clocks: phandle of canfd 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
-------
@ -63,12 +69,13 @@ SoC common .dtsi 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 {
pinctrl-0 = <&canfd1_pins>;
pinctrl-names = "default";
status = "okay";
pinctrl-0 = <&canfd1_pins>;
pinctrl-names = "default";
renesas,no-can-fd;
status = "okay";
channel1 {
status = "okay";
@ -79,9 +86,9 @@ E.g. below enables Channel 0 alone in the board using External clock
as fCAN clock.
&canfd {
pinctrl-0 = <&canfd0_pins &can_clk_pins>;
pinctrl-names = "default";
status = "okay";
pinctrl-0 = <&canfd0_pins &can_clk_pins>;
pinctrl-names = "default";
status = "okay";
channel0 {
status = "okay";

View File

@ -16,8 +16,9 @@
* mode, the controller acts as a CAN FD node that can also interoperate with
* CAN 2.0 nodes.
*
* As of now, this driver does not support the Classical CAN (CAN 2.0) mode,
* which is handled by a different register map compared to CAN FD only mode.
* To switch the controller to Classical CAN (CAN 2.0) only mode, add
* "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
* to use as it is in the driver. However, those names are added as comments
@ -48,15 +49,16 @@
/* RSCFDnCFDGRMCFG */
#define RCANFD_GRMCFG_RCMC BIT(0)
/* RSCFDnCFDGCFG */
#define RCANFD_GCFG_CMPOC BIT(5)
/* RSCFDnCFDGCFG / RSCFDnGCFG */
#define RCANFD_GCFG_EEFE BIT(6)
#define RCANFD_GCFG_CMPOC BIT(5) /* CAN FD only */
#define RCANFD_GCFG_DCS BIT(4)
#define RCANFD_GCFG_DCE BIT(1)
#define RCANFD_GCFG_TPRI BIT(0)
/* RSCFDnCFDGCTR */
/* RSCFDnCFDGCTR / RSCFDnGCTR */
#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_MEIE BIT(9)
#define RCANFD_GCTR_DEIE BIT(8)
@ -66,7 +68,7 @@
#define RCANFD_GCTR_GMDC_GRESET (0x1)
#define RCANFD_GCTR_GMDC_GTEST (0x2)
/* RSCFDnCFDGSTS */
/* RSCFDnCFDGSTS / RSCFDnGSTS */
#define RCANFD_GSTS_GRAMINIT BIT(3)
#define RCANFD_GSTS_GSLPSTS BIT(2)
#define RCANFD_GSTS_GHLTSTS BIT(1)
@ -74,44 +76,50 @@
/* Non-operational status */
#define RCANFD_GSTS_GNOPM (BIT(0) | BIT(1) | BIT(2) | BIT(3))
/* RSCFDnCFDGERFL */
/* RSCFDnCFDGERFL / RSCFDnGERFL */
#define RCANFD_GERFL_EEF1 BIT(17)
#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_MES BIT(1)
#define RCANFD_GERFL_DEF BIT(0)
#define RCANFD_GERFL_ERR(x) ((x) & (RCANFD_GERFL_EEF1 |\
RCANFD_GERFL_EEF0 |\
RCANFD_GERFL_MES |\
RCANFD_GERFL_CMPOF))
#define RCANFD_GERFL_ERR(gpriv, x) ((x) & (RCANFD_GERFL_EEF1 |\
RCANFD_GERFL_EEF0 | RCANFD_GERFL_MES |\
(gpriv->fdmode ?\
RCANFD_GERFL_CMPOF : 0)))
/* AFL Rx rules registers */
/* RSCFDnCFDGAFLCFG0 */
/* RSCFDnCFDGAFLCFG0 / RSCFDnGAFLCFG0 */
#define RCANFD_GAFLCFG_SETRNC(n, x) (((x) & 0xff) << (24 - n * 8))
#define RCANFD_GAFLCFG_GETRNC(n, x) (((x) >> (24 - n * 8)) & 0xff)
/* RSCFDnCFDGAFLECTR */
/* RSCFDnCFDGAFLECTR / RSCFDnGAFLECTR */
#define RCANFD_GAFLECTR_AFLDAE BIT(8)
#define RCANFD_GAFLECTR_AFLPN(x) ((x) & 0x1f)
/* RSCFDnCFDGAFLIDj */
/* RSCFDnCFDGAFLIDj / RSCFDnGAFLIDj */
#define RCANFD_GAFLID_GAFLLB BIT(29)
/* RSCFDnCFDGAFLP1_j */
/* RSCFDnCFDGAFLP1_j / RSCFDnGAFLP1_j */
#define RCANFD_GAFLP1_GAFLFDP(x) (1 << (x))
/* 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_NTSEG1(x) (((x) & 0x7f) << 16)
#define RCANFD_NCFG_NSJW(x) (((x) & 0x1f) << 11)
#define RCANFD_NCFG_NBRP(x) (((x) & 0x3ff) << 0)
/* RSCFDnCFDCmCTR */
/* RSCFDnCFDCmCTR / RSCFDnCmCTR */
#define RCANFD_CCTR_CTME BIT(24)
#define RCANFD_CCTR_ERRD BIT(23)
#define RCANFD_CCTR_BOM_MASK (0x3 << 21)
@ -136,7 +144,7 @@
#define RCANFD_CCTR_CHDMC_CRESET (0x1)
#define RCANFD_CCTR_CHDMC_CHLT (0x2)
/* RSCFDnCFDCmSTS */
/* RSCFDnCFDCmSTS / RSCFDnCmSTS */
#define RCANFD_CSTS_COMSTS BIT(7)
#define RCANFD_CSTS_RECSTS BIT(6)
#define RCANFD_CSTS_TRMSTS BIT(5)
@ -149,7 +157,7 @@
#define RCANFD_CSTS_TECCNT(x) (((x) >> 24) & 0xff)
#define RCANFD_CSTS_RECCNT(x) (((x) >> 16) & 0xff)
/* RSCFDnCFDCmERFL */
/* RSCFDnCFDCmERFL / RSCFDnCmERFL */
#define RCANFD_CERFL_ADERR BIT(14)
#define RCANFD_CERFL_B0ERR BIT(13)
#define RCANFD_CERFL_B1ERR BIT(12)
@ -239,14 +247,14 @@
#define RCANFD_CFFDCSTS_CFBRS BIT(1)
#define RCANFD_CFFDCSTS_CFESI BIT(0)
/* This controller supports classical CAN only mode or CAN FD only mode. These
* modes are supported in two separate set of register maps & names. However,
* some of the register offsets are common for both modes. Those offsets are
* listed below as Common registers.
/* This controller supports either Classical CAN only mode or CAN FD only mode.
* These modes are supported in two separate set of register maps & names.
* However, some of the register offsets are common for both modes. Those
* offsets are listed below as Common registers.
*
* The CAN FD only specific registers are listed separately and their names
* starts with RCANFD_F_xxx names. When classical CAN only specific registers
* are added, those specific registers can be prefixed as RCANFD_C_xxx.
* The CAN FD only mode specific registers & Classical CAN only mode specific
* registers are listed separately. Their register names starts with
* RCANFD_F_xxx & RCANFD_C_xxx respectively.
*/
/* Common registers */
@ -353,7 +361,7 @@
#define RCANFD_GTSTCTR (0x046c)
/* RSCFDnCFDGLOCKK / RSCFDnGLOCKK */
#define RCANFD_GLOCKK (0x047c)
/* RSCFDnCFDGRMCFG / RSCFDnGRMCFG */
/* RSCFDnCFDGRMCFG */
#define RCANFD_GRMCFG (0x04fc)
/* RSCFDnCFDGAFLIDj / RSCFDnGAFLIDj */
@ -365,6 +373,46 @@
/* RSCFDnCFDGAFLP1j / RSCFDnGAFLP1j */
#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 */
/* RSCFDnCFDCmXXX -> RCANFD_F_XXX(m) */
@ -468,6 +516,7 @@ struct rcar_canfd_global {
struct clk *can_clk; /* fCAN clock */
enum rcar_canfd_fcanclk fcan; /* CANFD or Ext clock */
unsigned long channels_mask; /* Enabled channels mask */
bool fdmode; /* CAN FD or Classical CAN only mode */
};
/* CAN FD mode nominal rate constants */
@ -496,6 +545,19 @@ static const struct can_bittiming_const rcar_canfd_data_bittiming_const = {
.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 */
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)
/* Reset Global error flags */
rcar_canfd_write(gpriv->base, RCANFD_GERFL, 0x0);
/* Set the controller into FD mode */
rcar_canfd_set_bit(gpriv->base, RCANFD_GRMCFG, RCANFD_GRMCFG_RCMC);
/* Set the controller into appropriate mode */
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 */
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)
/* Global configuration settings */
/* Truncate payload to configured message size RFPLS */
cfg = RCANFD_GCFG_CMPOC;
/* ECC Error flag Enable */
cfg = RCANFD_GCFG_EEFE;
if (gpriv->fdmode)
/* Truncate payload to configured message size RFPLS */
cfg |= RCANFD_GCFG_CMPOC;
/* Set External Clock if selected */
if (gpriv->fcan != RCANFD_CANFDCLK)
@ -647,7 +718,7 @@ static void rcar_canfd_configure_afl_rules(struct rcar_canfd_global *gpriv,
u32 ch)
{
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;
if (ch == 0) {
@ -667,19 +738,19 @@ static void rcar_canfd_configure_afl_rules(struct rcar_canfd_global *gpriv,
/* Write number of rules for channel */
rcar_canfd_set_bit(gpriv->base, RCANFD_GAFLCFG0,
RCANFD_GAFLCFG_SETRNC(ch, num_rules));
if (gpriv->fdmode)
offset = RCANFD_F_GAFL_OFFSET;
else
offset = RCANFD_C_GAFL_OFFSET;
/* Accept all IDs */
rcar_canfd_write(gpriv->base,
RCANFD_GAFLID(RCANFD_F_GAFL_OFFSET, start), 0);
rcar_canfd_write(gpriv->base, RCANFD_GAFLID(offset, start), 0);
/* IDE or RTR is not considered for matching */
rcar_canfd_write(gpriv->base,
RCANFD_GAFLM(RCANFD_F_GAFL_OFFSET, start), 0);
rcar_canfd_write(gpriv->base, RCANFD_GAFLM(offset, start), 0);
/* Any data length accepted */
rcar_canfd_write(gpriv->base,
RCANFD_GAFLP0(RCANFD_F_GAFL_OFFSET, start), 0);
rcar_canfd_write(gpriv->base, RCANFD_GAFLP0(offset, start), 0);
/* Place the msg in corresponding Rx FIFO entry */
rcar_canfd_write(gpriv->base,
RCANFD_GAFLP1(RCANFD_F_GAFL_OFFSET, start),
rcar_canfd_write(gpriv->base, RCANFD_GAFLP1(offset, start),
RCANFD_GAFLP1_GAFLFDP(ridx));
/* Disable write access to page */
@ -697,7 +768,10 @@ static void rcar_canfd_configure_rx(struct rcar_canfd_global *gpriv, u32 ch)
u32 ridx = ch + RCANFD_RFFIFO_IDX;
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) |
RCANFD_RFCC_RFPLS(rfpls) | RCANFD_RFCC_RFIE);
@ -718,16 +792,20 @@ static void rcar_canfd_configure_tx(struct rcar_canfd_global *gpriv, u32 ch)
cftml = 0; /* 0th buffer */
cfm = 1; /* b01 - Transmit mode */
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) |
RCANFD_CFCC_CFIM | RCANFD_CFCC_CFDC(cfdc) |
RCANFD_CFCC_CFPLS(cfpls) | RCANFD_CFCC_CFTXIE);
rcar_canfd_write(gpriv->base, RCANFD_CFCC(ch, RCANFD_CFFIFO_IDX), cfg);
/* Clear FD mode specific control/status register */
rcar_canfd_write(gpriv->base,
RCANFD_F_CFFDCSTS(ch, RCANFD_CFFIFO_IDX), 0);
if (gpriv->fdmode)
/* Clear FD mode specific control/status register */
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)
@ -739,7 +817,8 @@ static void rcar_canfd_enable_global_interrupts(struct rcar_canfd_global *gpriv)
/* Global interrupts setup */
ctr = RCANFD_GCTR_MEIE;
ctr |= RCANFD_GCTR_CFMPOFIE;
if (gpriv->fdmode)
ctr |= RCANFD_GCTR_CFMPOFIE;
rcar_canfd_set_bit(gpriv->base, RCANFD_GCTR, ctr);
}
@ -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)
{
struct rcar_canfd_channel *priv = netdev_priv(ndev);
struct rcar_canfd_global *gpriv = priv->gpriv;
struct net_device_stats *stats = &ndev->stats;
u32 ch = priv->channel;
u32 gerfl, sts;
@ -823,7 +903,7 @@ static void rcar_canfd_global_error(struct net_device *ndev)
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
* when this condition happens with counters and flags
* already updated.
@ -837,16 +917,17 @@ static void rcar_canfd_global_error(struct net_device *ndev)
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 net_device_stats *stats = &ndev->stats;
struct can_frame *cf;
struct sk_buff *skb;
u32 cerfl, csts;
u32 txerr = 0, rxerr = 0;
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 */
skb = alloc_can_err_skb(ndev, &cf);
if (!skb) {
@ -854,15 +935,7 @@ static void rcar_canfd_error(struct net_device *ndev)
return;
}
/* Channel error interrupt */
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);
/* Channel error interrupts */
if (cerfl & RCANFD_CERFL_BEF) {
netdev_dbg(ndev, "Bus error\n");
cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_PROT;
@ -952,8 +1025,9 @@ static void rcar_canfd_error(struct net_device *ndev)
cf->data[2] |= CAN_ERR_PROT_OVERLOAD;
}
/* Clear all channel error interrupts */
rcar_canfd_write(priv->base, RCANFD_CERFL(ch), 0);
/* Clear channel error interrupts that are handled */
rcar_canfd_write(priv->base, RCANFD_CERFL(ch),
RCANFD_CERFL_ERR(~cerfl));
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
netif_rx(skb);
@ -1018,12 +1092,12 @@ static irqreturn_t rcar_canfd_global_interrupt(int irq, void *dev_id)
/* Global error interrupts */
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);
/* Handle Rx interrupts */
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)) {
/* Disable Rx FIFO interrupts */
rcar_canfd_clear_bit(priv->base,
@ -1036,12 +1110,46 @@ static irqreturn_t rcar_canfd_global_interrupt(int irq, void *dev_id)
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)
{
struct rcar_canfd_global *gpriv = dev_id;
struct net_device *ndev;
struct rcar_canfd_channel *priv;
u32 sts, cerfl, ch;
u32 sts, ch, cerfl;
u16 txerr, rxerr;
/* Common FIFO is a per channel resource */
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)
/* Channel error interrupts */
cerfl = rcar_canfd_read(priv->base, RCANFD_CERFL(ch));
if (RCANFD_CERFL_ERR(cerfl))
rcar_canfd_error(ndev);
sts = rcar_canfd_read(priv->base, RCANFD_CSTS(ch));
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 */
sts = rcar_canfd_read(priv->base,
RCANFD_CFSTS(ch, RCANFD_CFFIFO_IDX));
if (sts & RCANFD_CFSTS_CFTXIF)
if (likely(sts & RCANFD_CFSTS_CFTXIF))
rcar_canfd_tx_done(ndev);
}
return IRQ_HANDLED;
@ -1077,25 +1193,37 @@ static void rcar_canfd_set_bittiming(struct net_device *dev)
tseg1 = bt->prop_seg + bt->phase_seg1 - 1;
tseg2 = bt->phase_seg2 - 1;
cfg = (RCANFD_NCFG_NTSEG1(tseg1) | RCANFD_NCFG_NBRP(brp) |
RCANFD_NCFG_NSJW(sjw) | RCANFD_NCFG_NTSEG2(tseg2));
if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
/* 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);
netdev_dbg(priv->ndev, "nrate: brp %u, sjw %u, tseg1 %u, tseg2 %u\n",
brp, sjw, tseg1, tseg2);
rcar_canfd_write(priv->base, RCANFD_CCFG(ch), cfg);
netdev_dbg(priv->ndev, "nrate: brp %u, sjw %u, tseg1 %u, tseg2 %u\n",
brp, sjw, tseg1, tseg2);
/* Data bit timing settings */
brp = dbt->brp - 1;
sjw = dbt->sjw - 1;
tseg1 = dbt->prop_seg + dbt->phase_seg1 - 1;
tseg2 = dbt->phase_seg2 - 1;
/* Data bit timing settings */
brp = dbt->brp - 1;
sjw = dbt->sjw - 1;
tseg1 = dbt->prop_seg + dbt->phase_seg1 - 1;
tseg2 = dbt->phase_seg2 - 1;
cfg = (RCANFD_DCFG_DTSEG1(tseg1) | RCANFD_DCFG_DBRP(brp) |
RCANFD_DCFG_DSJW(sjw) | RCANFD_DCFG_DTSEG2(tseg2));
cfg = (RCANFD_DCFG_DTSEG1(tseg1) | RCANFD_DCFG_DBRP(brp) |
RCANFD_DCFG_DSJW(sjw) | RCANFD_DCFG_DTSEG2(tseg2));
rcar_canfd_write(priv->base, RCANFD_F_DCFG(ch), cfg);
netdev_dbg(priv->ndev, "drate: brp %u, sjw %u, tseg1 %u, tseg2 %u\n",
brp, sjw, tseg1, tseg2);
rcar_canfd_write(priv->base, RCANFD_F_DCFG(ch), cfg);
netdev_dbg(priv->ndev, "drate: brp %u, sjw %u, tseg1 %u, tseg2 %u\n",
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)
@ -1233,28 +1361,38 @@ static netdev_tx_t rcar_canfd_start_xmit(struct sk_buff *skb,
if (cf->can_id & CAN_RTR_FLAG)
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));
rcar_canfd_write(priv->base,
RCANFD_F_CFPTR(ch, RCANFD_CFFIFO_IDX), dlc);
if (can_is_canfd_skb(skb)) {
/* CAN FD frame format */
sts |= RCANFD_CFFDCSTS_CFFDF;
if (cf->flags & CANFD_BRS)
sts |= RCANFD_CFFDCSTS_CFBRS;
if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
rcar_canfd_write(priv->base,
RCANFD_F_CFID(ch, RCANFD_CFFIFO_IDX), id);
rcar_canfd_write(priv->base,
RCANFD_F_CFPTR(ch, RCANFD_CFFIFO_IDX), dlc);
if (priv->can.state == CAN_STATE_ERROR_PASSIVE)
sts |= RCANFD_CFFDCSTS_CFESI;
if (can_is_canfd_skb(skb)) {
/* 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), sts);
rcar_canfd_put_data(priv, cf,
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));
}
rcar_canfd_write(priv->base, RCANFD_F_CFFDCSTS(ch, RCANFD_CFFIFO_IDX),
sts);
rcar_canfd_put_data(priv, cf,
RCANFD_F_CFDF(ch, RCANFD_CFFIFO_IDX, 0));
priv->tx_len[priv->tx_head % RCANFD_FIFO_DEPTH] = cf->len;
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)
struct net_device_stats *stats = &priv->ndev->stats;
struct canfd_frame *cf;
struct sk_buff *skb;
u32 sts = 0, id, ptr;
u32 sts = 0, id, dlc;
u32 ch = priv->channel;
u32 ridx = ch + RCANFD_RFFIFO_IDX;
id = rcar_canfd_read(priv->base, RCANFD_F_RFID(ridx));
ptr = rcar_canfd_read(priv->base, RCANFD_F_RFPTR(ridx));
if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
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));
if (sts & RCANFD_RFFDSTS_RFFDF)
skb = alloc_canfd_skb(priv->ndev, &cf);
else
skb = alloc_can_skb(priv->ndev,
(struct can_frame **)&cf);
sts = rcar_canfd_read(priv->base, RCANFD_F_RFFDSTS(ridx));
if (sts & RCANFD_RFFDSTS_RFFDF)
skb = alloc_canfd_skb(priv->ndev, &cf);
else
skb = alloc_can_skb(priv->ndev,
(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) {
stats->rx_dropped++;
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)
cf->can_id = (id & CAN_EFF_MASK) | CAN_EFF_FLAG;
else
cf->can_id = id & CAN_SFF_MASK;
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;
if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
if (sts & RCANFD_RFFDSTS_RFFDF)
cf->len = can_dlc2len(RCANFD_RFPTR_RFDLC(dlc));
else
cf->len = get_can_dlc(RCANFD_RFPTR_RFDLC(dlc));
rcar_canfd_get_data(priv, cf, RCANFD_F_RFDF(ridx, 0));
if (sts & RCANFD_RFFDSTS_RFESI) {
cf->flags |= CANFD_ESI;
netdev_dbg(priv->ndev, "ESI Error\n");
}
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
@ -1428,13 +1580,19 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch,
priv->can.clock.freq = fcan_freq;
dev_info(&pdev->dev, "can_clk rate is %u\n", priv->can.clock.freq);
priv->can.bittiming_const = &rcar_canfd_nom_bittiming_const;
priv->can.data_bittiming_const =
&rcar_canfd_data_bittiming_const;
if (gpriv->fdmode) {
priv->can.bittiming_const = &rcar_canfd_nom_bittiming_const;
priv->can.data_bittiming_const =
&rcar_canfd_data_bittiming_const;
/* Controller starts in CAN FD only mode */
can_set_static_ctrlmode(ndev, CAN_CTRLMODE_FD);
priv->can.ctrlmode_supported = CAN_CTRLMODE_BERR_REPORTING;
/* Controller starts in CAN FD only mode */
can_set_static_ctrlmode(ndev, CAN_CTRLMODE_FD);
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_get_berr_counter = rcar_canfd_get_berr_counter;
@ -1482,6 +1640,10 @@ static int rcar_canfd_probe(struct platform_device *pdev)
struct device_node *of_child;
unsigned long channels_mask = 0;
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");
if (of_child && of_device_is_available(of_child))
@ -1513,6 +1675,7 @@ static int rcar_canfd_probe(struct platform_device *pdev)
}
gpriv->pdev = pdev;
gpriv->channels_mask = channels_mask;
gpriv->fdmode = fdmode;
/* Peripheral clock */
gpriv->clkp = devm_clk_get(&pdev->dev, "fck");
@ -1623,8 +1786,8 @@ static int rcar_canfd_probe(struct platform_device *pdev)
}
platform_set_drvdata(pdev, gpriv);
dev_info(&pdev->dev, "global operational state (clk %d)\n",
gpriv->fcan);
dev_info(&pdev->dev, "global operational state (clk %d, fdmode %d)\n",
gpriv->fcan, gpriv->fdmode);
return 0;
fail_channel:

View File

@ -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 */
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;
}
mcp251x_hw_sleep(spi);
@ -1156,6 +1159,7 @@ static int mcp251x_can_probe(struct spi_device *spi)
devm_can_led_init(net);
netdev_info(net, "MCP%x successfully initialized.\n", priv->model);
return 0;
error_probe:
@ -1168,6 +1172,7 @@ out_clk:
out_free:
free_candev(net);
dev_err(&spi->dev, "Probe failed, err=%d\n", -ret);
return ret;
}

View File

@ -911,14 +911,14 @@ static __init int can_init(void)
if (!rcv_cache)
return -ENOMEM;
if (stats_timer) {
if (IS_ENABLED(CONFIG_PROC_FS)) {
if (stats_timer) {
/* the statistics are updated every second (timer triggered) */
setup_timer(&can_stattimer, can_stat_update, 0);
mod_timer(&can_stattimer, round_jiffies(jiffies + HZ));
} else
can_stattimer.function = NULL;
can_init_proc();
setup_timer(&can_stattimer, can_stat_update, 0);
mod_timer(&can_stattimer, round_jiffies(jiffies + HZ));
}
can_init_proc();
}
/* protocol register */
sock_register(&can_family_ops);
@ -933,10 +933,12 @@ static __exit void can_exit(void)
{
struct net_device *dev;
if (stats_timer)
del_timer_sync(&can_stattimer);
if (IS_ENABLED(CONFIG_PROC_FS)) {
if (stats_timer)
del_timer_sync(&can_stattimer);
can_remove_proc();
can_remove_proc();
}
/* protocol unregister */
dev_remove_pack(&canfd_packet);

View File

@ -113,19 +113,8 @@ struct s_pstats {
extern struct dev_rcv_lists can_rx_alldev_list;
/* function prototypes for the CAN networklayer procfs (proc.c) */
#ifdef CONFIG_PROC_FS
void can_init_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);
/* structures and variables from af_can.c needed in proc.c for reading */