diff options
Diffstat (limited to 'drivers/net/can/rcar/rcar_canfd.c')
-rw-r--r-- | drivers/net/can/rcar/rcar_canfd.c | 309 |
1 files changed, 145 insertions, 164 deletions
diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c index 7f10213738e5..b3c8c592fb0e 100644 --- a/drivers/net/can/rcar/rcar_canfd.c +++ b/drivers/net/can/rcar/rcar_canfd.c @@ -191,9 +191,19 @@ /* RSCFDnCFDCmFDCFG */ #define RCANFD_GEN4_FDCFG_CLOE BIT(30) #define RCANFD_GEN4_FDCFG_FDOE BIT(28) +#define RCANFD_FDCFG_TDCO GENMASK(23, 16) #define RCANFD_FDCFG_TDCE BIT(9) #define RCANFD_FDCFG_TDCOC BIT(8) -#define RCANFD_FDCFG_TDCO(x) (((x) & 0x7f) >> 16) + +/* RSCFDnCFDCmFDSTS */ +#define RCANFD_FDSTS_SOC GENMASK(31, 24) +#define RCANFD_FDSTS_EOC GENMASK(23, 16) +#define RCANFD_GEN4_FDSTS_TDCVF BIT(15) +#define RCANFD_GEN4_FDSTS_PNSTS GENMASK(13, 12) +#define RCANFD_FDSTS_SOCO BIT(9) +#define RCANFD_FDSTS_EOCO BIT(8) +#define RCANFD_FDSTS_TDCVF BIT(7) +#define RCANFD_FDSTS_TDCR GENMASK(7, 0) /* RSCFDnCFDRFCCx */ #define RCANFD_RFCC_RFIM BIT(12) @@ -214,8 +224,6 @@ /* RSCFDnCFDRFPTRx */ #define RCANFD_RFPTR_RFDLC(x) (((x) >> 28) & 0xf) -#define RCANFD_RFPTR_RFPTR(x) (((x) >> 16) & 0xfff) -#define RCANFD_RFPTR_RFTS(x) (((x) >> 0) & 0xffff) /* RSCFDnCFDRFFDSTSx */ #define RCANFD_RFFDSTS_RFFDF BIT(2) @@ -247,12 +255,9 @@ /* RSCFDnCFDCFIDk */ #define RCANFD_CFID_CFIDE BIT(31) #define RCANFD_CFID_CFRTR BIT(30) -#define RCANFD_CFID_CFID_MASK(x) ((x) & 0x1fffffff) /* RSCFDnCFDCFPTRk */ #define RCANFD_CFPTR_CFDLC(x) (((x) & 0xf) << 28) -#define RCANFD_CFPTR_CFPTR(x) (((x) & 0xfff) << 16) -#define RCANFD_CFPTR_CFTS(x) (((x) & 0xff) << 0) /* RSCFDnCFDCFFDCSTSk */ #define RCANFD_CFFDCSTS_CFFDF BIT(2) @@ -318,59 +323,6 @@ #define RCANFD_CFPCTR(gpriv, ch, idx) \ ((gpriv)->info->regs->cfpctr + (0x0c * (ch)) + (0x04 * (idx))) -/* RSCFDnCFDFESTS / RSCFDnFESTS */ -#define RCANFD_FESTS (0x0238) -/* RSCFDnCFDFFSTS / RSCFDnFFSTS */ -#define RCANFD_FFSTS (0x023c) -/* RSCFDnCFDFMSTS / RSCFDnFMSTS */ -#define RCANFD_FMSTS (0x0240) -/* RSCFDnCFDRFISTS / RSCFDnRFISTS */ -#define RCANFD_RFISTS (0x0244) -/* RSCFDnCFDCFRISTS / RSCFDnCFRISTS */ -#define RCANFD_CFRISTS (0x0248) -/* RSCFDnCFDCFTISTS / RSCFDnCFTISTS */ -#define RCANFD_CFTISTS (0x024c) - -/* RSCFDnCFDTMCp / RSCFDnTMCp */ -#define RCANFD_TMC(p) (0x0250 + (0x01 * (p))) -/* RSCFDnCFDTMSTSp / RSCFDnTMSTSp */ -#define RCANFD_TMSTS(p) (0x02d0 + (0x01 * (p))) - -/* RSCFDnCFDTMTRSTSp / RSCFDnTMTRSTSp */ -#define RCANFD_TMTRSTS(y) (0x0350 + (0x04 * (y))) -/* RSCFDnCFDTMTARSTSp / RSCFDnTMTARSTSp */ -#define RCANFD_TMTARSTS(y) (0x0360 + (0x04 * (y))) -/* RSCFDnCFDTMTCSTSp / RSCFDnTMTCSTSp */ -#define RCANFD_TMTCSTS(y) (0x0370 + (0x04 * (y))) -/* RSCFDnCFDTMTASTSp / RSCFDnTMTASTSp */ -#define RCANFD_TMTASTS(y) (0x0380 + (0x04 * (y))) -/* RSCFDnCFDTMIECy / RSCFDnTMIECy */ -#define RCANFD_TMIEC(y) (0x0390 + (0x04 * (y))) - -/* RSCFDnCFDTXQCCm / RSCFDnTXQCCm */ -#define RCANFD_TXQCC(m) (0x03a0 + (0x04 * (m))) -/* RSCFDnCFDTXQSTSm / RSCFDnTXQSTSm */ -#define RCANFD_TXQSTS(m) (0x03c0 + (0x04 * (m))) -/* RSCFDnCFDTXQPCTRm / RSCFDnTXQPCTRm */ -#define RCANFD_TXQPCTR(m) (0x03e0 + (0x04 * (m))) - -/* RSCFDnCFDTHLCCm / RSCFDnTHLCCm */ -#define RCANFD_THLCC(m) (0x0400 + (0x04 * (m))) -/* RSCFDnCFDTHLSTSm / RSCFDnTHLSTSm */ -#define RCANFD_THLSTS(m) (0x0420 + (0x04 * (m))) -/* RSCFDnCFDTHLPCTRm / RSCFDnTHLPCTRm */ -#define RCANFD_THLPCTR(m) (0x0440 + (0x04 * (m))) - -/* RSCFDnCFDGTINTSTS0 / RSCFDnGTINTSTS0 */ -#define RCANFD_GTINTSTS0 (0x0460) -/* RSCFDnCFDGTINTSTS1 / RSCFDnGTINTSTS1 */ -#define RCANFD_GTINTSTS1 (0x0464) -/* RSCFDnCFDGTSTCFG / RSCFDnGTSTCFG */ -#define RCANFD_GTSTCFG (0x0468) -/* RSCFDnCFDGTSTCTR / RSCFDnGTSTCTR */ -#define RCANFD_GTSTCTR (0x046c) -/* RSCFDnCFDGLOCKK / RSCFDnGLOCKK */ -#define RCANFD_GLOCKK (0x047c) /* RSCFDnCFDGRMCFG */ #define RCANFD_GRMCFG (0x04fc) @@ -388,12 +340,6 @@ /* 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))) @@ -413,40 +359,24 @@ #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))) - /* R-Car Gen4 Classical and CAN FD mode specific register map */ -#define RCANFD_GEN4_FDCFG(m) (0x1404 + (0x20 * (m))) - #define RCANFD_GEN4_GAFL_OFFSET (0x1800) /* CAN FD mode specific register map */ -/* RSCFDnCFDCmXXX -> RCANFD_F_XXX(m) */ -#define RCANFD_F_DCFG(gpriv, m) ((gpriv)->info->regs->f_dcfg + (0x20 * (m))) -#define RCANFD_F_CFDCFG(m) (0x0504 + (0x20 * (m))) -#define RCANFD_F_CFDCTR(m) (0x0508 + (0x20 * (m))) -#define RCANFD_F_CFDSTS(m) (0x050c + (0x20 * (m))) -#define RCANFD_F_CFDCRC(m) (0x0510 + (0x20 * (m))) +/* RSCFDnCFDCmXXX -> gpriv->fcbase[m].xxx */ +struct rcar_canfd_f_c { + u32 dcfg; + u32 cfdcfg; + u32 cfdctr; + u32 cfdsts; + u32 cfdcrc; + u32 pad[3]; +}; /* RSCFDnCFDGAFLXXXj offset */ #define RCANFD_F_GAFL_OFFSET (0x1000) -/* RSCFDnCFDRMXXXq -> RCANFD_F_RMXXX(q) */ -#define RCANFD_F_RMID(q) (0x2000 + (0x20 * (q))) -#define RCANFD_F_RMPTR(q) (0x2004 + (0x20 * (q))) -#define RCANFD_F_RMFDSTS(q) (0x2008 + (0x20 * (q))) -#define RCANFD_F_RMDF(q, b) (0x200c + (0x04 * (b)) + (0x20 * (q))) - /* RSCFDnCFDRFXXx -> RCANFD_F_RFXX(x) */ #define RCANFD_F_RFOFFSET(gpriv) ((gpriv)->info->regs->rfoffset) #define RCANFD_F_RFID(gpriv, x) (RCANFD_F_RFOFFSET(gpriv) + (0x80 * (x))) @@ -471,23 +401,11 @@ (RCANFD_F_CFOFFSET(gpriv) + 0x0c + (0x180 * (ch)) + (0x80 * (idx)) + \ (0x04 * (df))) -/* RSCFDnCFDTMXXp -> RCANFD_F_TMXX(p) */ -#define RCANFD_F_TMID(p) (0x4000 + (0x20 * (p))) -#define RCANFD_F_TMPTR(p) (0x4004 + (0x20 * (p))) -#define RCANFD_F_TMFDCTR(p) (0x4008 + (0x20 * (p))) -#define RCANFD_F_TMDF(p, b) (0x400c + (0x20 * (p)) + (0x04 * (b))) - -/* RSCFDnCFDTHLACCm */ -#define RCANFD_F_THLACC(m) (0x6000 + (0x04 * (m))) -/* RSCFDnCFDRPGACCr */ -#define RCANFD_F_RPGACC(r) (0x6400 + (0x04 * (r))) - /* Constants */ #define RCANFD_FIFO_DEPTH 8 /* Tx FIFO depth */ #define RCANFD_NAPI_WEIGHT 8 /* Rx poll quota */ #define RCANFD_NUM_CHANNELS 8 /* Eight channels max */ -#define RCANFD_CHANNELS_MASK BIT((RCANFD_NUM_CHANNELS) - 1) #define RCANFD_GAFL_PAGENUM(entry) ((entry) / 16) #define RCANFD_CHANNEL_NUMRULES 1 /* only one rule per channel */ @@ -510,7 +428,7 @@ struct rcar_canfd_regs { u16 cfcc; /* Common FIFO Configuration/Control Register */ u16 cfsts; /* Common FIFO Status Register */ u16 cfpctr; /* Common FIFO Pointer Control Register */ - u16 f_dcfg; /* Global FD Configuration Register */ + u16 coffset; /* Channel Data Bitrate Configuration Register */ u16 rfoffset; /* Receive FIFO buffer access ID register */ u16 cfoffset; /* Transmit/receive FIFO buffer access ID register */ }; @@ -529,6 +447,7 @@ struct rcar_canfd_shift_data { struct rcar_canfd_hw_info { const struct can_bittiming_const *nom_bittiming; const struct can_bittiming_const *data_bittiming; + const struct can_tdc_const *tdc_const; const struct rcar_canfd_regs *regs; const struct rcar_canfd_shift_data *sh; u8 rnc_field_width; @@ -562,6 +481,7 @@ struct rcar_canfd_channel { struct rcar_canfd_global { struct rcar_canfd_channel *ch[RCANFD_NUM_CHANNELS]; void __iomem *base; /* Register base address */ + struct rcar_canfd_f_c __iomem *fcbase; struct platform_device *pdev; /* Respective platform device */ struct clk *clkp; /* Peripheral clock */ struct clk *can_clk; /* fCAN clock */ @@ -636,12 +556,31 @@ static const struct can_bittiming_const rcar_canfd_bittiming_const = { .brp_inc = 1, }; +/* CAN FD Transmission Delay Compensation constants */ +static const struct can_tdc_const rcar_canfd_gen3_tdc_const = { + .tdcv_min = 1, + .tdcv_max = 128, + .tdco_min = 1, + .tdco_max = 128, + .tdcf_min = 0, /* Filter window not supported */ + .tdcf_max = 0, +}; + +static const struct can_tdc_const rcar_canfd_gen4_tdc_const = { + .tdcv_min = 1, + .tdcv_max = 256, + .tdco_min = 1, + .tdco_max = 256, + .tdcf_min = 0, /* Filter window not supported */ + .tdcf_max = 0, +}; + static const struct rcar_canfd_regs rcar_gen3_regs = { .rfcc = 0x00b8, .cfcc = 0x0118, .cfsts = 0x0178, .cfpctr = 0x01d8, - .f_dcfg = 0x0500, + .coffset = 0x0500, .rfoffset = 0x3000, .cfoffset = 0x3400, }; @@ -651,7 +590,7 @@ static const struct rcar_canfd_regs rcar_gen4_regs = { .cfcc = 0x0120, .cfsts = 0x01e0, .cfpctr = 0x0240, - .f_dcfg = 0x1400, + .coffset = 0x1400, .rfoffset = 0x6000, .cfoffset = 0x6400, }; @@ -681,6 +620,7 @@ static const struct rcar_canfd_shift_data rcar_gen4_shift_data = { static const struct rcar_canfd_hw_info rcar_gen3_hw_info = { .nom_bittiming = &rcar_canfd_gen3_nom_bittiming_const, .data_bittiming = &rcar_canfd_gen3_data_bittiming_const, + .tdc_const = &rcar_canfd_gen3_tdc_const, .regs = &rcar_gen3_regs, .sh = &rcar_gen3_shift_data, .rnc_field_width = 8, @@ -697,6 +637,7 @@ static const struct rcar_canfd_hw_info rcar_gen3_hw_info = { static const struct rcar_canfd_hw_info rcar_gen4_hw_info = { .nom_bittiming = &rcar_canfd_gen4_nom_bittiming_const, .data_bittiming = &rcar_canfd_gen4_data_bittiming_const, + .tdc_const = &rcar_canfd_gen4_tdc_const, .regs = &rcar_gen4_regs, .sh = &rcar_gen4_shift_data, .rnc_field_width = 16, @@ -713,6 +654,7 @@ static const struct rcar_canfd_hw_info rcar_gen4_hw_info = { static const struct rcar_canfd_hw_info rzg2l_hw_info = { .nom_bittiming = &rcar_canfd_gen3_nom_bittiming_const, .data_bittiming = &rcar_canfd_gen3_data_bittiming_const, + .tdc_const = &rcar_canfd_gen3_tdc_const, .regs = &rcar_gen3_regs, .sh = &rcar_gen3_shift_data, .rnc_field_width = 8, @@ -729,6 +671,7 @@ static const struct rcar_canfd_hw_info rzg2l_hw_info = { static const struct rcar_canfd_hw_info r9a09g047_hw_info = { .nom_bittiming = &rcar_canfd_gen4_nom_bittiming_const, .data_bittiming = &rcar_canfd_gen4_data_bittiming_const, + .tdc_const = &rcar_canfd_gen4_tdc_const, .regs = &rcar_gen4_regs, .sh = &rcar_gen4_shift_data, .rnc_field_width = 16, @@ -778,26 +721,36 @@ static void rcar_canfd_update_bit(void __iomem *base, u32 reg, rcar_canfd_update(mask, val, base + reg); } +static void rcar_canfd_set_bit_reg(void __iomem *addr, u32 val) +{ + rcar_canfd_update(val, val, addr); +} + +static void rcar_canfd_update_bit_reg(void __iomem *addr, u32 mask, u32 val) +{ + rcar_canfd_update(mask, val, addr); +} + static void rcar_canfd_get_data(struct rcar_canfd_channel *priv, struct canfd_frame *cf, u32 off) { + u32 *data = (u32 *)cf->data; u32 i, lwords; lwords = DIV_ROUND_UP(cf->len, sizeof(u32)); for (i = 0; i < lwords; i++) - *((u32 *)cf->data + i) = - rcar_canfd_read(priv->base, off + i * sizeof(u32)); + data[i] = rcar_canfd_read(priv->base, off + i * sizeof(u32)); } static void rcar_canfd_put_data(struct rcar_canfd_channel *priv, struct canfd_frame *cf, u32 off) { + const u32 *data = (u32 *)cf->data; u32 i, lwords; lwords = DIV_ROUND_UP(cf->len, sizeof(u32)); for (i = 0; i < lwords; i++) - rcar_canfd_write(priv->base, off + i * sizeof(u32), - *((u32 *)cf->data + i)); + rcar_canfd_write(priv->base, off + i * sizeof(u32), data[i]); } static void rcar_canfd_tx_failure_cleanup(struct net_device *ndev) @@ -808,8 +761,8 @@ static void rcar_canfd_tx_failure_cleanup(struct net_device *ndev) can_free_echo_skb(ndev, i, NULL); } -static void rcar_canfd_setrnc(struct rcar_canfd_global *gpriv, unsigned int ch, - unsigned int num_rules) +static void rcar_canfd_set_rnc(struct rcar_canfd_global *gpriv, unsigned int ch, + unsigned int num_rules) { unsigned int rnc_stride = 32 / gpriv->info->rnc_field_width; unsigned int shift = 32 - (ch % rnc_stride + 1) * gpriv->info->rnc_field_width; @@ -827,8 +780,7 @@ static void rcar_canfd_set_mode(struct rcar_canfd_global *gpriv) for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) - rcar_canfd_set_bit(gpriv->base, RCANFD_GEN4_FDCFG(ch), - val); + rcar_canfd_set_bit_reg(&gpriv->fcbase[ch].cfdcfg, val); } else { if (gpriv->fdmode) rcar_canfd_set_bit(gpriv->base, RCANFD_GRMCFG, @@ -841,6 +793,7 @@ static void rcar_canfd_set_mode(struct rcar_canfd_global *gpriv) static int rcar_canfd_reset_controller(struct rcar_canfd_global *gpriv) { + struct device *dev = &gpriv->pdev->dev; u32 sts, ch; int err; @@ -850,7 +803,7 @@ static int rcar_canfd_reset_controller(struct rcar_canfd_global *gpriv) err = readl_poll_timeout((gpriv->base + RCANFD_GSTS), sts, !(sts & RCANFD_GSTS_GRAMINIT), 2, 500000); if (err) { - dev_dbg(&gpriv->pdev->dev, "global raminit failed\n"); + dev_dbg(dev, "global raminit failed\n"); return err; } @@ -863,7 +816,7 @@ static int rcar_canfd_reset_controller(struct rcar_canfd_global *gpriv) err = readl_poll_timeout((gpriv->base + RCANFD_GSTS), sts, (sts & RCANFD_GSTS_GRSTSTS), 2, 500000); if (err) { - dev_dbg(&gpriv->pdev->dev, "global reset failed\n"); + dev_dbg(dev, "global reset failed\n"); return err; } @@ -887,8 +840,7 @@ static int rcar_canfd_reset_controller(struct rcar_canfd_global *gpriv) (sts & RCANFD_CSTS_CRSTSTS), 2, 500000); if (err) { - dev_dbg(&gpriv->pdev->dev, - "channel %u reset failed\n", ch); + dev_dbg(dev, "channel %u reset failed\n", ch); return err; } } @@ -938,7 +890,7 @@ static void rcar_canfd_configure_afl_rules(struct rcar_canfd_global *gpriv, RCANFD_GAFLECTR_AFLDAE)); /* Write number of rules for channel */ - rcar_canfd_setrnc(gpriv, ch, num_rules); + rcar_canfd_set_rnc(gpriv, ch, num_rules); if (gpriv->info->shared_can_regs) offset = RCANFD_GEN4_GAFL_OFFSET; else if (gpriv->fdmode) @@ -1436,14 +1388,17 @@ static irqreturn_t rcar_canfd_channel_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static void rcar_canfd_set_bittiming(struct net_device *dev) +static void rcar_canfd_set_bittiming(struct net_device *ndev) { - struct rcar_canfd_channel *priv = netdev_priv(dev); + u32 mask = RCANFD_FDCFG_TDCO | RCANFD_FDCFG_TDCE | RCANFD_FDCFG_TDCOC; + struct rcar_canfd_channel *priv = netdev_priv(ndev); struct rcar_canfd_global *gpriv = priv->gpriv; const struct can_bittiming *bt = &priv->can.bittiming; const struct can_bittiming *dbt = &priv->can.fd.data_bittiming; + const struct can_tdc_const *tdc_const = priv->can.fd.tdc_const; + const struct can_tdc *tdc = &priv->can.fd.tdc; + u32 cfg, tdcmode = 0, tdco = 0; u16 brp, sjw, tseg1, tseg2; - u32 cfg; u32 ch = priv->channel; /* Nominal bit timing settings */ @@ -1452,46 +1407,43 @@ static void rcar_canfd_set_bittiming(struct net_device *dev) tseg1 = bt->prop_seg + bt->phase_seg1 - 1; tseg2 = bt->phase_seg2 - 1; - if (priv->can.ctrlmode & CAN_CTRLMODE_FD) { - /* CAN FD only mode */ + if ((priv->can.ctrlmode & CAN_CTRLMODE_FD) || gpriv->info->shared_can_regs) { 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, "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; - - cfg = (RCANFD_DCFG_DTSEG1(gpriv, tseg1) | RCANFD_DCFG_DBRP(brp) | - RCANFD_DCFG_DSJW(gpriv, sjw) | RCANFD_DCFG_DTSEG2(gpriv, tseg2)); + rcar_canfd_write(priv->base, RCANFD_CCFG(ch), cfg); - rcar_canfd_write(priv->base, RCANFD_F_DCFG(gpriv, 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 */ - if (gpriv->info->shared_can_regs) { - 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)); - } + if (!(priv->can.ctrlmode & CAN_CTRLMODE_FD)) + return; - 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); + /* 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(gpriv, tseg1) | RCANFD_DCFG_DBRP(brp) | + RCANFD_DCFG_DSJW(gpriv, sjw) | RCANFD_DCFG_DTSEG2(gpriv, tseg2)); + + writel(cfg, &gpriv->fcbase[ch].dcfg); + + /* Transceiver Delay Compensation */ + if (priv->can.ctrlmode & CAN_CTRLMODE_TDC_AUTO) { + /* TDC enabled, measured + offset */ + tdcmode = RCANFD_FDCFG_TDCE; + tdco = tdc->tdco - 1; + } else if (priv->can.ctrlmode & CAN_CTRLMODE_TDC_MANUAL) { + /* TDC enabled, offset only */ + tdcmode = RCANFD_FDCFG_TDCE | RCANFD_FDCFG_TDCOC; + tdco = min(tdc->tdcv + tdc->tdco, tdc_const->tdco_max) - 1; } + + rcar_canfd_update_bit_reg(&gpriv->fcbase[ch].cfdcfg, mask, + tdcmode | FIELD_PREP(RCANFD_FDCFG_TDCO, tdco)); } static int rcar_canfd_start(struct net_device *ndev) @@ -1691,7 +1643,8 @@ 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 net_device *ndev = priv->ndev; + struct net_device_stats *stats = &ndev->stats; struct rcar_canfd_global *gpriv = priv->gpriv; struct canfd_frame *cf; struct sk_buff *skb; @@ -1707,14 +1660,13 @@ static void rcar_canfd_rx_pkt(struct rcar_canfd_channel *priv) if ((priv->can.ctrlmode & CAN_CTRLMODE_FD) && sts & RCANFD_RFFDSTS_RFFDF) - skb = alloc_canfd_skb(priv->ndev, &cf); + skb = alloc_canfd_skb(ndev, &cf); else - skb = alloc_can_skb(priv->ndev, - (struct can_frame **)&cf); + skb = alloc_can_skb(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); + skb = alloc_can_skb(ndev, (struct can_frame **)&cf); } if (!skb) { @@ -1735,7 +1687,7 @@ static void rcar_canfd_rx_pkt(struct rcar_canfd_channel *priv) if (sts & RCANFD_RFFDSTS_RFESI) { cf->flags |= CANFD_ESI; - netdev_dbg(priv->ndev, "ESI Error\n"); + netdev_dbg(ndev, "ESI Error\n"); } if (!(sts & RCANFD_RFFDSTS_RFFDF) && (id & RCANFD_RFID_RFRTR)) { @@ -1802,6 +1754,29 @@ static int rcar_canfd_rx_poll(struct napi_struct *napi, int quota) return num_pkts; } +static unsigned int rcar_canfd_get_tdcr(struct rcar_canfd_global *gpriv, + unsigned int ch) +{ + u32 sts = readl(&gpriv->fcbase[ch].cfdsts); + u32 tdcr = FIELD_GET(RCANFD_FDSTS_TDCR, sts); + + return tdcr & (gpriv->info->tdc_const->tdcv_max - 1); +} + +static int rcar_canfd_get_auto_tdcv(const struct net_device *ndev, u32 *tdcv) +{ + struct rcar_canfd_channel *priv = netdev_priv(ndev); + u32 tdco = priv->can.fd.tdc.tdco; + u32 tdcr; + + /* Transceiver Delay Compensation Result */ + tdcr = rcar_canfd_get_tdcr(priv->gpriv, priv->channel) + 1; + + *tdcv = tdcr < tdco ? 0 : tdcr - tdco; + + return 0; +} + static int rcar_canfd_do_set_mode(struct net_device *ndev, enum can_mode mode) { int err; @@ -1818,10 +1793,10 @@ static int rcar_canfd_do_set_mode(struct net_device *ndev, enum can_mode mode) } } -static int rcar_canfd_get_berr_counter(const struct net_device *dev, +static int rcar_canfd_get_berr_counter(const struct net_device *ndev, struct can_berr_counter *bec) { - struct rcar_canfd_channel *priv = netdev_priv(dev); + struct rcar_canfd_channel *priv = netdev_priv(ndev); u32 val, ch = priv->channel; /* Peripheral clock is already enabled in probe */ @@ -1924,12 +1899,17 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch, if (gpriv->fdmode) { priv->can.bittiming_const = gpriv->info->nom_bittiming; priv->can.fd.data_bittiming_const = gpriv->info->data_bittiming; + priv->can.fd.tdc_const = gpriv->info->tdc_const; /* Controller starts in CAN FD only mode */ err = can_set_static_ctrlmode(ndev, CAN_CTRLMODE_FD); if (err) goto fail; - priv->can.ctrlmode_supported = CAN_CTRLMODE_BERR_REPORTING; + + priv->can.ctrlmode_supported = CAN_CTRLMODE_BERR_REPORTING | + CAN_CTRLMODE_TDC_AUTO | + CAN_CTRLMODE_TDC_MANUAL; + priv->can.fd.do_get_auto_tdcv = rcar_canfd_get_auto_tdcv; } else { /* Controller starts in Classical CAN only mode */ priv->can.bittiming_const = &rcar_canfd_bittiming_const; @@ -2086,6 +2066,7 @@ static int rcar_canfd_probe(struct platform_device *pdev) goto fail_dev; } gpriv->base = addr; + gpriv->fcbase = addr + gpriv->info->regs->coffset; /* Request IRQ that's common for both channels */ if (info->shared_global_irqs) { |