diff options
Diffstat (limited to 'drivers/net/can')
-rw-r--r-- | drivers/net/can/rcar/rcar_canfd.c | 353 | ||||
-rw-r--r-- | drivers/net/can/usb/etas_es58x/es58x_fd.c | 3 | ||||
-rw-r--r-- | drivers/net/can/usb/gs_usb.c | 446 | ||||
-rw-r--r-- | drivers/net/can/vxcan.c | 19 |
4 files changed, 556 insertions, 265 deletions
diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c index acd74725831f..1e121e04208c 100644 --- a/drivers/net/can/rcar/rcar_canfd.c +++ b/drivers/net/can/rcar/rcar_canfd.c @@ -44,6 +44,7 @@ enum rcanfd_chip_id { RENESAS_RCAR_GEN3 = 0, RENESAS_RZG2L, + RENESAS_R8A779A0, }; /* Global register bits */ @@ -79,6 +80,7 @@ enum rcanfd_chip_id { #define RCANFD_GSTS_GNOPM (BIT(0) | BIT(1) | BIT(2) | BIT(3)) /* RSCFDnCFDGERFL / RSCFDnGERFL */ +#define RCANFD_GERFL_EEF0_7 GENMASK(23, 16) #define RCANFD_GERFL_EEF1 BIT(17) #define RCANFD_GERFL_EEF0 BIT(16) #define RCANFD_GERFL_CMPOF BIT(3) /* CAN FD only */ @@ -86,20 +88,26 @@ enum rcanfd_chip_id { #define RCANFD_GERFL_MES BIT(1) #define RCANFD_GERFL_DEF BIT(0) -#define RCANFD_GERFL_ERR(gpriv, x) ((x) & (RCANFD_GERFL_EEF1 |\ - RCANFD_GERFL_EEF0 | RCANFD_GERFL_MES |\ - (gpriv->fdmode ?\ - RCANFD_GERFL_CMPOF : 0))) +#define RCANFD_GERFL_ERR(gpriv, x) \ + ((x) & (reg_v3u(gpriv, RCANFD_GERFL_EEF0_7, \ + RCANFD_GERFL_EEF0 | RCANFD_GERFL_EEF1) | \ + RCANFD_GERFL_MES | \ + ((gpriv)->fdmode ? RCANFD_GERFL_CMPOF : 0))) /* AFL Rx rules registers */ /* RSCFDnCFDGAFLCFG0 / RSCFDnGAFLCFG0 */ -#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_SETRNC(gpriv, n, x) \ + (((x) & reg_v3u(gpriv, 0x1ff, 0xff)) << \ + (reg_v3u(gpriv, 16, 24) - (n) * reg_v3u(gpriv, 16, 8))) + +#define RCANFD_GAFLCFG_GETRNC(gpriv, n, x) \ + (((x) >> (reg_v3u(gpriv, 16, 24) - (n) * reg_v3u(gpriv, 16, 8))) & \ + reg_v3u(gpriv, 0x1ff, 0xff)) /* RSCFDnCFDGAFLECTR / RSCFDnGAFLECTR */ #define RCANFD_GAFLECTR_AFLDAE BIT(8) -#define RCANFD_GAFLECTR_AFLPN(x) ((x) & 0x1f) +#define RCANFD_GAFLECTR_AFLPN(gpriv, x) ((x) & reg_v3u(gpriv, 0x7f, 0x1f)) /* RSCFDnCFDGAFLIDj / RSCFDnGAFLIDj */ #define RCANFD_GAFLID_GAFLLB BIT(29) @@ -116,9 +124,15 @@ enum rcanfd_chip_id { #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_NTSEG2(gpriv, x) \ + (((x) & reg_v3u(gpriv, 0x7f, 0x1f)) << reg_v3u(gpriv, 25, 24)) + +#define RCANFD_NCFG_NTSEG1(gpriv, x) \ + (((x) & reg_v3u(gpriv, 0xff, 0x7f)) << reg_v3u(gpriv, 17, 16)) + +#define RCANFD_NCFG_NSJW(gpriv, x) \ + (((x) & reg_v3u(gpriv, 0x7f, 0x1f)) << reg_v3u(gpriv, 10, 11)) + #define RCANFD_NCFG_NBRP(x) (((x) & 0x3ff) << 0) /* RSCFDnCFDCmCTR / RSCFDnCmCTR */ @@ -180,11 +194,18 @@ enum rcanfd_chip_id { /* RSCFDnCFDCmDCFG */ #define RCANFD_DCFG_DSJW(x) (((x) & 0x7) << 24) -#define RCANFD_DCFG_DTSEG2(x) (((x) & 0x7) << 20) -#define RCANFD_DCFG_DTSEG1(x) (((x) & 0xf) << 16) + +#define RCANFD_DCFG_DTSEG2(gpriv, x) \ + (((x) & reg_v3u(gpriv, 0x0f, 0x7)) << reg_v3u(gpriv, 16, 20)) + +#define RCANFD_DCFG_DTSEG1(gpriv, x) \ + (((x) & reg_v3u(gpriv, 0x1f, 0xf)) << reg_v3u(gpriv, 8, 16)) + #define RCANFD_DCFG_DBRP(x) (((x) & 0xff) << 0) /* RSCFDnCFDCmFDCFG */ +#define RCANFD_FDCFG_CLOE BIT(30) +#define RCANFD_FDCFG_FDOE BIT(28) #define RCANFD_FDCFG_TDCE BIT(9) #define RCANFD_FDCFG_TDCOC BIT(8) #define RCANFD_FDCFG_TDCO(x) (((x) & 0x7f) >> 16) @@ -219,10 +240,10 @@ enum rcanfd_chip_id { /* Common FIFO bits */ /* RSCFDnCFDCFCCk */ -#define RCANFD_CFCC_CFTML(x) (((x) & 0xf) << 20) -#define RCANFD_CFCC_CFM(x) (((x) & 0x3) << 16) +#define RCANFD_CFCC_CFTML(gpriv, x) (((x) & 0xf) << reg_v3u(gpriv, 16, 20)) +#define RCANFD_CFCC_CFM(gpriv, x) (((x) & 0x3) << reg_v3u(gpriv, 8, 16)) #define RCANFD_CFCC_CFIM BIT(12) -#define RCANFD_CFCC_CFDC(x) (((x) & 0x7) << 8) +#define RCANFD_CFCC_CFDC(gpriv, x) (((x) & 0x7) << reg_v3u(gpriv, 21, 8)) #define RCANFD_CFCC_CFPLS(x) (((x) & 0x7) << 4) #define RCANFD_CFCC_CFTXIE BIT(2) #define RCANFD_CFCC_CFE BIT(0) @@ -282,33 +303,31 @@ enum rcanfd_chip_id { #define RCANFD_GTSC (0x0094) /* RSCFDnCFDGAFLECTR / RSCFDnGAFLECTR */ #define RCANFD_GAFLECTR (0x0098) -/* RSCFDnCFDGAFLCFG0 / RSCFDnGAFLCFG0 */ -#define RCANFD_GAFLCFG0 (0x009c) -/* RSCFDnCFDGAFLCFG1 / RSCFDnGAFLCFG1 */ -#define RCANFD_GAFLCFG1 (0x00a0) +/* RSCFDnCFDGAFLCFG / RSCFDnGAFLCFG */ +#define RCANFD_GAFLCFG(ch) (0x009c + (0x04 * ((ch) / 2))) /* RSCFDnCFDRMNB / RSCFDnRMNB */ #define RCANFD_RMNB (0x00a4) /* RSCFDnCFDRMND / RSCFDnRMND */ #define RCANFD_RMND(y) (0x00a8 + (0x04 * (y))) /* RSCFDnCFDRFCCx / RSCFDnRFCCx */ -#define RCANFD_RFCC(x) (0x00b8 + (0x04 * (x))) +#define RCANFD_RFCC(gpriv, x) (reg_v3u(gpriv, 0x00c0, 0x00b8) + (0x04 * (x))) /* RSCFDnCFDRFSTSx / RSCFDnRFSTSx */ -#define RCANFD_RFSTS(x) (0x00d8 + (0x04 * (x))) +#define RCANFD_RFSTS(gpriv, x) (RCANFD_RFCC(gpriv, x) + 0x20) /* RSCFDnCFDRFPCTRx / RSCFDnRFPCTRx */ -#define RCANFD_RFPCTR(x) (0x00f8 + (0x04 * (x))) +#define RCANFD_RFPCTR(gpriv, x) (RCANFD_RFCC(gpriv, x) + 0x40) /* Common FIFO Control registers */ /* RSCFDnCFDCFCCx / RSCFDnCFCCx */ -#define RCANFD_CFCC(ch, idx) (0x0118 + (0x0c * (ch)) + \ - (0x04 * (idx))) +#define RCANFD_CFCC(gpriv, ch, idx) \ + (reg_v3u(gpriv, 0x0120, 0x0118) + (0x0c * (ch)) + (0x04 * (idx))) /* RSCFDnCFDCFSTSx / RSCFDnCFSTSx */ -#define RCANFD_CFSTS(ch, idx) (0x0178 + (0x0c * (ch)) + \ - (0x04 * (idx))) +#define RCANFD_CFSTS(gpriv, ch, idx) \ + (reg_v3u(gpriv, 0x01e0, 0x0178) + (0x0c * (ch)) + (0x04 * (idx))) /* RSCFDnCFDCFPCTRx / RSCFDnCFPCTRx */ -#define RCANFD_CFPCTR(ch, idx) (0x01d8 + (0x0c * (ch)) + \ - (0x04 * (idx))) +#define RCANFD_CFPCTR(gpriv, ch, idx) \ + (reg_v3u(gpriv, 0x0240, 0x01d8) + (0x0c * (ch)) + (0x04 * (idx))) /* RSCFDnCFDFESTS / RSCFDnFESTS */ #define RCANFD_FESTS (0x0238) @@ -387,22 +406,23 @@ enum rcanfd_chip_id { #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))) +#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))) + +#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))) @@ -415,6 +435,12 @@ enum rcanfd_chip_id { /* RSCFDnRPGACCr */ #define RCANFD_C_RPGACC(r) (0x1900 + (0x04 * (r))) +/* R-Car V3U Classical and CAN FD mode specific register map */ +#define RCANFD_V3U_CFDCFG (0x1314) +#define RCANFD_V3U_DCFG(m) (0x1400 + (0x20 * (m))) + +#define RCANFD_V3U_GAFL_OFFSET (0x1800) + /* CAN FD mode specific register map */ /* RSCFDnCFDCmXXX -> RCANFD_F_XXX(m) */ @@ -434,26 +460,28 @@ enum rcanfd_chip_id { #define RCANFD_F_RMDF(q, b) (0x200c + (0x04 * (b)) + (0x20 * (q))) /* RSCFDnCFDRFXXx -> RCANFD_F_RFXX(x) */ -#define RCANFD_F_RFOFFSET (0x3000) -#define RCANFD_F_RFID(x) (RCANFD_F_RFOFFSET + (0x80 * (x))) -#define RCANFD_F_RFPTR(x) (RCANFD_F_RFOFFSET + 0x04 + \ - (0x80 * (x))) -#define RCANFD_F_RFFDSTS(x) (RCANFD_F_RFOFFSET + 0x08 + \ - (0x80 * (x))) -#define RCANFD_F_RFDF(x, df) (RCANFD_F_RFOFFSET + 0x0c + \ - (0x80 * (x)) + (0x04 * (df))) +#define RCANFD_F_RFOFFSET(gpriv) reg_v3u(gpriv, 0x6000, 0x3000) +#define RCANFD_F_RFID(gpriv, x) (RCANFD_F_RFOFFSET(gpriv) + (0x80 * (x))) +#define RCANFD_F_RFPTR(gpriv, x) (RCANFD_F_RFOFFSET(gpriv) + 0x04 + (0x80 * (x))) +#define RCANFD_F_RFFDSTS(gpriv, x) (RCANFD_F_RFOFFSET(gpriv) + 0x08 + (0x80 * (x))) +#define RCANFD_F_RFDF(gpriv, x, df) \ + (RCANFD_F_RFOFFSET(gpriv) + 0x0c + (0x80 * (x)) + (0x04 * (df))) /* RSCFDnCFDCFXXk -> RCANFD_F_CFXX(ch, k) */ -#define RCANFD_F_CFOFFSET (0x3400) -#define RCANFD_F_CFID(ch, idx) (RCANFD_F_CFOFFSET + (0x180 * (ch)) + \ - (0x80 * (idx))) -#define RCANFD_F_CFPTR(ch, idx) (RCANFD_F_CFOFFSET + 0x04 + \ - (0x180 * (ch)) + (0x80 * (idx))) -#define RCANFD_F_CFFDCSTS(ch, idx) (RCANFD_F_CFOFFSET + 0x08 + \ - (0x180 * (ch)) + (0x80 * (idx))) -#define RCANFD_F_CFDF(ch, idx, df) (RCANFD_F_CFOFFSET + 0x0c + \ - (0x180 * (ch)) + (0x80 * (idx)) + \ - (0x04 * (df))) +#define RCANFD_F_CFOFFSET(gpriv) reg_v3u(gpriv, 0x6400, 0x3400) + +#define RCANFD_F_CFID(gpriv, ch, idx) \ + (RCANFD_F_CFOFFSET(gpriv) + (0x180 * (ch)) + (0x80 * (idx))) + +#define RCANFD_F_CFPTR(gpriv, ch, idx) \ + (RCANFD_F_CFOFFSET(gpriv) + 0x04 + (0x180 * (ch)) + (0x80 * (idx))) + +#define RCANFD_F_CFFDCSTS(gpriv, ch, idx) \ + (RCANFD_F_CFOFFSET(gpriv) + 0x08 + (0x180 * (ch)) + (0x80 * (idx))) + +#define RCANFD_F_CFDF(gpriv, ch, idx, df) \ + (RCANFD_F_CFOFFSET(gpriv) + 0x0c + (0x180 * (ch)) + (0x80 * (idx)) + \ + (0x04 * (df))) /* RSCFDnCFDTMXXp -> RCANFD_F_TMXX(p) */ #define RCANFD_F_TMID(p) (0x4000 + (0x20 * (p))) @@ -470,7 +498,7 @@ enum rcanfd_chip_id { #define RCANFD_FIFO_DEPTH 8 /* Tx FIFO depth */ #define RCANFD_NAPI_WEIGHT 8 /* Rx poll quota */ -#define RCANFD_NUM_CHANNELS 2 /* Two channels max */ +#define RCANFD_NUM_CHANNELS 8 /* Eight channels max */ #define RCANFD_CHANNELS_MASK BIT((RCANFD_NUM_CHANNELS) - 1) #define RCANFD_GAFL_PAGENUM(entry) ((entry) / 16) @@ -521,6 +549,7 @@ struct rcar_canfd_global { struct reset_control *rstc1; struct reset_control *rstc2; enum rcanfd_chip_id chip_id; + u32 max_channels; }; /* CAN FD mode nominal rate constants */ @@ -563,6 +592,17 @@ static const struct can_bittiming_const rcar_canfd_bittiming_const = { }; /* Helper functions */ +static inline bool is_v3u(struct rcar_canfd_global *gpriv) +{ + return gpriv->chip_id == RENESAS_R8A779A0; +} + +static inline u32 reg_v3u(struct rcar_canfd_global *gpriv, + u32 v3u, u32 not_v3u) +{ + return is_v3u(gpriv) ? v3u : not_v3u; +} + static inline void rcar_canfd_update(u32 mask, u32 val, u32 __iomem *reg) { u32 data = readl(reg); @@ -628,6 +668,25 @@ static void rcar_canfd_tx_failure_cleanup(struct net_device *ndev) can_free_echo_skb(ndev, i, NULL); } +static void rcar_canfd_set_mode(struct rcar_canfd_global *gpriv) +{ + if (is_v3u(gpriv)) { + if (gpriv->fdmode) + rcar_canfd_set_bit(gpriv->base, RCANFD_V3U_CFDCFG, + RCANFD_FDCFG_FDOE); + else + rcar_canfd_set_bit(gpriv->base, RCANFD_V3U_CFDCFG, + RCANFD_FDCFG_CLOE); + } else { + 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); + } +} + static int rcar_canfd_reset_controller(struct rcar_canfd_global *gpriv) { u32 sts, ch; @@ -660,15 +719,10 @@ static int rcar_canfd_reset_controller(struct rcar_canfd_global *gpriv) rcar_canfd_write(gpriv->base, RCANFD_GERFL, 0x0); /* 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); + rcar_canfd_set_mode(gpriv); /* 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, gpriv->max_channels) { rcar_canfd_clear_bit(gpriv->base, RCANFD_CCTR(ch), RCANFD_CCTR_CSLPR); @@ -709,7 +763,7 @@ static void rcar_canfd_configure_controller(struct rcar_canfd_global *gpriv) rcar_canfd_set_bit(gpriv->base, RCANFD_GCFG, cfg); /* Channel configuration settings */ - for_each_set_bit(ch, &gpriv->channels_mask, RCANFD_NUM_CHANNELS) { + for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels) { rcar_canfd_set_bit(gpriv->base, RCANFD_CCTR(ch), RCANFD_CCTR_ERRD); rcar_canfd_update_bit(gpriv->base, RCANFD_CCTR(ch), @@ -729,20 +783,22 @@ static void rcar_canfd_configure_afl_rules(struct rcar_canfd_global *gpriv, start = 0; /* Channel 0 always starts from 0th rule */ } else { /* Get number of Channel 0 rules and adjust */ - cfg = rcar_canfd_read(gpriv->base, RCANFD_GAFLCFG0); - start = RCANFD_GAFLCFG_GETRNC(0, cfg); + cfg = rcar_canfd_read(gpriv->base, RCANFD_GAFLCFG(ch)); + start = RCANFD_GAFLCFG_GETRNC(gpriv, 0, cfg); } /* Enable write access to entry */ page = RCANFD_GAFL_PAGENUM(start); rcar_canfd_set_bit(gpriv->base, RCANFD_GAFLECTR, - (RCANFD_GAFLECTR_AFLPN(page) | + (RCANFD_GAFLECTR_AFLPN(gpriv, page) | RCANFD_GAFLECTR_AFLDAE)); /* Write number of rules for channel */ - rcar_canfd_set_bit(gpriv->base, RCANFD_GAFLCFG0, - RCANFD_GAFLCFG_SETRNC(ch, num_rules)); - if (gpriv->fdmode) + rcar_canfd_set_bit(gpriv->base, RCANFD_GAFLCFG(ch), + RCANFD_GAFLCFG_SETRNC(gpriv, ch, num_rules)); + if (is_v3u(gpriv)) + offset = RCANFD_V3U_GAFL_OFFSET; + else if (gpriv->fdmode) offset = RCANFD_F_GAFL_OFFSET; else offset = RCANFD_C_GAFL_OFFSET; @@ -754,8 +810,8 @@ static void rcar_canfd_configure_afl_rules(struct rcar_canfd_global *gpriv, /* Any data length accepted */ 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(offset, start), - RCANFD_GAFLP1_GAFLFDP(ridx)); + rcar_canfd_set_bit(gpriv->base, RCANFD_GAFLP1(offset, start), + RCANFD_GAFLP1_GAFLFDP(ridx)); /* Disable write access to page */ rcar_canfd_clear_bit(gpriv->base, @@ -779,7 +835,7 @@ static void rcar_canfd_configure_rx(struct rcar_canfd_global *gpriv, u32 ch) cfg = (RCANFD_RFCC_RFIM | RCANFD_RFCC_RFDC(rfdc) | RCANFD_RFCC_RFPLS(rfpls) | RCANFD_RFCC_RFIE); - rcar_canfd_write(gpriv->base, RCANFD_RFCC(ridx), cfg); + rcar_canfd_write(gpriv->base, RCANFD_RFCC(gpriv, ridx), cfg); } static void rcar_canfd_configure_tx(struct rcar_canfd_global *gpriv, u32 ch) @@ -801,15 +857,15 @@ static void rcar_canfd_configure_tx(struct rcar_canfd_global *gpriv, u32 ch) else cfpls = 0; /* b000 - Max 8 bytes payload */ - cfg = (RCANFD_CFCC_CFTML(cftml) | RCANFD_CFCC_CFM(cfm) | - RCANFD_CFCC_CFIM | RCANFD_CFCC_CFDC(cfdc) | + cfg = (RCANFD_CFCC_CFTML(gpriv, cftml) | RCANFD_CFCC_CFM(gpriv, cfm) | + RCANFD_CFCC_CFIM | RCANFD_CFCC_CFDC(gpriv, cfdc) | 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(gpriv, ch, RCANFD_CFFIFO_IDX), cfg); if (gpriv->fdmode) /* Clear FD mode specific control/status register */ rcar_canfd_write(gpriv->base, - RCANFD_F_CFFDCSTS(ch, RCANFD_CFFIFO_IDX), 0); + RCANFD_F_CFFDCSTS(gpriv, ch, RCANFD_CFFIFO_IDX), 0); } static void rcar_canfd_enable_global_interrupts(struct rcar_canfd_global *gpriv) @@ -890,20 +946,20 @@ static void rcar_canfd_global_error(struct net_device *ndev) } if (gerfl & RCANFD_GERFL_MES) { sts = rcar_canfd_read(priv->base, - RCANFD_CFSTS(ch, RCANFD_CFFIFO_IDX)); + RCANFD_CFSTS(gpriv, ch, RCANFD_CFFIFO_IDX)); if (sts & RCANFD_CFSTS_CFMLT) { netdev_dbg(ndev, "Tx Message Lost flag\n"); stats->tx_dropped++; rcar_canfd_write(priv->base, - RCANFD_CFSTS(ch, RCANFD_CFFIFO_IDX), + RCANFD_CFSTS(gpriv, ch, RCANFD_CFFIFO_IDX), sts & ~RCANFD_CFSTS_CFMLT); } - sts = rcar_canfd_read(priv->base, RCANFD_RFSTS(ridx)); + sts = rcar_canfd_read(priv->base, RCANFD_RFSTS(gpriv, ridx)); if (sts & RCANFD_RFSTS_RFMLT) { netdev_dbg(ndev, "Rx Message Lost flag\n"); stats->rx_dropped++; - rcar_canfd_write(priv->base, RCANFD_RFSTS(ridx), + rcar_canfd_write(priv->base, RCANFD_RFSTS(gpriv, ridx), sts & ~RCANFD_RFSTS_RFMLT); } } @@ -1038,6 +1094,7 @@ static void rcar_canfd_error(struct net_device *ndev, u32 cerfl, static void rcar_canfd_tx_done(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 sts; unsigned long flags; @@ -1053,7 +1110,7 @@ static void rcar_canfd_tx_done(struct net_device *ndev) spin_lock_irqsave(&priv->tx_lock, flags); priv->tx_tail++; sts = rcar_canfd_read(priv->base, - RCANFD_CFSTS(ch, RCANFD_CFFIFO_IDX)); + RCANFD_CFSTS(gpriv, ch, RCANFD_CFFIFO_IDX)); unsent = RCANFD_CFSTS_CFMC(sts); /* Wake producer only when there is room */ @@ -1069,7 +1126,7 @@ static void rcar_canfd_tx_done(struct net_device *ndev) } while (1); /* Clear interrupt */ - rcar_canfd_write(priv->base, RCANFD_CFSTS(ch, RCANFD_CFFIFO_IDX), + rcar_canfd_write(priv->base, RCANFD_CFSTS(gpriv, ch, RCANFD_CFFIFO_IDX), sts & ~RCANFD_CFSTS_CFTXIF); can_led_event(ndev, CAN_LED_EVENT_TX); } @@ -1091,7 +1148,7 @@ static irqreturn_t rcar_canfd_global_err_interrupt(int irq, void *dev_id) struct rcar_canfd_global *gpriv = dev_id; u32 ch; - for_each_set_bit(ch, &gpriv->channels_mask, RCANFD_NUM_CHANNELS) + for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels) rcar_canfd_handle_global_err(gpriv, ch); return IRQ_HANDLED; @@ -1104,12 +1161,12 @@ static void rcar_canfd_handle_global_receive(struct rcar_canfd_global *gpriv, u3 u32 sts; /* Handle Rx interrupts */ - sts = rcar_canfd_read(priv->base, RCANFD_RFSTS(ridx)); + sts = rcar_canfd_read(priv->base, RCANFD_RFSTS(gpriv, ridx)); if (likely(sts & RCANFD_RFSTS_RFIF)) { if (napi_schedule_prep(&priv->napi)) { /* Disable Rx FIFO interrupts */ rcar_canfd_clear_bit(priv->base, - RCANFD_RFCC(ridx), + RCANFD_RFCC(gpriv, ridx), RCANFD_RFCC_RFIE); __napi_schedule(&priv->napi); } @@ -1121,7 +1178,7 @@ static irqreturn_t rcar_canfd_global_receive_fifo_interrupt(int irq, void *dev_i struct rcar_canfd_global *gpriv = dev_id; u32 ch; - for_each_set_bit(ch, &gpriv->channels_mask, RCANFD_NUM_CHANNELS) + for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels) rcar_canfd_handle_global_receive(gpriv, ch); return IRQ_HANDLED; @@ -1135,7 +1192,7 @@ static irqreturn_t rcar_canfd_global_interrupt(int irq, void *dev_id) /* Global error interrupts still indicate a condition specific * to a channel. RxFIFO interrupt is a global interrupt. */ - for_each_set_bit(ch, &gpriv->channels_mask, RCANFD_NUM_CHANNELS) { + for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels) { rcar_canfd_handle_global_err(gpriv, ch); rcar_canfd_handle_global_receive(gpriv, ch); } @@ -1181,7 +1238,7 @@ static void rcar_canfd_handle_channel_tx(struct rcar_canfd_global *gpriv, u32 ch /* Handle Tx interrupts */ sts = rcar_canfd_read(priv->base, - RCANFD_CFSTS(ch, RCANFD_CFFIFO_IDX)); + RCANFD_CFSTS(gpriv, ch, RCANFD_CFFIFO_IDX)); if (likely(sts & RCANFD_CFSTS_CFTXIF)) rcar_canfd_tx_done(ndev); } @@ -1191,7 +1248,7 @@ static irqreturn_t rcar_canfd_channel_tx_interrupt(int irq, void *dev_id) struct rcar_canfd_global *gpriv = dev_id; u32 ch; - for_each_set_bit(ch, &gpriv->channels_mask, RCANFD_NUM_CHANNELS) + for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels) rcar_canfd_handle_channel_tx(gpriv, ch); return IRQ_HANDLED; @@ -1223,7 +1280,7 @@ static irqreturn_t rcar_canfd_channel_err_interrupt(int irq, void *dev_id) struct rcar_canfd_global *gpriv = dev_id; u32 ch; - for_each_set_bit(ch, &gpriv->channels_mask, RCANFD_NUM_CHANNELS) + for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels) rcar_canfd_handle_channel_err(gpriv, ch); return IRQ_HANDLED; @@ -1235,7 +1292,7 @@ static irqreturn_t rcar_canfd_channel_interrupt(int irq, void *dev_id) u32 ch; /* 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, gpriv->max_channels) { rcar_canfd_handle_channel_err(gpriv, ch); rcar_canfd_handle_channel_tx(gpriv, ch); } @@ -1246,6 +1303,7 @@ static irqreturn_t rcar_canfd_channel_interrupt(int irq, void *dev_id) static void rcar_canfd_set_bittiming(struct net_device *dev) { struct rcar_canfd_channel *priv = netdev_priv(dev); + struct rcar_canfd_global *gpriv = priv->gpriv; const struct can_bittiming *bt = &priv->can.bittiming; const struct can_bittiming *dbt = &priv->can.data_bittiming; u16 brp, sjw, tseg1, tseg2; @@ -1260,8 +1318,8 @@ static void rcar_canfd_set_bittiming(struct net_device *dev) 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)); + cfg = (RCANFD_NCFG_NTSEG1(gpriv, tseg1) | RCANFD_NCFG_NBRP(brp) | + RCANFD_NCFG_NSJW(gpriv, sjw) | RCANFD_NCFG_NTSEG2(gpriv, tseg2)); rcar_canfd_write(priv->base, RCANFD_CCFG(ch), cfg); netdev_dbg(priv->ndev, "nrate: brp %u, sjw %u, tseg1 %u, tseg2 %u\n", @@ -1273,16 +1331,25 @@ static void rcar_canfd_set_bittiming(struct net_device *dev) 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(gpriv, tseg1) | RCANFD_DCFG_DBRP(brp) | + RCANFD_DCFG_DSJW(sjw) | RCANFD_DCFG_DTSEG2(gpriv, 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)); + if (is_v3u(gpriv)) { + cfg = (RCANFD_NCFG_NTSEG1(gpriv, tseg1) | + RCANFD_NCFG_NBRP(brp) | + RCANFD_NCFG_NSJW(gpriv, sjw) | + RCANFD_NCFG_NTSEG2(gpriv, tseg2)); + } else { + 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, @@ -1294,6 +1361,7 @@ static void rcar_canfd_set_bittiming(struct net_device *dev) static int rcar_canfd_start(struct net_device *ndev) { struct rcar_canfd_channel *priv = netdev_priv(ndev); + struct rcar_canfd_global *gpriv = priv->gpriv; int err = -EOPNOTSUPP; u32 sts, ch = priv->channel; u32 ridx = ch + RCANFD_RFFIFO_IDX; @@ -1315,9 +1383,9 @@ static int rcar_canfd_start(struct net_device *ndev) } /* Enable Common & Rx FIFO */ - rcar_canfd_set_bit(priv->base, RCANFD_CFCC(ch, RCANFD_CFFIFO_IDX), + rcar_canfd_set_bit(priv->base, RCANFD_CFCC(gpriv, ch, RCANFD_CFFIFO_IDX), RCANFD_CFCC_CFE); - rcar_canfd_set_bit(priv->base, RCANFD_RFCC(ridx), RCANFD_RFCC_RFE); + rcar_canfd_set_bit(priv->base, RCANFD_RFCC(gpriv, ridx), RCANFD_RFCC_RFE); priv->can.state = CAN_STATE_ERROR_ACTIVE; return 0; @@ -1365,6 +1433,7 @@ out_clock: static void rcar_canfd_stop(struct net_device *ndev) { struct rcar_canfd_channel *priv = netdev_priv(ndev); + struct rcar_canfd_global *gpriv = priv->gpriv; int err; u32 sts, ch = priv->channel; u32 ridx = ch + RCANFD_RFFIFO_IDX; @@ -1382,9 +1451,9 @@ static void rcar_canfd_stop(struct net_device *ndev) rcar_canfd_disable_channel_interrupts(priv); /* Disable Common & Rx FIFO */ - rcar_canfd_clear_bit(priv->base, RCANFD_CFCC(ch, RCANFD_CFFIFO_IDX), + rcar_canfd_clear_bit(priv->base, RCANFD_CFCC(gpriv, ch, RCANFD_CFFIFO_IDX), RCANFD_CFCC_CFE); - rcar_canfd_clear_bit(priv->base, RCANFD_RFCC(ridx), RCANFD_RFCC_RFE); + rcar_canfd_clear_bit(priv->base, RCANFD_RFCC(gpriv, ridx), RCANFD_RFCC_RFE); /* Set the state as STOPPED */ priv->can.state = CAN_STATE_STOPPED; @@ -1408,6 +1477,7 @@ static netdev_tx_t rcar_canfd_start_xmit(struct sk_buff *skb, struct net_device *ndev) { struct rcar_canfd_channel *priv = netdev_priv(ndev); + struct rcar_canfd_global *gpriv = priv->gpriv; struct canfd_frame *cf = (struct canfd_frame *)skb->data; u32 sts = 0, id, dlc; unsigned long flags; @@ -1428,11 +1498,11 @@ static netdev_tx_t rcar_canfd_start_xmit(struct sk_buff *skb, dlc = RCANFD_CFPTR_CFDLC(can_fd_len2dlc(cf->len)); - if (priv->can.ctrlmode & CAN_CTRLMODE_FD) { + if ((priv->can.ctrlmode & CAN_CTRLMODE_FD) || is_v3u(gpriv)) { rcar_canfd_write(priv->base, - RCANFD_F_CFID(ch, RCANFD_CFFIFO_IDX), id); + RCANFD_F_CFID(gpriv, ch, RCANFD_CFFIFO_IDX), id); rcar_canfd_write(priv->base, - RCANFD_F_CFPTR(ch, RCANFD_CFFIFO_IDX), dlc); + RCANFD_F_CFPTR(gpriv, ch, RCANFD_CFFIFO_IDX), dlc); if (can_is_canfd_skb(skb)) { /* CAN FD frame format */ @@ -1445,10 +1515,10 @@ static netdev_tx_t rcar_canfd_start_xmit(struct sk_buff *skb, } rcar_canfd_write(priv->base, - RCANFD_F_CFFDCSTS(ch, RCANFD_CFFIFO_IDX), sts); + RCANFD_F_CFFDCSTS(gpriv, ch, RCANFD_CFFIFO_IDX), sts); rcar_canfd_put_data(priv, cf, - RCANFD_F_CFDF(ch, RCANFD_CFFIFO_IDX, 0)); + RCANFD_F_CFDF(gpriv, ch, RCANFD_CFFIFO_IDX, 0)); } else { rcar_canfd_write(priv->base, RCANFD_C_CFID(ch, RCANFD_CFFIFO_IDX), id); @@ -1471,7 +1541,7 @@ static netdev_tx_t rcar_canfd_start_xmit(struct sk_buff *skb, * pointer for the Common FIFO */ rcar_canfd_write(priv->base, - RCANFD_CFPCTR(ch, RCANFD_CFFIFO_IDX), 0xff); + RCANFD_CFPCTR(gpriv, ch, RCANFD_CFFIFO_IDX), 0xff); spin_unlock_irqrestore(&priv->tx_lock, flags); return NETDEV_TX_OK; @@ -1480,18 +1550,21 @@ static netdev_tx_t rcar_canfd_start_xmit(struct sk_buff *skb, static void rcar_canfd_rx_pkt(struct rcar_canfd_channel *priv) { struct net_device_stats *stats = &priv->ndev->stats; + struct rcar_canfd_global *gpriv = priv->gpriv; struct canfd_frame *cf; struct sk_buff *skb; u32 sts = 0, id, dlc; u32 ch = priv->channel; u32 ridx = ch + RCANFD_RFFIFO_IDX; - 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)); + if ((priv->can.ctrlmode & CAN_CTRLMODE_FD) || is_v3u(gpriv)) { + id = rcar_canfd_read(priv->base, RCANFD_F_RFID(gpriv, ridx)); + dlc = rcar_canfd_read(priv->base, RCANFD_F_RFPTR(gpriv, ridx)); - sts = rcar_canfd_read(priv->base, RCANFD_F_RFFDSTS(ridx)); - if (sts & RCANFD_RFFDSTS_RFFDF) + sts = rcar_canfd_read(priv->base, RCANFD_F_RFFDSTS(gpriv, ridx)); + + if ((priv->can.ctrlmode & CAN_CTRLMODE_FD) && + sts & RCANFD_RFFDSTS_RFFDF) skb = alloc_canfd_skb(priv->ndev, &cf); else skb = alloc_can_skb(priv->ndev, @@ -1529,12 +1602,14 @@ static void rcar_canfd_rx_pkt(struct rcar_canfd_channel *priv) if (sts & RCANFD_RFFDSTS_RFBRS) cf->flags |= CANFD_BRS; - rcar_canfd_get_data(priv, cf, RCANFD_F_RFDF(ridx, 0)); + rcar_canfd_get_data(priv, cf, RCANFD_F_RFDF(gpriv, ridx, 0)); } } else { cf->len = can_cc_dlc2len(RCANFD_RFPTR_RFDLC(dlc)); if (id & RCANFD_RFID_RFRTR) cf->can_id |= CAN_RTR_FLAG; + else if (is_v3u(gpriv)) + rcar_canfd_get_data(priv, cf, RCANFD_F_RFDF(gpriv, ridx, 0)); else rcar_canfd_get_data(priv, cf, RCANFD_C_RFDF(ridx, 0)); } @@ -1542,7 +1617,7 @@ static void rcar_canfd_rx_pkt(struct rcar_canfd_channel *priv) /* Write 0xff to RFPC to increment the CPU-side * pointer of the Rx FIFO */ - rcar_canfd_write(priv->base, RCANFD_RFPCTR(ridx), 0xff); + rcar_canfd_write(priv->base, RCANFD_RFPCTR(gpriv, ridx), 0xff); can_led_event(priv->ndev, CAN_LED_EVENT_RX); @@ -1556,13 +1631,14 @@ static int rcar_canfd_rx_poll(struct napi_struct *napi, int quota) { struct rcar_canfd_channel *priv = container_of(napi, struct rcar_canfd_channel, napi); + struct rcar_canfd_global *gpriv = priv->gpriv; int num_pkts; u32 sts; u32 ch = priv->channel; u32 ridx = ch + RCANFD_RFFIFO_IDX; for (num_pkts = 0; num_pkts < quota; num_pkts++) { - sts = rcar_canfd_read(priv->base, RCANFD_RFSTS(ridx)); + sts = rcar_canfd_read(priv->base, RCANFD_RFSTS(gpriv, ridx)); /* Check FIFO empty condition */ if (sts & RCANFD_RFSTS_RFEMP) break; @@ -1571,7 +1647,7 @@ static int rcar_canfd_rx_poll(struct napi_struct *napi, int quota) /* Clear interrupt bit */ if (sts & RCANFD_RFSTS_RFIF) - rcar_canfd_write(priv->base, RCANFD_RFSTS(ridx), + rcar_canfd_write(priv->base, RCANFD_RFSTS(gpriv, ridx), sts & ~RCANFD_RFSTS_RFIF); } @@ -1579,7 +1655,7 @@ static int rcar_canfd_rx_poll(struct napi_struct *napi, int quota) if (num_pkts < quota) { if (napi_complete_done(napi, num_pkts)) { /* Enable Rx FIFO interrupts */ - rcar_canfd_set_bit(priv->base, RCANFD_RFCC(ridx), + rcar_canfd_set_bit(priv->base, RCANFD_RFCC(gpriv, ridx), RCANFD_RFCC_RFIE); } } @@ -1756,21 +1832,24 @@ static int rcar_canfd_probe(struct platform_device *pdev) int g_err_irq, g_recc_irq; bool fdmode = true; /* CAN FD only mode - default */ enum rcanfd_chip_id chip_id; + int max_channels; + char name[9] = "channelX"; + int i; chip_id = (uintptr_t)of_device_get_match_data(&pdev->dev); + max_channels = chip_id == RENESAS_R8A779A0 ? 8 : 2; 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)) - channels_mask |= BIT(0); /* Channel 0 */ - - of_child = of_get_child_by_name(pdev->dev.of_node, "channel1"); - if (of_child && of_device_is_available(of_child)) - channels_mask |= BIT(1); /* Channel 1 */ + for (i = 0; i < max_channels; ++i) { + name[7] = '0' + i; + of_child = of_get_child_by_name(pdev->dev.of_node, name); + if (of_child && of_device_is_available(of_child)) + channels_mask |= BIT(i); + } - if (chip_id == RENESAS_RCAR_GEN3) { + if (chip_id != RENESAS_RZG2L) { ch_irq = platform_get_irq_byname_optional(pdev, "ch_int"); if (ch_irq < 0) { /* For backward compatibility get irq by index */ @@ -1806,6 +1885,7 @@ static int rcar_canfd_probe(struct platform_device *pdev) gpriv->channels_mask = channels_mask; gpriv->fdmode = fdmode; gpriv->chip_id = chip_id; + gpriv->max_channels = max_channels; if (gpriv->chip_id == RENESAS_RZG2L) { gpriv->rstc1 = devm_reset_control_get_exclusive(&pdev->dev, "rstp_n"); @@ -1847,7 +1927,7 @@ static int rcar_canfd_probe(struct platform_device *pdev) } fcan_freq = clk_get_rate(gpriv->can_clk); - if (gpriv->fcan == RCANFD_CANFDCLK && gpriv->chip_id == RENESAS_RCAR_GEN3) + if (gpriv->fcan == RCANFD_CANFDCLK && gpriv->chip_id != RENESAS_RZG2L) /* CANFD clock is further divided by (1/2) within the IP */ fcan_freq /= 2; @@ -1859,7 +1939,7 @@ static int rcar_canfd_probe(struct platform_device *pdev) gpriv->base = addr; /* Request IRQ that's common for both channels */ - if (gpriv->chip_id == RENESAS_RCAR_GEN3) { + if (gpriv->chip_id != RENESAS_RZG2L) { err = devm_request_irq(&pdev->dev, ch_irq, rcar_canfd_channel_interrupt, 0, "canfd.ch_int", gpriv); @@ -1925,7 +2005,7 @@ static int rcar_canfd_probe(struct platform_device *pdev) rcar_canfd_configure_controller(gpriv); /* Configure per channel attributes */ - for_each_set_bit(ch, &gpriv->channels_mask, RCANFD_NUM_CHANNELS) { + for_each_set_bit(ch, &gpriv->channels_mask, max_channels) { /* Configure Channel's Rx fifo */ rcar_canfd_configure_rx(gpriv, ch); @@ -1951,7 +2031,7 @@ static int rcar_canfd_probe(struct platform_device *pdev) goto fail_mode; } - for_each_set_bit(ch, &gpriv->channels_mask, RCANFD_NUM_CHANNELS) { + for_each_set_bit(ch, &gpriv->channels_mask, max_channels) { err = rcar_canfd_channel_probe(gpriv, ch, fcan_freq); if (err) goto fail_channel; @@ -1963,7 +2043,7 @@ static int rcar_canfd_probe(struct platform_device *pdev) return 0; fail_channel: - for_each_set_bit(ch, &gpriv->channels_mask, RCANFD_NUM_CHANNELS) + for_each_set_bit(ch, &gpriv->channels_mask, max_channels) rcar_canfd_channel_remove(gpriv, ch); fail_mode: rcar_canfd_disable_global_interrupts(gpriv); @@ -1984,7 +2064,7 @@ static int rcar_canfd_remove(struct platform_device *pdev) rcar_canfd_reset_controller(gpriv); rcar_canfd_disable_global_interrupts(gpriv); - for_each_set_bit(ch, &gpriv->channels_mask, RCANFD_NUM_CHANNELS) { + for_each_set_bit(ch, &gpriv->channels_mask, gpriv->max_channels) { rcar_canfd_disable_channel_interrupts(gpriv->ch[ch]); rcar_canfd_channel_remove(gpriv, ch); } @@ -2014,6 +2094,7 @@ static SIMPLE_DEV_PM_OPS(rcar_canfd_pm_ops, rcar_canfd_suspend, static const __maybe_unused struct of_device_id rcar_canfd_of_table[] = { { .compatible = "renesas,rcar-gen3-canfd", .data = (void *)RENESAS_RCAR_GEN3 }, { .compatible = "renesas,rzg2l-canfd", .data = (void *)RENESAS_RZG2L }, + { .compatible = "renesas,r8a779a0-canfd", .data = (void *)RENESAS_R8A779A0 }, { } }; diff --git a/drivers/net/can/usb/etas_es58x/es58x_fd.c b/drivers/net/can/usb/etas_es58x/es58x_fd.c index 88d2540abbbe..c97ffa71fd75 100644 --- a/drivers/net/can/usb/etas_es58x/es58x_fd.c +++ b/drivers/net/can/usb/etas_es58x/es58x_fd.c @@ -173,12 +173,11 @@ static int es58x_fd_rx_event_msg(struct net_device *netdev, const struct es58x_fd_rx_event_msg *rx_event_msg; int ret; + rx_event_msg = &es58x_fd_urb_cmd->rx_event_msg; ret = es58x_check_msg_len(es58x_dev->dev, *rx_event_msg, msg_len); if (ret) return ret; - rx_event_msg = &es58x_fd_urb_cmd->rx_event_msg; - return es58x_rx_err_msg(netdev, rx_event_msg->error_code, rx_event_msg->event_code, get_unaligned_le64(&rx_event_msg->timestamp)); diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index d35749fad1ef..67408e316062 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -9,11 +9,12 @@ * Many thanks to all socketcan devs! */ +#include <linux/bitfield.h> #include <linux/ethtool.h> #include <linux/init.h> -#include <linux/signal.h> #include <linux/module.h> #include <linux/netdevice.h> +#include <linux/signal.h> #include <linux/usb.h> #include <linux/can.h> @@ -21,14 +22,20 @@ #include <linux/can/error.h> /* Device specific constants */ -#define USB_GSUSB_1_VENDOR_ID 0x1d50 -#define USB_GSUSB_1_PRODUCT_ID 0x606f +#define USB_GSUSB_1_VENDOR_ID 0x1d50 +#define USB_GSUSB_1_PRODUCT_ID 0x606f -#define USB_CANDLELIGHT_VENDOR_ID 0x1209 +#define USB_CANDLELIGHT_VENDOR_ID 0x1209 #define USB_CANDLELIGHT_PRODUCT_ID 0x2323 -#define GSUSB_ENDPOINT_IN 1 -#define GSUSB_ENDPOINT_OUT 2 +#define USB_CES_CANEXT_FD_VENDOR_ID 0x1cd2 +#define USB_CES_CANEXT_FD_PRODUCT_ID 0x606f + +#define USB_ABE_CANDEBUGGER_FD_VENDOR_ID 0x16d0 +#define USB_ABE_CANDEBUGGER_FD_PRODUCT_ID 0x10b8 + +#define GSUSB_ENDPOINT_IN 1 +#define GSUSB_ENDPOINT_OUT 2 /* Device specific constants */ enum gs_usb_breq { @@ -40,6 +47,11 @@ enum gs_usb_breq { GS_USB_BREQ_DEVICE_CONFIG, GS_USB_BREQ_TIMESTAMP, GS_USB_BREQ_IDENTIFY, + GS_USB_BREQ_GET_USER_ID, + GS_USB_BREQ_QUIRK_CANTACT_PRO_DATA_BITTIMING = GS_USB_BREQ_GET_USER_ID, + GS_USB_BREQ_SET_USER_ID, + GS_USB_BREQ_DATA_BITTIMING, + GS_USB_BREQ_BT_CONST_EXT, }; enum gs_can_mode { @@ -87,11 +99,18 @@ struct gs_device_config { __le32 hw_version; } __packed; -#define GS_CAN_MODE_NORMAL 0 -#define GS_CAN_MODE_LISTEN_ONLY BIT(0) -#define GS_CAN_MODE_LOOP_BACK BIT(1) -#define GS_CAN_MODE_TRIPLE_SAMPLE BIT(2) -#define GS_CAN_MODE_ONE_SHOT BIT(3) +#define GS_CAN_MODE_NORMAL 0 +#define GS_CAN_MODE_LISTEN_ONLY BIT(0) +#define GS_CAN_MODE_LOOP_BACK BIT(1) +#define GS_CAN_MODE_TRIPLE_SAMPLE BIT(2) +#define GS_CAN_MODE_ONE_SHOT BIT(3) +#define GS_CAN_MODE_HW_TIMESTAMP BIT(4) +/* GS_CAN_FEATURE_IDENTIFY BIT(5) */ +/* GS_CAN_FEATURE_USER_ID BIT(6) */ +#define GS_CAN_MODE_PAD_PKTS_TO_MAX_PKT_SIZE BIT(7) +#define GS_CAN_MODE_FD BIT(8) +/* GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX BIT(9) */ +/* GS_CAN_FEATURE_BT_CONST_EXT BIT(10) */ struct gs_device_mode { __le32 mode; @@ -116,12 +135,25 @@ struct gs_identify_mode { __le32 mode; } __packed; -#define GS_CAN_FEATURE_LISTEN_ONLY BIT(0) -#define GS_CAN_FEATURE_LOOP_BACK BIT(1) -#define GS_CAN_FEATURE_TRIPLE_SAMPLE BIT(2) -#define GS_CAN_FEATURE_ONE_SHOT BIT(3) -#define GS_CAN_FEATURE_HW_TIMESTAMP BIT(4) -#define GS_CAN_FEATURE_IDENTIFY BIT(5) +#define GS_CAN_FEATURE_LISTEN_ONLY BIT(0) +#define GS_CAN_FEATURE_LOOP_BACK BIT(1) +#define GS_CAN_FEATURE_TRIPLE_SAMPLE BIT(2) +#define GS_CAN_FEATURE_ONE_SHOT BIT(3) +#define GS_CAN_FEATURE_HW_TIMESTAMP BIT(4) +#define GS_CAN_FEATURE_IDENTIFY BIT(5) +#define GS_CAN_FEATURE_USER_ID BIT(6) +#define GS_CAN_FEATURE_PAD_PKTS_TO_MAX_PKT_SIZE BIT(7) +#define GS_CAN_FEATURE_FD BIT(8) +#define GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX BIT(9) +#define GS_CAN_FEATURE_BT_CONST_EXT BIT(10) +#define GS_CAN_FEATURE_MASK GENMASK(10, 0) + +/* internal quirks - keep in GS_CAN_FEATURE space for now */ + +/* CANtact Pro original firmware: + * BREQ DATA_BITTIMING overlaps with GET_USER_ID + */ +#define GS_CAN_FEATURE_QUIRK_BREQ_CANTACT_PRO BIT(31) struct gs_device_bt_const { __le32 feature; @@ -136,7 +168,50 @@ struct gs_device_bt_const { __le32 brp_inc; } __packed; -#define GS_CAN_FLAG_OVERFLOW 1 +struct gs_device_bt_const_extended { + __le32 feature; + __le32 fclk_can; + __le32 tseg1_min; + __le32 tseg1_max; + __le32 tseg2_min; + __le32 tseg2_max; + __le32 sjw_max; + __le32 brp_min; + __le32 brp_max; + __le32 brp_inc; + + __le32 dtseg1_min; + __le32 dtseg1_max; + __le32 dtseg2_min; + __le32 dtseg2_max; + __le32 dsjw_max; + __le32 dbrp_min; + __le32 dbrp_max; + __le32 dbrp_inc; +} __packed; + +#define GS_CAN_FLAG_OVERFLOW BIT(0) +#define GS_CAN_FLAG_FD BIT(1) +#define GS_CAN_FLAG_BRS BIT(2) +#define GS_CAN_FLAG_ESI BIT(3) + +struct classic_can { + u8 data[8]; +} __packed; + +struct classic_can_quirk { + u8 data[8]; + u8 quirk; +} __packed; + +struct canfd { + u8 data[64]; +} __packed; + +struct canfd_quirk { + u8 data[64]; + u8 quirk; +} __packed; struct gs_host_frame { u32 echo_id; @@ -147,7 +222,12 @@ struct gs_host_frame { u8 flags; u8 reserved; - u8 data[8]; + union { + DECLARE_FLEX_ARRAY(struct classic_can, classic_can); + DECLARE_FLEX_ARRAY(struct classic_can_quirk, classic_can_quirk); + DECLARE_FLEX_ARRAY(struct canfd, canfd); + DECLARE_FLEX_ARRAY(struct canfd_quirk, canfd_quirk); + }; } __packed; /* The GS USB devices make use of the same flags and masks as in * linux/can.h and linux/can/error.h, and no additional mapping is necessary. @@ -158,9 +238,9 @@ struct gs_host_frame { /* Only launch a max of GS_MAX_RX_URBS usb requests at a time. */ #define GS_MAX_RX_URBS 30 /* Maximum number of interfaces the driver supports per device. - * Current hardware only supports 2 interfaces. The future may vary. + * Current hardware only supports 3 interfaces. The future may vary. */ -#define GS_MAX_INTF 2 +#define GS_MAX_INTF 3 struct gs_tx_context { struct gs_can *dev; @@ -176,9 +256,12 @@ struct gs_can { struct usb_device *udev; struct usb_interface *iface; - struct can_bittiming_const bt_const; + struct can_bittiming_const bt_const, data_bt_const; unsigned int channel; /* channel number */ + u32 feature; + unsigned int hf_size_tx; + /* This lock prevents a race condition between xmit and receive. */ spinlock_t tx_ctx_lock; struct gs_tx_context tx_context[GS_MAX_TX_URBS]; @@ -192,6 +275,7 @@ struct gs_usb { struct gs_can *canch[GS_MAX_INTF]; struct usb_anchor rx_submitted; struct usb_device *udev; + unsigned int hf_size_rx; u8 active_channels; }; @@ -258,11 +342,7 @@ static int gs_cmd_reset(struct gs_can *gsdev) usb_sndctrlpipe(interface_to_usbdev(intf), 0), GS_USB_BREQ_MODE, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - gsdev->channel, - 0, - dm, - sizeof(*dm), - 1000); + gsdev->channel, 0, dm, sizeof(*dm), 1000); kfree(dm); @@ -304,6 +384,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) struct gs_host_frame *hf = urb->transfer_buffer; struct gs_tx_context *txc; struct can_frame *cf; + struct canfd_frame *cfd; struct sk_buff *skb; BUG_ON(!usbcan); @@ -332,18 +413,33 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) return; if (hf->echo_id == -1) { /* normal rx */ - skb = alloc_can_skb(dev->netdev, &cf); - if (!skb) - return; + if (hf->flags & GS_CAN_FLAG_FD) { + skb = alloc_canfd_skb(dev->netdev, &cfd); + if (!skb) + return; + + cfd->can_id = le32_to_cpu(hf->can_id); + cfd->len = can_fd_dlc2len(hf->can_dlc); + if (hf->flags & GS_CAN_FLAG_BRS) + cfd->flags |= CANFD_BRS; + if (hf->flags & GS_CAN_FLAG_ESI) + cfd->flags |= CANFD_ESI; + + memcpy(cfd->data, hf->canfd->data, cfd->len); + } else { + skb = alloc_can_skb(dev->netdev, &cf); + if (!skb) + return; - cf->can_id = le32_to_cpu(hf->can_id); + cf->can_id = le32_to_cpu(hf->can_id); + can_frame_set_cc_len(cf, hf->can_dlc, dev->can.ctrlmode); - can_frame_set_cc_len(cf, hf->can_dlc, dev->can.ctrlmode); - memcpy(cf->data, hf->data, 8); + memcpy(cf->data, hf->classic_can->data, 8); - /* ERROR frames tell us information about the controller */ - if (le32_to_cpu(hf->can_id) & CAN_ERR_FLAG) - gs_update_state(dev, cf); + /* ERROR frames tell us information about the controller */ + if (le32_to_cpu(hf->can_id) & CAN_ERR_FLAG) + gs_update_state(dev, cf); + } netdev->stats.rx_packets++; netdev->stats.rx_bytes += hf->can_dlc; @@ -392,14 +488,10 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) } resubmit_urb: - usb_fill_bulk_urb(urb, - usbcan->udev, + usb_fill_bulk_urb(urb, usbcan->udev, usb_rcvbulkpipe(usbcan->udev, GSUSB_ENDPOINT_IN), - hf, - sizeof(struct gs_host_frame), - gs_usb_receive_bulk_callback, - usbcan - ); + hf, dev->parent->hf_size_rx, + gs_usb_receive_bulk_callback, usbcan); rc = usb_submit_urb(urb, GFP_ATOMIC); @@ -436,11 +528,7 @@ static int gs_usb_set_bittiming(struct net_device *netdev) usb_sndctrlpipe(interface_to_usbdev(intf), 0), GS_USB_BREQ_BITTIMING, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - dev->channel, - 0, - dbt, - sizeof(*dbt), - 1000); + dev->channel, 0, dbt, sizeof(*dbt), 1000); kfree(dbt); @@ -451,6 +539,44 @@ static int gs_usb_set_bittiming(struct net_device *netdev) return (rc > 0) ? 0 : rc; } +static int gs_usb_set_data_bittiming(struct net_device *netdev) +{ + struct gs_can *dev = netdev_priv(netdev); + struct can_bittiming *bt = &dev->can.data_bittiming; + struct usb_interface *intf = dev->iface; + struct gs_device_bittiming *dbt; + u8 request = GS_USB_BREQ_DATA_BITTIMING; + int rc; + + dbt = kmalloc(sizeof(*dbt), GFP_KERNEL); + if (!dbt) + return -ENOMEM; + + dbt->prop_seg = cpu_to_le32(bt->prop_seg); + dbt->phase_seg1 = cpu_to_le32(bt->phase_seg1); + dbt->phase_seg2 = cpu_to_le32(bt->phase_seg2); + dbt->sjw = cpu_to_le32(bt->sjw); + dbt->brp = cpu_to_le32(bt->brp); + + if (dev->feature & GS_CAN_FEATURE_QUIRK_BREQ_CANTACT_PRO) + request = GS_USB_BREQ_QUIRK_CANTACT_PRO_DATA_BITTIMING; + + /* request bit timings */ + rc = usb_control_msg(interface_to_usbdev(intf), + usb_sndctrlpipe(interface_to_usbdev(intf), 0), + request, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + dev->channel, 0, dbt, sizeof(*dbt), 1000); + + kfree(dbt); + + if (rc < 0) + dev_err(netdev->dev.parent, + "Couldn't set data bittimings (err=%d)", rc); + + return (rc > 0) ? 0 : rc; +} + static void gs_usb_xmit_callback(struct urb *urb) { struct gs_tx_context *txc = urb->context; @@ -460,10 +586,8 @@ static void gs_usb_xmit_callback(struct urb *urb) if (urb->status) netdev_info(netdev, "usb xmit fail %u\n", txc->echo_id); - usb_free_coherent(urb->dev, - urb->transfer_buffer_length, - urb->transfer_buffer, - urb->transfer_dma); + usb_free_coherent(urb->dev, urb->transfer_buffer_length, + urb->transfer_buffer, urb->transfer_dma); } static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, @@ -474,6 +598,7 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, struct urb *urb; struct gs_host_frame *hf; struct can_frame *cf; + struct canfd_frame *cfd; int rc; unsigned int idx; struct gs_tx_context *txc; @@ -491,7 +616,7 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, if (!urb) goto nomem_urb; - hf = usb_alloc_coherent(dev->udev, sizeof(*hf), GFP_ATOMIC, + hf = usb_alloc_coherent(dev->udev, dev->hf_size_tx, GFP_ATOMIC, &urb->transfer_dma); if (!hf) { netdev_err(netdev, "No memory left for USB buffer\n"); @@ -510,19 +635,31 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, hf->flags = 0; hf->reserved = 0; - cf = (struct can_frame *)skb->data; + if (can_is_canfd_skb(skb)) { + cfd = (struct canfd_frame *)skb->data; - hf->can_id = cpu_to_le32(cf->can_id); - hf->can_dlc = can_get_cc_dlc(cf, dev->can.ctrlmode); + hf->can_id = cpu_to_le32(cfd->can_id); + hf->can_dlc = can_fd_len2dlc(cfd->len); + hf->flags |= GS_CAN_FLAG_FD; + if (cfd->flags & CANFD_BRS) + hf->flags |= GS_CAN_FLAG_BRS; + if (cfd->flags & CANFD_ESI) + hf->flags |= GS_CAN_FLAG_ESI; - memcpy(hf->data, cf->data, cf->len); + memcpy(hf->canfd->data, cfd->data, cfd->len); + } else { + cf = (struct can_frame *)skb->data; + + hf->can_id = cpu_to_le32(cf->can_id); + hf->can_dlc = can_get_cc_dlc(cf, dev->can.ctrlmode); + + memcpy(hf->classic_can->data, cf->data, cf->len); + } usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, GSUSB_ENDPOINT_OUT), - hf, - sizeof(*hf), - gs_usb_xmit_callback, - txc); + hf, dev->hf_size_tx, + gs_usb_xmit_callback, txc); urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; usb_anchor_urb(urb, &dev->tx_submitted); @@ -539,10 +676,8 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, gs_free_tx_context(txc); usb_unanchor_urb(urb); - usb_free_coherent(dev->udev, - sizeof(*hf), - hf, - urb->transfer_dma); + usb_free_coherent(dev->udev, urb->transfer_buffer_length, + urb->transfer_buffer, urb->transfer_dma); if (rc == -ENODEV) { netif_device_detach(netdev); @@ -562,10 +697,8 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, return NETDEV_TX_OK; badidx: - usb_free_coherent(dev->udev, - sizeof(*hf), - hf, - urb->transfer_dma); + usb_free_coherent(dev->udev, urb->transfer_buffer_length, + urb->transfer_buffer, urb->transfer_dma); nomem_hf: usb_free_urb(urb); @@ -582,6 +715,7 @@ static int gs_can_open(struct net_device *netdev) struct gs_usb *parent = dev->parent; int rc, i; struct gs_device_mode *dm; + struct gs_host_frame *hf; u32 ctrlmode; u32 flags = 0; @@ -589,6 +723,21 @@ static int gs_can_open(struct net_device *netdev) if (rc) return rc; + ctrlmode = dev->can.ctrlmode; + if (ctrlmode & CAN_CTRLMODE_FD) { + flags |= GS_CAN_MODE_FD; + + if (dev->feature & GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX) + dev->hf_size_tx = struct_size(hf, canfd_quirk, 1); + else + dev->hf_size_tx = struct_size(hf, canfd, 1); + } else { + if (dev->feature & GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX) + dev->hf_size_tx = struct_size(hf, classic_can_quirk, 1); + else + dev->hf_size_tx = struct_size(hf, classic_can, 1); + } + if (!parent->active_channels) { for (i = 0; i < GS_MAX_RX_URBS; i++) { struct urb *urb; @@ -601,7 +750,7 @@ static int gs_can_open(struct net_device *netdev) /* alloc rx buffer */ buf = usb_alloc_coherent(dev->udev, - sizeof(struct gs_host_frame), + dev->parent->hf_size_rx, GFP_KERNEL, &urb->transfer_dma); if (!buf) { @@ -617,9 +766,8 @@ static int gs_can_open(struct net_device *netdev) usb_rcvbulkpipe(dev->udev, GSUSB_ENDPOINT_IN), buf, - sizeof(struct gs_host_frame), - gs_usb_receive_bulk_callback, - parent); + dev->parent->hf_size_rx, + gs_usb_receive_bulk_callback, parent); urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; usb_anchor_urb(urb, &parent->rx_submitted); @@ -630,8 +778,7 @@ static int gs_can_open(struct net_device *netdev) netif_device_detach(dev->netdev); netdev_err(netdev, - "usb_submit failed (err=%d)\n", - rc); + "usb_submit failed (err=%d)\n", rc); usb_unanchor_urb(urb); usb_free_urb(urb); @@ -650,8 +797,6 @@ static int gs_can_open(struct net_device *netdev) return -ENOMEM; /* flags */ - ctrlmode = dev->can.ctrlmode; - if (ctrlmode & CAN_CTRLMODE_LOOPBACK) flags |= GS_CAN_MODE_LOOP_BACK; else if (ctrlmode & CAN_CTRLMODE_LISTENONLY) @@ -672,13 +817,8 @@ static int gs_can_open(struct net_device *netdev) rc = usb_control_msg(interface_to_usbdev(dev->iface), usb_sndctrlpipe(interface_to_usbdev(dev->iface), 0), GS_USB_BREQ_MODE, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_INTERFACE, - dev->channel, - 0, - dm, - sizeof(*dm), - 1000); + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + dev->channel, 0, dm, sizeof(*dm), 1000); if (rc < 0) { netdev_err(netdev, "Couldn't start device (err=%d)\n", rc); @@ -755,16 +895,10 @@ static int gs_usb_set_identify(struct net_device *netdev, bool do_identify) imode->mode = cpu_to_le32(GS_CAN_IDENTIFY_OFF); rc = usb_control_msg(interface_to_usbdev(dev->iface), - usb_sndctrlpipe(interface_to_usbdev(dev->iface), - 0), + usb_sndctrlpipe(interface_to_usbdev(dev->iface), 0), GS_USB_BREQ_IDENTIFY, - USB_DIR_OUT | USB_TYPE_VENDOR | - USB_RECIP_INTERFACE, - dev->channel, - 0, - imode, - sizeof(*imode), - 100); + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + dev->channel, 0, imode, sizeof(*imode), 100); kfree(imode); @@ -803,6 +937,7 @@ static struct gs_can *gs_make_candev(unsigned int channel, struct net_device *netdev; int rc; struct gs_device_bt_const *bt_const; + struct gs_device_bt_const_extended *bt_const_extended; u32 feature; bt_const = kmalloc(sizeof(*bt_const), GFP_KERNEL); @@ -814,11 +949,7 @@ static struct gs_can *gs_make_candev(unsigned int channel, usb_rcvctrlpipe(interface_to_usbdev(intf), 0), GS_USB_BREQ_BT_CONST, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - channel, - 0, - bt_const, - sizeof(*bt_const), - 1000); + channel, 0, bt_const, sizeof(*bt_const), 1000); if (rc < 0) { dev_err(&intf->dev, @@ -875,6 +1006,7 @@ static struct gs_can *gs_make_candev(unsigned int channel, dev->can.ctrlmode_supported = CAN_CTRLMODE_CC_LEN8_DLC; feature = le32_to_cpu(bt_const->feature); + dev->feature = FIELD_GET(GS_CAN_FEATURE_MASK, feature); if (feature & GS_CAN_FEATURE_LISTEN_ONLY) dev->can.ctrlmode_supported |= CAN_CTRLMODE_LISTENONLY; @@ -887,7 +1019,37 @@ static struct gs_can *gs_make_candev(unsigned int channel, if (feature & GS_CAN_FEATURE_ONE_SHOT) dev->can.ctrlmode_supported |= CAN_CTRLMODE_ONE_SHOT; - SET_NETDEV_DEV(netdev, &intf->dev); + if (feature & GS_CAN_FEATURE_FD) { + dev->can.ctrlmode_supported |= CAN_CTRLMODE_FD; + /* The data bit timing will be overwritten, if + * GS_CAN_FEATURE_BT_CONST_EXT is set. + */ + dev->can.data_bittiming_const = &dev->bt_const; + dev->can.do_set_data_bittiming = gs_usb_set_data_bittiming; + } + + /* The CANtact Pro from LinkLayer Labs is based on the + * LPC54616 µC, which is affected by the NXP LPC USB transfer + * erratum. However, the current firmware (version 2) doesn't + * set the GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX bit. Set the + * feature GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX to workaround + * this issue. + * + * For the GS_USB_BREQ_DATA_BITTIMING USB control message the + * CANtact Pro firmware uses a request value, which is already + * used by the candleLight firmware for a different purpose + * (GS_USB_BREQ_GET_USER_ID). Set the feature + * GS_CAN_FEATURE_QUIRK_BREQ_CANTACT_PRO to workaround this + * issue. + */ + if (dev->udev->descriptor.idVendor == cpu_to_le16(USB_GSUSB_1_VENDOR_ID) && + dev->udev->descriptor.idProduct == cpu_to_le16(USB_GSUSB_1_PRODUCT_ID) && + dev->udev->manufacturer && dev->udev->product && + !strcmp(dev->udev->manufacturer, "LinkLayer Labs") && + !strcmp(dev->udev->product, "CANtact Pro") && + (le32_to_cpu(dconf->sw_version) <= 2)) + dev->feature |= GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX | + GS_CAN_FEATURE_QUIRK_BREQ_CANTACT_PRO; if (le32_to_cpu(dconf->sw_version) > 1) if (feature & GS_CAN_FEATURE_IDENTIFY) @@ -895,6 +1057,45 @@ static struct gs_can *gs_make_candev(unsigned int channel, kfree(bt_const); + /* fetch extended bit timing constants if device has feature + * GS_CAN_FEATURE_FD and GS_CAN_FEATURE_BT_CONST_EXT + */ + if (feature & GS_CAN_FEATURE_FD && + feature & GS_CAN_FEATURE_BT_CONST_EXT) { + bt_const_extended = kmalloc(sizeof(*bt_const_extended), GFP_KERNEL); + if (!bt_const_extended) + return ERR_PTR(-ENOMEM); + + rc = usb_control_msg(interface_to_usbdev(intf), + usb_rcvctrlpipe(interface_to_usbdev(intf), 0), + GS_USB_BREQ_BT_CONST_EXT, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + channel, 0, bt_const_extended, + sizeof(*bt_const_extended), + 1000); + if (rc < 0) { + dev_err(&intf->dev, + "Couldn't get extended bit timing const for channel (err=%d)\n", + rc); + kfree(bt_const_extended); + return ERR_PTR(rc); + } + + strcpy(dev->data_bt_const.name, "gs_usb"); + dev->data_bt_const.tseg1_min = le32_to_cpu(bt_const_extended->dtseg1_min); + dev->data_bt_const.tseg1_max = le32_to_cpu(bt_const_extended->dtseg1_max); + dev->data_bt_const.tseg2_min = le32_to_cpu(bt_const_extended->dtseg2_min); + dev->data_bt_const.tseg2_max = le32_to_cpu(bt_const_extended->dtseg2_max); + dev->data_bt_const.sjw_max = le32_to_cpu(bt_const_extended->dsjw_max); + dev->data_bt_const.brp_min = le32_to_cpu(bt_const_extended->dbrp_min); + dev->data_bt_const.brp_max = le32_to_cpu(bt_const_extended->dbrp_max); + dev->data_bt_const.brp_inc = le32_to_cpu(bt_const_extended->dbrp_inc); + + dev->can.data_bittiming_const = &dev->data_bt_const; + } + + SET_NETDEV_DEV(netdev, &intf->dev); + rc = register_candev(dev->netdev); if (rc) { free_candev(dev->netdev); @@ -915,6 +1116,8 @@ static void gs_destroy_candev(struct gs_can *dev) static int gs_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { + struct usb_device *udev = interface_to_usbdev(intf); + struct gs_host_frame *hf; struct gs_usb *dev; int rc = -ENOMEM; unsigned int icount, i; @@ -928,21 +1131,16 @@ static int gs_usb_probe(struct usb_interface *intf, hconf->byte_order = cpu_to_le32(0x0000beef); /* send host config */ - rc = usb_control_msg(interface_to_usbdev(intf), - usb_sndctrlpipe(interface_to_usbdev(intf), 0), + rc = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), GS_USB_BREQ_HOST_FORMAT, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - 1, - intf->cur_altsetting->desc.bInterfaceNumber, - hconf, - sizeof(*hconf), - 1000); + 1, intf->cur_altsetting->desc.bInterfaceNumber, + hconf, sizeof(*hconf), 1000); kfree(hconf); if (rc < 0) { - dev_err(&intf->dev, "Couldn't send data format (err=%d)\n", - rc); + dev_err(&intf->dev, "Couldn't send data format (err=%d)\n", rc); return rc; } @@ -951,15 +1149,11 @@ static int gs_usb_probe(struct usb_interface *intf, return -ENOMEM; /* read device config */ - rc = usb_control_msg(interface_to_usbdev(intf), - usb_rcvctrlpipe(interface_to_usbdev(intf), 0), + rc = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), GS_USB_BREQ_DEVICE_CONFIG, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - 1, - intf->cur_altsetting->desc.bInterfaceNumber, - dconf, - sizeof(*dconf), - 1000); + 1, intf->cur_altsetting->desc.bInterfaceNumber, + dconf, sizeof(*dconf), 1000); if (rc < 0) { dev_err(&intf->dev, "Couldn't get device config: (err=%d)\n", rc); @@ -985,9 +1179,13 @@ static int gs_usb_probe(struct usb_interface *intf, } init_usb_anchor(&dev->rx_submitted); + /* default to classic CAN, switch to CAN-FD if at least one of + * our channels support CAN-FD. + */ + dev->hf_size_rx = struct_size(hf, classic_can, 1); usb_set_intfdata(intf, dev); - dev->udev = interface_to_usbdev(intf); + dev->udev = udev; for (i = 0; i < icount; i++) { dev->canch[i] = gs_make_candev(i, intf, dconf); @@ -1006,6 +1204,9 @@ static int gs_usb_probe(struct usb_interface *intf, return rc; } dev->canch[i]->parent = dev; + + if (dev->canch[i]->can.ctrlmode_supported & CAN_CTRLMODE_FD) + dev->hf_size_rx = struct_size(hf, canfd, 1); } kfree(dconf); @@ -1015,8 +1216,9 @@ static int gs_usb_probe(struct usb_interface *intf, static void gs_usb_disconnect(struct usb_interface *intf) { - unsigned i; struct gs_usb *dev = usb_get_intfdata(intf); + unsigned int i; + usb_set_intfdata(intf, NULL); if (!dev) { @@ -1037,16 +1239,20 @@ static const struct usb_device_id gs_usb_table[] = { USB_GSUSB_1_PRODUCT_ID, 0) }, { USB_DEVICE_INTERFACE_NUMBER(USB_CANDLELIGHT_VENDOR_ID, USB_CANDLELIGHT_PRODUCT_ID, 0) }, + { USB_DEVICE_INTERFACE_NUMBER(USB_CES_CANEXT_FD_VENDOR_ID, + USB_CES_CANEXT_FD_PRODUCT_ID, 0) }, + { USB_DEVICE_INTERFACE_NUMBER(USB_ABE_CANDEBUGGER_FD_VENDOR_ID, + USB_ABE_CANDEBUGGER_FD_PRODUCT_ID, 0) }, {} /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, gs_usb_table); static struct usb_driver gs_usb_driver = { - .name = "gs_usb", - .probe = gs_usb_probe, + .name = "gs_usb", + .probe = gs_usb_probe, .disconnect = gs_usb_disconnect, - .id_table = gs_usb_table, + .id_table = gs_usb_table, }; module_usb_driver(gs_usb_driver); diff --git a/drivers/net/can/vxcan.c b/drivers/net/can/vxcan.c index 556f1a12ec9a..94a0c9c6a509 100644 --- a/drivers/net/can/vxcan.c +++ b/drivers/net/can/vxcan.c @@ -33,28 +33,33 @@ struct vxcan_priv { struct net_device __rcu *peer; }; -static netdev_tx_t vxcan_xmit(struct sk_buff *skb, struct net_device *dev) +static netdev_tx_t vxcan_xmit(struct sk_buff *oskb, struct net_device *dev) { struct vxcan_priv *priv = netdev_priv(dev); struct net_device *peer; - struct canfd_frame *cfd = (struct canfd_frame *)skb->data; + struct canfd_frame *cfd = (struct canfd_frame *)oskb->data; struct net_device_stats *peerstats, *srcstats = &dev->stats; + struct sk_buff *skb; u8 len; - if (can_dropped_invalid_skb(dev, skb)) + if (can_dropped_invalid_skb(dev, oskb)) return NETDEV_TX_OK; rcu_read_lock(); peer = rcu_dereference(priv->peer); if (unlikely(!peer)) { - kfree_skb(skb); + kfree_skb(oskb); dev->stats.tx_dropped++; goto out_unlock; } - skb = can_create_echo_skb(skb); - if (!skb) + skb = skb_clone(oskb, GFP_ATOMIC); + if (skb) { + consume_skb(oskb); + } else { + kfree(oskb); goto out_unlock; + } /* reset CAN GW hop counter */ skb->csum_start = 0; @@ -148,7 +153,7 @@ static void vxcan_setup(struct net_device *dev) dev->hard_header_len = 0; dev->addr_len = 0; dev->tx_queue_len = 0; - dev->flags = (IFF_NOARP|IFF_ECHO); + dev->flags = IFF_NOARP; dev->netdev_ops = &vxcan_netdev_ops; dev->needs_free_netdev = true; |