linux-can-next-for-6.16-20250522

-----BEGIN PGP SIGNATURE-----
 
 iQFHBAABCgAxFiEEn/sM2K9nqF/8FWzzDHRl3/mQkZwFAmgu4Z8THG1rbEBwZW5n
 dXRyb25peC5kZQAKCRAMdGXf+ZCRnBV7B/9i36vJXJuRMvLhP6vQNeEtixa5YkWe
 AZ/ALtAlYVzQXIKYJs7st+bxzQLmN7BfvcGdtXmtgIsNttNL1Kl1asvKFuRN3hqp
 CNjH83vqmoJMbKjcnPmxi/t3IfprfTU99g34gz5ayJN15rYptQAZRIFoX63Di6jC
 XvJbhM2ztJqHA5o5kMseCJ8kRq+RCAunI5Z1hltaAUWmypdc1RPWAJQed4x1ssSM
 8ctyWGy32ctyIoZ+B8tXzE3FoTay5UditN0lfdOe9pE+j6ZeYZRKdquKh4gLvK9c
 mFjxQm/TqbWWIWuts30iy2dp2PgNEyFrcJUZWu8/y5rhZSQQeqzQww8v
 =ILU2
 -----END PGP SIGNATURE-----

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

Marc Kleine-Budde says:

====================
pull-request: can-next 2025-05-22

this is a pull request of 22 patches for net-next/main.

The series by Biju Das contains 19 patches and adds RZ/G3E CANFD
support to the rcar_canfd driver.

The patch by Vincent Mailhol adds a struct data_bittiming_params to
group FD parameters as a preparation patch for CAN-XL support.

Felix Maurer's patch imports tst-filter from can-tests into the kernel
self tests and Vincent Mailhol adds support for physical CAN
interfaces.

linux-can-next-for-6.16-20250522

* tag 'linux-can-next-for-6.16-20250522' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next: (22 commits)
  selftests: can: test_raw_filter.sh: add support of physical interfaces
  selftests: can: Import tst-filter from can-tests
  can: dev: add struct data_bittiming_params to group FD parameters
  can: rcar_canfd: Add RZ/G3E support
  can: rcar_canfd: Enhance multi_channel_irqs handling
  can: rcar_canfd: Add external_clk variable to struct rcar_canfd_hw_info
  can: rcar_canfd: Add sh variable to struct rcar_canfd_hw_info
  can: rcar_canfd: Add struct rcanfd_regs variable to struct rcar_canfd_hw_info
  can: rcar_canfd: Add shared_can_regs variable to struct rcar_canfd_hw_info
  can: rcar_canfd: Add ch_interface_mode variable to struct rcar_canfd_hw_info
  can: rcar_canfd: Add {nom,data}_bittiming variables to struct rcar_canfd_hw_info
  can: rcar_canfd: Add max_cftml variable to struct rcar_canfd_hw_info
  can: rcar_canfd: Add max_aflpn variable to struct rcar_canfd_hw_info
  can: rcar_canfd: Add rnc_field_width variable to struct rcar_canfd_hw_info
  can: rcar_canfd: Update RCANFD_GAFLCFG macro
  can: rcar_canfd: Add rcar_canfd_setrnc()
  can: rcar_canfd: Drop the mask operation in RCANFD_GAFLCFG_SETRNC macro
  can: rcar_canfd: Update RCANFD_GERFL_ERR macro
  can: rcar_canfd: Drop RCANFD_GAFLCFG_GETRNC macro
  can: rcar_canfd: Use of_get_available_child_by_name()
  ...
====================

Link: https://patch.msgid.link/20250522084128.501049-1-mkl@pengutronix.de
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
Paolo Abeni 2025-05-26 18:11:23 +02:00
commit 34d26315db
28 changed files with 922 additions and 221 deletions

View File

@ -42,19 +42,80 @@ properties:
- renesas,r9a07g054-canfd # RZ/V2L - renesas,r9a07g054-canfd # RZ/V2L
- const: renesas,rzg2l-canfd # RZ/G2L family - const: renesas,rzg2l-canfd # RZ/G2L family
- const: renesas,r9a09g047-canfd # RZ/G3E
reg: reg:
maxItems: 1 maxItems: 1
interrupts: true interrupts:
oneOf:
- items:
- description: Channel interrupt
- description: Global interrupt
- items:
- description: CAN global error interrupt
- description: CAN receive FIFO interrupt
- description: CAN0 error interrupt
- description: CAN0 transmit interrupt
- description: CAN0 transmit/receive FIFO receive completion interrupt
- description: CAN1 error interrupt
- description: CAN1 transmit interrupt
- description: CAN1 transmit/receive FIFO receive completion interrupt
- description: CAN2 error interrupt
- description: CAN2 transmit interrupt
- description: CAN2 transmit/receive FIFO receive completion interrupt
- description: CAN3 error interrupt
- description: CAN3 transmit interrupt
- description: CAN3 transmit/receive FIFO receive completion interrupt
- description: CAN4 error interrupt
- description: CAN4 transmit interrupt
- description: CAN4 transmit/receive FIFO receive completion interrupt
- description: CAN5 error interrupt
- description: CAN5 transmit interrupt
- description: CAN5 transmit/receive FIFO receive completion interrupt
minItems: 8
interrupt-names:
oneOf:
- items:
- const: ch_int
- const: g_int
- items:
- const: g_err
- const: g_recc
- const: ch0_err
- const: ch0_rec
- const: ch0_trx
- const: ch1_err
- const: ch1_rec
- const: ch1_trx
- const: ch2_err
- const: ch2_rec
- const: ch2_trx
- const: ch3_err
- const: ch3_rec
- const: ch3_trx
- const: ch4_err
- const: ch4_rec
- const: ch4_trx
- const: ch5_err
- const: ch5_rec
- const: ch5_trx
minItems: 8
clocks: clocks:
maxItems: 3 maxItems: 3
clock-names: clock-names:
items: oneOf:
- const: fck - items:
- const: canfd - const: fck
- const: can_clk - const: canfd
- const: can_clk
- items:
- const: fck
- const: ram_clk
- const: can_clk
power-domains: power-domains:
maxItems: 1 maxItems: 1
@ -117,52 +178,77 @@ allOf:
then: then:
properties: properties:
interrupts: interrupts:
items: maxItems: 8
- description: CAN global error interrupt
- description: CAN receive FIFO interrupt
- description: CAN0 error interrupt
- description: CAN0 transmit interrupt
- description: CAN0 transmit/receive FIFO receive completion interrupt
- description: CAN1 error interrupt
- description: CAN1 transmit interrupt
- description: CAN1 transmit/receive FIFO receive completion interrupt
interrupt-names: interrupt-names:
items: maxItems: 8
- const: g_err
- const: g_recc
- const: ch0_err
- const: ch0_rec
- const: ch0_trx
- const: ch1_err
- const: ch1_rec
- const: ch1_trx
resets: resets:
minItems: 2
maxItems: 2 maxItems: 2
reset-names: reset-names:
items: minItems: 2
- const: rstp_n maxItems: 2
- const: rstc_n
required: required:
- reset-names - reset-names
else:
- if:
properties:
compatible:
contains:
enum:
- renesas,rcar-gen3-canfd
- renesas,rcar-gen4-canfd
then:
properties: properties:
interrupts: interrupts:
items: minItems: 2
- description: Channel interrupt maxItems: 2
- description: Global interrupt
interrupt-names: interrupt-names:
items: minItems: 2
- const: ch_int maxItems: 2
- const: g_int
resets: resets:
maxItems: 1 maxItems: 1
- if:
properties:
compatible:
contains:
const: renesas,r9a09g047-canfd
then:
properties:
interrupts:
minItems: 20
interrupt-names:
minItems: 20
resets:
minItems: 2
maxItems: 2
reset-names:
minItems: 2
maxItems: 2
required:
- reset-names
- if:
properties:
compatible:
contains:
enum:
- renesas,rcar-gen3-canfd
- renesas,rzg2l-canfd
then:
patternProperties:
"^channel[2-7]$": false
- if: - if:
properties: properties:
compatible: compatible:
@ -171,16 +257,15 @@ allOf:
then: then:
patternProperties: patternProperties:
"^channel[4-7]$": false "^channel[4-7]$": false
else:
if: - if:
not: properties:
properties: compatible:
compatible: contains:
contains: const: renesas,r9a09g047-canfd
const: renesas,rcar-gen4-canfd then:
then: patternProperties:
patternProperties: "^channel[6-7]$": false
"^channel[2-7]$": false
unevaluatedProperties: false unevaluatedProperties: false

View File

@ -5274,6 +5274,7 @@ F: include/uapi/linux/can/isotp.h
F: include/uapi/linux/can/raw.h F: include/uapi/linux/can/raw.h
F: net/can/ F: net/can/
F: net/sched/em_canid.c F: net/sched/em_canid.c
F: tools/testing/selftests/net/can/
CAN-J1939 NETWORK LAYER CAN-J1939 NETWORK LAYER
M: Robin van der Gracht <robin@protonic.nl> M: Robin van der Gracht <robin@protonic.nl>
@ -17076,6 +17077,7 @@ X: net/ceph/
X: net/mac80211/ X: net/mac80211/
X: net/rfkill/ X: net/rfkill/
X: net/wireless/ X: net/wireless/
X: tools/testing/selftests/net/can/
NETWORKING [IPSEC] NETWORKING [IPSEC]
M: Steffen Klassert <steffen.klassert@secunet.com> M: Steffen Klassert <steffen.klassert@secunet.com>

View File

@ -275,7 +275,7 @@ static int ctucan_set_bittiming(struct net_device *ndev)
static int ctucan_set_data_bittiming(struct net_device *ndev) static int ctucan_set_data_bittiming(struct net_device *ndev)
{ {
struct ctucan_priv *priv = netdev_priv(ndev); struct ctucan_priv *priv = netdev_priv(ndev);
struct can_bittiming *dbt = &priv->can.data_bittiming; struct can_bittiming *dbt = &priv->can.fd.data_bittiming;
/* Note that dbt may be modified here */ /* Note that dbt may be modified here */
return ctucan_set_btr(ndev, dbt, false); return ctucan_set_btr(ndev, dbt, false);
@ -290,7 +290,7 @@ static int ctucan_set_data_bittiming(struct net_device *ndev)
static int ctucan_set_secondary_sample_point(struct net_device *ndev) static int ctucan_set_secondary_sample_point(struct net_device *ndev)
{ {
struct ctucan_priv *priv = netdev_priv(ndev); struct ctucan_priv *priv = netdev_priv(ndev);
struct can_bittiming *dbt = &priv->can.data_bittiming; struct can_bittiming *dbt = &priv->can.fd.data_bittiming;
int ssp_offset = 0; int ssp_offset = 0;
u32 ssp_cfg = 0; /* No SSP by default */ u32 ssp_cfg = 0; /* No SSP by default */
@ -1358,12 +1358,12 @@ int ctucan_probe_common(struct device *dev, void __iomem *addr, int irq, unsigne
priv->ntxbufs = ntxbufs; priv->ntxbufs = ntxbufs;
priv->dev = dev; priv->dev = dev;
priv->can.bittiming_const = &ctu_can_fd_bit_timing_max; priv->can.bittiming_const = &ctu_can_fd_bit_timing_max;
priv->can.data_bittiming_const = &ctu_can_fd_bit_timing_data_max; priv->can.fd.data_bittiming_const = &ctu_can_fd_bit_timing_data_max;
priv->can.do_set_mode = ctucan_do_set_mode; priv->can.do_set_mode = ctucan_do_set_mode;
/* Needed for timing adjustment to be performed as soon as possible */ /* Needed for timing adjustment to be performed as soon as possible */
priv->can.do_set_bittiming = ctucan_set_bittiming; priv->can.do_set_bittiming = ctucan_set_bittiming;
priv->can.do_set_data_bittiming = ctucan_set_data_bittiming; priv->can.fd.do_set_data_bittiming = ctucan_set_data_bittiming;
priv->can.do_get_berr_counter = ctucan_get_berr_counter; priv->can.do_get_berr_counter = ctucan_get_berr_counter;
priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK

View File

@ -404,8 +404,8 @@ int open_candev(struct net_device *dev)
/* For CAN FD the data bitrate has to be >= the arbitration bitrate */ /* For CAN FD the data bitrate has to be >= the arbitration bitrate */
if ((priv->ctrlmode & CAN_CTRLMODE_FD) && if ((priv->ctrlmode & CAN_CTRLMODE_FD) &&
(!priv->data_bittiming.bitrate || (!priv->fd.data_bittiming.bitrate ||
priv->data_bittiming.bitrate < priv->bittiming.bitrate)) { priv->fd.data_bittiming.bitrate < priv->bittiming.bitrate)) {
netdev_err(dev, "incorrect/missing data bit-timing\n"); netdev_err(dev, "incorrect/missing data bit-timing\n");
return -EINVAL; return -EINVAL;
} }
@ -543,16 +543,16 @@ int register_candev(struct net_device *dev)
if (!priv->bitrate_const != !priv->bitrate_const_cnt) if (!priv->bitrate_const != !priv->bitrate_const_cnt)
return -EINVAL; return -EINVAL;
if (!priv->data_bitrate_const != !priv->data_bitrate_const_cnt) if (!priv->fd.data_bitrate_const != !priv->fd.data_bitrate_const_cnt)
return -EINVAL; return -EINVAL;
/* We only support either fixed bit rates or bit timing const. */ /* We only support either fixed bit rates or bit timing const. */
if ((priv->bitrate_const || priv->data_bitrate_const) && if ((priv->bitrate_const || priv->fd.data_bitrate_const) &&
(priv->bittiming_const || priv->data_bittiming_const)) (priv->bittiming_const || priv->fd.data_bittiming_const))
return -EINVAL; return -EINVAL;
if (!can_bittiming_const_valid(priv->bittiming_const) || if (!can_bittiming_const_valid(priv->bittiming_const) ||
!can_bittiming_const_valid(priv->data_bittiming_const)) !can_bittiming_const_valid(priv->fd.data_bittiming_const))
return -EINVAL; return -EINVAL;
if (!priv->termination_const) { if (!priv->termination_const) {

View File

@ -141,7 +141,7 @@ static int can_tdc_changelink(struct can_priv *priv, const struct nlattr *nla,
{ {
struct nlattr *tb_tdc[IFLA_CAN_TDC_MAX + 1]; struct nlattr *tb_tdc[IFLA_CAN_TDC_MAX + 1];
struct can_tdc tdc = { 0 }; struct can_tdc tdc = { 0 };
const struct can_tdc_const *tdc_const = priv->tdc_const; const struct can_tdc_const *tdc_const = priv->fd.tdc_const;
int err; int err;
if (!tdc_const || !can_tdc_is_enabled(priv)) if (!tdc_const || !can_tdc_is_enabled(priv))
@ -179,7 +179,7 @@ static int can_tdc_changelink(struct can_priv *priv, const struct nlattr *nla,
tdc.tdcf = tdcf; tdc.tdcf = tdcf;
} }
priv->tdc = tdc; priv->fd.tdc = tdc;
return 0; return 0;
} }
@ -228,10 +228,10 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
dev->mtu = CANFD_MTU; dev->mtu = CANFD_MTU;
} else { } else {
dev->mtu = CAN_MTU; dev->mtu = CAN_MTU;
memset(&priv->data_bittiming, 0, memset(&priv->fd.data_bittiming, 0,
sizeof(priv->data_bittiming)); sizeof(priv->fd.data_bittiming));
priv->ctrlmode &= ~CAN_CTRLMODE_TDC_MASK; priv->ctrlmode &= ~CAN_CTRLMODE_TDC_MASK;
memset(&priv->tdc, 0, sizeof(priv->tdc)); memset(&priv->fd.tdc, 0, sizeof(priv->fd.tdc));
} }
tdc_mask = cm->mask & CAN_CTRLMODE_TDC_MASK; tdc_mask = cm->mask & CAN_CTRLMODE_TDC_MASK;
@ -312,16 +312,16 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
* directly via do_set_bitrate(). Bail out if neither * directly via do_set_bitrate(). Bail out if neither
* is given. * is given.
*/ */
if (!priv->data_bittiming_const && !priv->do_set_data_bittiming && if (!priv->fd.data_bittiming_const && !priv->fd.do_set_data_bittiming &&
!priv->data_bitrate_const) !priv->fd.data_bitrate_const)
return -EOPNOTSUPP; return -EOPNOTSUPP;
memcpy(&dbt, nla_data(data[IFLA_CAN_DATA_BITTIMING]), memcpy(&dbt, nla_data(data[IFLA_CAN_DATA_BITTIMING]),
sizeof(dbt)); sizeof(dbt));
err = can_get_bittiming(dev, &dbt, err = can_get_bittiming(dev, &dbt,
priv->data_bittiming_const, priv->fd.data_bittiming_const,
priv->data_bitrate_const, priv->fd.data_bitrate_const,
priv->data_bitrate_const_cnt, priv->fd.data_bitrate_const_cnt,
extack); extack);
if (err) if (err)
return err; return err;
@ -333,7 +333,7 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
return -EINVAL; return -EINVAL;
} }
memset(&priv->tdc, 0, sizeof(priv->tdc)); memset(&priv->fd.tdc, 0, sizeof(priv->fd.tdc));
if (data[IFLA_CAN_TDC]) { if (data[IFLA_CAN_TDC]) {
/* TDC parameters are provided: use them */ /* TDC parameters are provided: use them */
err = can_tdc_changelink(priv, data[IFLA_CAN_TDC], err = can_tdc_changelink(priv, data[IFLA_CAN_TDC],
@ -346,17 +346,17 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
/* Neither of TDC parameters nor TDC flags are /* Neither of TDC parameters nor TDC flags are
* provided: do calculation * provided: do calculation
*/ */
can_calc_tdco(&priv->tdc, priv->tdc_const, &dbt, can_calc_tdco(&priv->fd.tdc, priv->fd.tdc_const, &dbt,
&priv->ctrlmode, priv->ctrlmode_supported); &priv->ctrlmode, priv->ctrlmode_supported);
} /* else: both CAN_CTRLMODE_TDC_{AUTO,MANUAL} are explicitly } /* else: both CAN_CTRLMODE_TDC_{AUTO,MANUAL} are explicitly
* turned off. TDC is disabled: do nothing * turned off. TDC is disabled: do nothing
*/ */
memcpy(&priv->data_bittiming, &dbt, sizeof(dbt)); memcpy(&priv->fd.data_bittiming, &dbt, sizeof(dbt));
if (priv->do_set_data_bittiming) { if (priv->fd.do_set_data_bittiming) {
/* Finally, set the bit-timing registers */ /* Finally, set the bit-timing registers */
err = priv->do_set_data_bittiming(dev); err = priv->fd.do_set_data_bittiming(dev);
if (err) if (err)
return err; return err;
} }
@ -394,7 +394,7 @@ static size_t can_tdc_get_size(const struct net_device *dev)
struct can_priv *priv = netdev_priv(dev); struct can_priv *priv = netdev_priv(dev);
size_t size; size_t size;
if (!priv->tdc_const) if (!priv->fd.tdc_const)
return 0; return 0;
size = nla_total_size(0); /* nest IFLA_CAN_TDC */ size = nla_total_size(0); /* nest IFLA_CAN_TDC */
@ -404,17 +404,17 @@ static size_t can_tdc_get_size(const struct net_device *dev)
} }
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCO_MIN */ size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCO_MIN */
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCO_MAX */ size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCO_MAX */
if (priv->tdc_const->tdcf_max) { if (priv->fd.tdc_const->tdcf_max) {
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCF_MIN */ size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCF_MIN */
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCF_MAX */ size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCF_MAX */
} }
if (can_tdc_is_enabled(priv)) { if (can_tdc_is_enabled(priv)) {
if (priv->ctrlmode & CAN_CTRLMODE_TDC_MANUAL || if (priv->ctrlmode & CAN_CTRLMODE_TDC_MANUAL ||
priv->do_get_auto_tdcv) priv->fd.do_get_auto_tdcv)
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCV */ size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCV */
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCO */ size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCO */
if (priv->tdc_const->tdcf_max) if (priv->fd.tdc_const->tdcf_max)
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCF */ size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCF */
} }
@ -442,9 +442,9 @@ static size_t can_get_size(const struct net_device *dev)
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_RESTART_MS */ size += nla_total_size(sizeof(u32)); /* IFLA_CAN_RESTART_MS */
if (priv->do_get_berr_counter) /* IFLA_CAN_BERR_COUNTER */ if (priv->do_get_berr_counter) /* IFLA_CAN_BERR_COUNTER */
size += nla_total_size(sizeof(struct can_berr_counter)); size += nla_total_size(sizeof(struct can_berr_counter));
if (priv->data_bittiming.bitrate) /* IFLA_CAN_DATA_BITTIMING */ if (priv->fd.data_bittiming.bitrate) /* IFLA_CAN_DATA_BITTIMING */
size += nla_total_size(sizeof(struct can_bittiming)); size += nla_total_size(sizeof(struct can_bittiming));
if (priv->data_bittiming_const) /* IFLA_CAN_DATA_BITTIMING_CONST */ if (priv->fd.data_bittiming_const) /* IFLA_CAN_DATA_BITTIMING_CONST */
size += nla_total_size(sizeof(struct can_bittiming_const)); size += nla_total_size(sizeof(struct can_bittiming_const));
if (priv->termination_const) { if (priv->termination_const) {
size += nla_total_size(sizeof(priv->termination)); /* IFLA_CAN_TERMINATION */ size += nla_total_size(sizeof(priv->termination)); /* IFLA_CAN_TERMINATION */
@ -454,9 +454,9 @@ static size_t can_get_size(const struct net_device *dev)
if (priv->bitrate_const) /* IFLA_CAN_BITRATE_CONST */ if (priv->bitrate_const) /* IFLA_CAN_BITRATE_CONST */
size += nla_total_size(sizeof(*priv->bitrate_const) * size += nla_total_size(sizeof(*priv->bitrate_const) *
priv->bitrate_const_cnt); priv->bitrate_const_cnt);
if (priv->data_bitrate_const) /* IFLA_CAN_DATA_BITRATE_CONST */ if (priv->fd.data_bitrate_const) /* IFLA_CAN_DATA_BITRATE_CONST */
size += nla_total_size(sizeof(*priv->data_bitrate_const) * size += nla_total_size(sizeof(*priv->fd.data_bitrate_const) *
priv->data_bitrate_const_cnt); priv->fd.data_bitrate_const_cnt);
size += sizeof(priv->bitrate_max); /* IFLA_CAN_BITRATE_MAX */ size += sizeof(priv->bitrate_max); /* IFLA_CAN_BITRATE_MAX */
size += can_tdc_get_size(dev); /* IFLA_CAN_TDC */ size += can_tdc_get_size(dev); /* IFLA_CAN_TDC */
size += can_ctrlmode_ext_get_size(); /* IFLA_CAN_CTRLMODE_EXT */ size += can_ctrlmode_ext_get_size(); /* IFLA_CAN_CTRLMODE_EXT */
@ -468,8 +468,8 @@ static int can_tdc_fill_info(struct sk_buff *skb, const struct net_device *dev)
{ {
struct nlattr *nest; struct nlattr *nest;
struct can_priv *priv = netdev_priv(dev); struct can_priv *priv = netdev_priv(dev);
struct can_tdc *tdc = &priv->tdc; struct can_tdc *tdc = &priv->fd.tdc;
const struct can_tdc_const *tdc_const = priv->tdc_const; const struct can_tdc_const *tdc_const = priv->fd.tdc_const;
if (!tdc_const) if (!tdc_const)
return 0; return 0;
@ -497,8 +497,8 @@ static int can_tdc_fill_info(struct sk_buff *skb, const struct net_device *dev)
if (priv->ctrlmode & CAN_CTRLMODE_TDC_MANUAL) { if (priv->ctrlmode & CAN_CTRLMODE_TDC_MANUAL) {
tdcv = tdc->tdcv; tdcv = tdc->tdcv;
err = 0; err = 0;
} else if (priv->do_get_auto_tdcv) { } else if (priv->fd.do_get_auto_tdcv) {
err = priv->do_get_auto_tdcv(dev, &tdcv); err = priv->fd.do_get_auto_tdcv(dev, &tdcv);
} }
if (!err && nla_put_u32(skb, IFLA_CAN_TDC_TDCV, tdcv)) if (!err && nla_put_u32(skb, IFLA_CAN_TDC_TDCV, tdcv))
goto err_cancel; goto err_cancel;
@ -564,14 +564,14 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
!priv->do_get_berr_counter(dev, &bec) && !priv->do_get_berr_counter(dev, &bec) &&
nla_put(skb, IFLA_CAN_BERR_COUNTER, sizeof(bec), &bec)) || nla_put(skb, IFLA_CAN_BERR_COUNTER, sizeof(bec), &bec)) ||
(priv->data_bittiming.bitrate && (priv->fd.data_bittiming.bitrate &&
nla_put(skb, IFLA_CAN_DATA_BITTIMING, nla_put(skb, IFLA_CAN_DATA_BITTIMING,
sizeof(priv->data_bittiming), &priv->data_bittiming)) || sizeof(priv->fd.data_bittiming), &priv->fd.data_bittiming)) ||
(priv->data_bittiming_const && (priv->fd.data_bittiming_const &&
nla_put(skb, IFLA_CAN_DATA_BITTIMING_CONST, nla_put(skb, IFLA_CAN_DATA_BITTIMING_CONST,
sizeof(*priv->data_bittiming_const), sizeof(*priv->fd.data_bittiming_const),
priv->data_bittiming_const)) || priv->fd.data_bittiming_const)) ||
(priv->termination_const && (priv->termination_const &&
(nla_put_u16(skb, IFLA_CAN_TERMINATION, priv->termination) || (nla_put_u16(skb, IFLA_CAN_TERMINATION, priv->termination) ||
@ -586,11 +586,11 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
priv->bitrate_const_cnt, priv->bitrate_const_cnt,
priv->bitrate_const)) || priv->bitrate_const)) ||
(priv->data_bitrate_const && (priv->fd.data_bitrate_const &&
nla_put(skb, IFLA_CAN_DATA_BITRATE_CONST, nla_put(skb, IFLA_CAN_DATA_BITRATE_CONST,
sizeof(*priv->data_bitrate_const) * sizeof(*priv->fd.data_bitrate_const) *
priv->data_bitrate_const_cnt, priv->fd.data_bitrate_const_cnt,
priv->data_bitrate_const)) || priv->fd.data_bitrate_const)) ||
(nla_put(skb, IFLA_CAN_BITRATE_MAX, (nla_put(skb, IFLA_CAN_BITRATE_MAX,
sizeof(priv->bitrate_max), sizeof(priv->bitrate_max),

View File

@ -1226,7 +1226,7 @@ static void flexcan_set_bittiming_cbt(const struct net_device *dev)
{ {
struct flexcan_priv *priv = netdev_priv(dev); struct flexcan_priv *priv = netdev_priv(dev);
struct can_bittiming *bt = &priv->can.bittiming; struct can_bittiming *bt = &priv->can.bittiming;
struct can_bittiming *dbt = &priv->can.data_bittiming; struct can_bittiming *dbt = &priv->can.fd.data_bittiming;
struct flexcan_regs __iomem *regs = priv->regs; struct flexcan_regs __iomem *regs = priv->regs;
u32 reg_cbt, reg_fdctrl; u32 reg_cbt, reg_fdctrl;
@ -2239,7 +2239,7 @@ static int flexcan_probe(struct platform_device *pdev)
priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD | priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD |
CAN_CTRLMODE_FD_NON_ISO; CAN_CTRLMODE_FD_NON_ISO;
priv->can.bittiming_const = &flexcan_fd_bittiming_const; priv->can.bittiming_const = &flexcan_fd_bittiming_const;
priv->can.data_bittiming_const = priv->can.fd.data_bittiming_const =
&flexcan_fd_data_bittiming_const; &flexcan_fd_data_bittiming_const;
} else { } else {
priv->can.bittiming_const = &flexcan_bittiming_const; priv->can.bittiming_const = &flexcan_bittiming_const;

View File

@ -669,7 +669,7 @@ static void ifi_canfd_set_bittiming(struct net_device *ndev)
{ {
struct ifi_canfd_priv *priv = netdev_priv(ndev); struct ifi_canfd_priv *priv = netdev_priv(ndev);
const struct can_bittiming *bt = &priv->can.bittiming; const struct can_bittiming *bt = &priv->can.bittiming;
const struct can_bittiming *dbt = &priv->can.data_bittiming; const struct can_bittiming *dbt = &priv->can.fd.data_bittiming;
u16 brp, sjw, tseg1, tseg2, tdc; u16 brp, sjw, tseg1, tseg2, tdc;
/* Configure bit timing */ /* Configure bit timing */
@ -1000,10 +1000,10 @@ static int ifi_canfd_plat_probe(struct platform_device *pdev)
priv->can.clock.freq = readl(addr + IFI_CANFD_CANCLOCK); priv->can.clock.freq = readl(addr + IFI_CANFD_CANCLOCK);
priv->can.bittiming_const = &ifi_canfd_bittiming_const; priv->can.bittiming_const = &ifi_canfd_bittiming_const;
priv->can.data_bittiming_const = &ifi_canfd_bittiming_const; priv->can.fd.data_bittiming_const = &ifi_canfd_bittiming_const;
priv->can.do_set_mode = ifi_canfd_set_mode; priv->can.do_set_mode = ifi_canfd_set_mode;
priv->can.do_get_berr_counter = ifi_canfd_get_berr_counter; priv->can.do_get_berr_counter = ifi_canfd_get_berr_counter;
/* IFI CANFD can do both Bosch FD and ISO FD */ /* IFI CANFD can do both Bosch FD and ISO FD */
priv->can.ctrlmode = CAN_CTRLMODE_FD; priv->can.ctrlmode = CAN_CTRLMODE_FD;

View File

@ -863,7 +863,7 @@ static int kvaser_pciefd_set_bittiming(struct kvaser_pciefd_can *can, bool data)
struct can_bittiming *bt; struct can_bittiming *bt;
if (data) if (data)
bt = &can->can.data_bittiming; bt = &can->can.fd.data_bittiming;
else else
bt = &can->can.bittiming; bt = &can->can.bittiming;
@ -999,9 +999,9 @@ static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie)
spin_lock_init(&can->lock); spin_lock_init(&can->lock);
can->can.bittiming_const = &kvaser_pciefd_bittiming_const; can->can.bittiming_const = &kvaser_pciefd_bittiming_const;
can->can.data_bittiming_const = &kvaser_pciefd_bittiming_const; can->can.fd.data_bittiming_const = &kvaser_pciefd_bittiming_const;
can->can.do_set_bittiming = kvaser_pciefd_set_nominal_bittiming; can->can.do_set_bittiming = kvaser_pciefd_set_nominal_bittiming;
can->can.do_set_data_bittiming = kvaser_pciefd_set_data_bittiming; can->can.fd.do_set_data_bittiming = kvaser_pciefd_set_data_bittiming;
can->can.do_set_mode = kvaser_pciefd_set_mode; can->can.do_set_mode = kvaser_pciefd_set_mode;
can->can.do_get_berr_counter = kvaser_pciefd_get_berr_counter; can->can.do_get_berr_counter = kvaser_pciefd_get_berr_counter;
can->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY | can->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY |

View File

@ -1372,7 +1372,7 @@ static int m_can_set_bittiming(struct net_device *dev)
{ {
struct m_can_classdev *cdev = netdev_priv(dev); struct m_can_classdev *cdev = netdev_priv(dev);
const struct can_bittiming *bt = &cdev->can.bittiming; const struct can_bittiming *bt = &cdev->can.bittiming;
const struct can_bittiming *dbt = &cdev->can.data_bittiming; const struct can_bittiming *dbt = &cdev->can.fd.data_bittiming;
u16 brp, sjw, tseg1, tseg2; u16 brp, sjw, tseg1, tseg2;
u32 reg_btp; u32 reg_btp;
@ -1738,7 +1738,7 @@ static int m_can_dev_setup(struct m_can_classdev *cdev)
if (err) if (err)
return err; return err;
cdev->can.bittiming_const = &m_can_bittiming_const_30X; cdev->can.bittiming_const = &m_can_bittiming_const_30X;
cdev->can.data_bittiming_const = &m_can_data_bittiming_const_30X; cdev->can.fd.data_bittiming_const = &m_can_data_bittiming_const_30X;
break; break;
case 31: case 31:
/* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.1.x */ /* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.1.x */
@ -1746,13 +1746,13 @@ static int m_can_dev_setup(struct m_can_classdev *cdev)
if (err) if (err)
return err; return err;
cdev->can.bittiming_const = &m_can_bittiming_const_31X; cdev->can.bittiming_const = &m_can_bittiming_const_31X;
cdev->can.data_bittiming_const = &m_can_data_bittiming_const_31X; cdev->can.fd.data_bittiming_const = &m_can_data_bittiming_const_31X;
break; break;
case 32: case 32:
case 33: case 33:
/* Support both MCAN version v3.2.x and v3.3.0 */ /* Support both MCAN version v3.2.x and v3.3.0 */
cdev->can.bittiming_const = &m_can_bittiming_const_31X; cdev->can.bittiming_const = &m_can_bittiming_const_31X;
cdev->can.data_bittiming_const = &m_can_data_bittiming_const_31X; cdev->can.fd.data_bittiming_const = &m_can_data_bittiming_const_31X;
niso = m_can_niso_supported(cdev); niso = m_can_niso_supported(cdev);
if (niso < 0) if (niso < 0)

View File

@ -624,7 +624,7 @@ static int peak_canfd_set_data_bittiming(struct net_device *ndev)
{ {
struct peak_canfd_priv *priv = netdev_priv(ndev); struct peak_canfd_priv *priv = netdev_priv(ndev);
return pucan_set_timing_fast(priv, &priv->can.data_bittiming); return pucan_set_timing_fast(priv, &priv->can.fd.data_bittiming);
} }
static int peak_canfd_close(struct net_device *ndev) static int peak_canfd_close(struct net_device *ndev)
@ -813,12 +813,12 @@ struct net_device *alloc_peak_canfd_dev(int sizeof_priv, int index,
/* complete now socket-can initialization side */ /* complete now socket-can initialization side */
priv->can.state = CAN_STATE_STOPPED; priv->can.state = CAN_STATE_STOPPED;
priv->can.bittiming_const = &peak_canfd_nominal_const; priv->can.bittiming_const = &peak_canfd_nominal_const;
priv->can.data_bittiming_const = &peak_canfd_data_const; priv->can.fd.data_bittiming_const = &peak_canfd_data_const;
priv->can.do_set_mode = peak_canfd_set_mode; priv->can.do_set_mode = peak_canfd_set_mode;
priv->can.do_get_berr_counter = peak_canfd_get_berr_counter; priv->can.do_get_berr_counter = peak_canfd_get_berr_counter;
priv->can.do_set_bittiming = peak_canfd_set_bittiming; priv->can.do_set_bittiming = peak_canfd_set_bittiming;
priv->can.do_set_data_bittiming = peak_canfd_set_data_bittiming; priv->can.fd.do_set_data_bittiming = peak_canfd_set_data_bittiming;
priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_LISTENONLY |
CAN_CTRLMODE_3_SAMPLES | CAN_CTRLMODE_3_SAMPLES |

View File

@ -21,6 +21,7 @@
* wherever it is modified to a readable name. * wherever it is modified to a readable name.
*/ */
#include <linux/bitfield.h>
#include <linux/bitmap.h> #include <linux/bitmap.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/can/dev.h> #include <linux/can/dev.h>
@ -74,33 +75,24 @@
#define RCANFD_GSTS_GNOPM (BIT(0) | BIT(1) | BIT(2) | BIT(3)) #define RCANFD_GSTS_GNOPM (BIT(0) | BIT(1) | BIT(2) | BIT(3))
/* RSCFDnCFDGERFL / RSCFDnGERFL */ /* RSCFDnCFDGERFL / RSCFDnGERFL */
#define RCANFD_GERFL_EEF0_7 GENMASK(23, 16) #define RCANFD_GERFL_EEF GENMASK(23, 16)
#define RCANFD_GERFL_EEF(ch) BIT(16 + (ch))
#define RCANFD_GERFL_CMPOF BIT(3) /* CAN FD only */ #define RCANFD_GERFL_CMPOF BIT(3) /* CAN FD only */
#define RCANFD_GERFL_THLES BIT(2) #define RCANFD_GERFL_THLES BIT(2)
#define RCANFD_GERFL_MES BIT(1) #define RCANFD_GERFL_MES BIT(1)
#define RCANFD_GERFL_DEF BIT(0) #define RCANFD_GERFL_DEF BIT(0)
#define RCANFD_GERFL_ERR(gpriv, x) \ #define RCANFD_GERFL_ERR(gpriv, x) \
((x) & (reg_gen4(gpriv, RCANFD_GERFL_EEF0_7, \ ({\
RCANFD_GERFL_EEF(0) | RCANFD_GERFL_EEF(1)) | \ typeof(gpriv) (_gpriv) = (gpriv); \
RCANFD_GERFL_MES | \ ((x) & ((FIELD_PREP(RCANFD_GERFL_EEF, (_gpriv)->channels_mask)) | \
((gpriv)->fdmode ? RCANFD_GERFL_CMPOF : 0))) RCANFD_GERFL_MES | ((_gpriv)->fdmode ? RCANFD_GERFL_CMPOF : 0))); \
})
/* AFL Rx rules registers */ /* AFL Rx rules registers */
/* RSCFDnCFDGAFLCFG0 / RSCFDnGAFLCFG0 */
#define RCANFD_GAFLCFG_SETRNC(gpriv, n, x) \
(((x) & reg_gen4(gpriv, 0x1ff, 0xff)) << \
(reg_gen4(gpriv, 16, 24) - ((n) & 1) * reg_gen4(gpriv, 16, 8)))
#define RCANFD_GAFLCFG_GETRNC(gpriv, n, x) \
(((x) >> (reg_gen4(gpriv, 16, 24) - ((n) & 1) * reg_gen4(gpriv, 16, 8))) & \
reg_gen4(gpriv, 0x1ff, 0xff))
/* RSCFDnCFDGAFLECTR / RSCFDnGAFLECTR */ /* RSCFDnCFDGAFLECTR / RSCFDnGAFLECTR */
#define RCANFD_GAFLECTR_AFLDAE BIT(8) #define RCANFD_GAFLECTR_AFLDAE BIT(8)
#define RCANFD_GAFLECTR_AFLPN(gpriv, x) ((x) & reg_gen4(gpriv, 0x7f, 0x1f)) #define RCANFD_GAFLECTR_AFLPN(gpriv, page_num) ((page_num) & (gpriv)->info->max_aflpn)
/* RSCFDnCFDGAFLIDj / RSCFDnGAFLIDj */ /* RSCFDnCFDGAFLIDj / RSCFDnGAFLIDj */
#define RCANFD_GAFLID_GAFLLB BIT(29) #define RCANFD_GAFLID_GAFLLB BIT(29)
@ -118,13 +110,13 @@
/* RSCFDnCFDCmNCFG - CAN FD only */ /* RSCFDnCFDCmNCFG - CAN FD only */
#define RCANFD_NCFG_NTSEG2(gpriv, x) \ #define RCANFD_NCFG_NTSEG2(gpriv, x) \
(((x) & reg_gen4(gpriv, 0x7f, 0x1f)) << reg_gen4(gpriv, 25, 24)) (((x) & ((gpriv)->info->nom_bittiming->tseg2_max - 1)) << (gpriv)->info->sh->ntseg2)
#define RCANFD_NCFG_NTSEG1(gpriv, x) \ #define RCANFD_NCFG_NTSEG1(gpriv, x) \
(((x) & reg_gen4(gpriv, 0xff, 0x7f)) << reg_gen4(gpriv, 17, 16)) (((x) & ((gpriv)->info->nom_bittiming->tseg1_max - 1)) << (gpriv)->info->sh->ntseg1)
#define RCANFD_NCFG_NSJW(gpriv, x) \ #define RCANFD_NCFG_NSJW(gpriv, x) \
(((x) & reg_gen4(gpriv, 0x7f, 0x1f)) << reg_gen4(gpriv, 10, 11)) (((x) & ((gpriv)->info->nom_bittiming->sjw_max - 1)) << (gpriv)->info->sh->nsjw)
#define RCANFD_NCFG_NBRP(x) (((x) & 0x3ff) << 0) #define RCANFD_NCFG_NBRP(x) (((x) & 0x3ff) << 0)
@ -186,13 +178,13 @@
#define RCANFD_CERFL_ERR(x) ((x) & (0x7fff)) /* above bits 14:0 */ #define RCANFD_CERFL_ERR(x) ((x) & (0x7fff)) /* above bits 14:0 */
/* RSCFDnCFDCmDCFG */ /* RSCFDnCFDCmDCFG */
#define RCANFD_DCFG_DSJW(gpriv, x) (((x) & reg_gen4(gpriv, 0xf, 0x7)) << 24) #define RCANFD_DCFG_DSJW(gpriv, x) (((x) & ((gpriv)->info->data_bittiming->sjw_max - 1)) << 24)
#define RCANFD_DCFG_DTSEG2(gpriv, x) \ #define RCANFD_DCFG_DTSEG2(gpriv, x) \
(((x) & reg_gen4(gpriv, 0x0f, 0x7)) << reg_gen4(gpriv, 16, 20)) (((x) & ((gpriv)->info->data_bittiming->tseg2_max - 1)) << (gpriv)->info->sh->dtseg2)
#define RCANFD_DCFG_DTSEG1(gpriv, x) \ #define RCANFD_DCFG_DTSEG1(gpriv, x) \
(((x) & reg_gen4(gpriv, 0x1f, 0xf)) << reg_gen4(gpriv, 8, 16)) (((x) & ((gpriv)->info->data_bittiming->tseg1_max - 1)) << (gpriv)->info->sh->dtseg1)
#define RCANFD_DCFG_DBRP(x) (((x) & 0xff) << 0) #define RCANFD_DCFG_DBRP(x) (((x) & 0xff) << 0)
@ -233,11 +225,14 @@
/* Common FIFO bits */ /* Common FIFO bits */
/* RSCFDnCFDCFCCk */ /* RSCFDnCFDCFCCk */
#define RCANFD_CFCC_CFTML(gpriv, x) \ #define RCANFD_CFCC_CFTML(gpriv, cftml) \
(((x) & reg_gen4(gpriv, 0x1f, 0xf)) << reg_gen4(gpriv, 16, 20)) ({\
#define RCANFD_CFCC_CFM(gpriv, x) (((x) & 0x3) << reg_gen4(gpriv, 8, 16)) typeof(gpriv) (_gpriv) = (gpriv); \
(((cftml) & (_gpriv)->info->max_cftml) << (_gpriv)->info->sh->cftml); \
})
#define RCANFD_CFCC_CFM(gpriv, x) (((x) & 0x3) << (gpriv)->info->sh->cfm)
#define RCANFD_CFCC_CFIM BIT(12) #define RCANFD_CFCC_CFIM BIT(12)
#define RCANFD_CFCC_CFDC(gpriv, x) (((x) & 0x7) << reg_gen4(gpriv, 21, 8)) #define RCANFD_CFCC_CFDC(gpriv, x) (((x) & 0x7) << (gpriv)->info->sh->cfdc)
#define RCANFD_CFCC_CFPLS(x) (((x) & 0x7) << 4) #define RCANFD_CFCC_CFPLS(x) (((x) & 0x7) << 4)
#define RCANFD_CFCC_CFTXIE BIT(2) #define RCANFD_CFCC_CFTXIE BIT(2)
#define RCANFD_CFCC_CFE BIT(0) #define RCANFD_CFCC_CFE BIT(0)
@ -298,14 +293,14 @@
/* RSCFDnCFDGAFLECTR / RSCFDnGAFLECTR */ /* RSCFDnCFDGAFLECTR / RSCFDnGAFLECTR */
#define RCANFD_GAFLECTR (0x0098) #define RCANFD_GAFLECTR (0x0098)
/* RSCFDnCFDGAFLCFG / RSCFDnGAFLCFG */ /* RSCFDnCFDGAFLCFG / RSCFDnGAFLCFG */
#define RCANFD_GAFLCFG(ch) (0x009c + (0x04 * ((ch) / 2))) #define RCANFD_GAFLCFG(w) (0x009c + (0x04 * (w)))
/* RSCFDnCFDRMNB / RSCFDnRMNB */ /* RSCFDnCFDRMNB / RSCFDnRMNB */
#define RCANFD_RMNB (0x00a4) #define RCANFD_RMNB (0x00a4)
/* RSCFDnCFDRMND / RSCFDnRMND */ /* RSCFDnCFDRMND / RSCFDnRMND */
#define RCANFD_RMND(y) (0x00a8 + (0x04 * (y))) #define RCANFD_RMND(y) (0x00a8 + (0x04 * (y)))
/* RSCFDnCFDRFCCx / RSCFDnRFCCx */ /* RSCFDnCFDRFCCx / RSCFDnRFCCx */
#define RCANFD_RFCC(gpriv, x) (reg_gen4(gpriv, 0x00c0, 0x00b8) + (0x04 * (x))) #define RCANFD_RFCC(gpriv, x) ((gpriv)->info->regs->rfcc + (0x04 * (x)))
/* RSCFDnCFDRFSTSx / RSCFDnRFSTSx */ /* RSCFDnCFDRFSTSx / RSCFDnRFSTSx */
#define RCANFD_RFSTS(gpriv, x) (RCANFD_RFCC(gpriv, x) + 0x20) #define RCANFD_RFSTS(gpriv, x) (RCANFD_RFCC(gpriv, x) + 0x20)
/* RSCFDnCFDRFPCTRx / RSCFDnRFPCTRx */ /* RSCFDnCFDRFPCTRx / RSCFDnRFPCTRx */
@ -315,13 +310,13 @@
/* RSCFDnCFDCFCCx / RSCFDnCFCCx */ /* RSCFDnCFDCFCCx / RSCFDnCFCCx */
#define RCANFD_CFCC(gpriv, ch, idx) \ #define RCANFD_CFCC(gpriv, ch, idx) \
(reg_gen4(gpriv, 0x0120, 0x0118) + (0x0c * (ch)) + (0x04 * (idx))) ((gpriv)->info->regs->cfcc + (0x0c * (ch)) + (0x04 * (idx)))
/* RSCFDnCFDCFSTSx / RSCFDnCFSTSx */ /* RSCFDnCFDCFSTSx / RSCFDnCFSTSx */
#define RCANFD_CFSTS(gpriv, ch, idx) \ #define RCANFD_CFSTS(gpriv, ch, idx) \
(reg_gen4(gpriv, 0x01e0, 0x0178) + (0x0c * (ch)) + (0x04 * (idx))) ((gpriv)->info->regs->cfsts + (0x0c * (ch)) + (0x04 * (idx)))
/* RSCFDnCFDCFPCTRx / RSCFDnCFPCTRx */ /* RSCFDnCFDCFPCTRx / RSCFDnCFPCTRx */
#define RCANFD_CFPCTR(gpriv, ch, idx) \ #define RCANFD_CFPCTR(gpriv, ch, idx) \
(reg_gen4(gpriv, 0x0240, 0x01d8) + (0x0c * (ch)) + (0x04 * (idx))) ((gpriv)->info->regs->cfpctr + (0x0c * (ch)) + (0x04 * (idx)))
/* RSCFDnCFDFESTS / RSCFDnFESTS */ /* RSCFDnCFDFESTS / RSCFDnFESTS */
#define RCANFD_FESTS (0x0238) #define RCANFD_FESTS (0x0238)
@ -437,7 +432,7 @@
/* CAN FD mode specific register map */ /* CAN FD mode specific register map */
/* RSCFDnCFDCmXXX -> RCANFD_F_XXX(m) */ /* RSCFDnCFDCmXXX -> RCANFD_F_XXX(m) */
#define RCANFD_F_DCFG(gpriv, m) (reg_gen4(gpriv, 0x1400, 0x0500) + (0x20 * (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_CFDCFG(m) (0x0504 + (0x20 * (m)))
#define RCANFD_F_CFDCTR(m) (0x0508 + (0x20 * (m))) #define RCANFD_F_CFDCTR(m) (0x0508 + (0x20 * (m)))
#define RCANFD_F_CFDSTS(m) (0x050c + (0x20 * (m))) #define RCANFD_F_CFDSTS(m) (0x050c + (0x20 * (m)))
@ -453,7 +448,7 @@
#define RCANFD_F_RMDF(q, b) (0x200c + (0x04 * (b)) + (0x20 * (q))) #define RCANFD_F_RMDF(q, b) (0x200c + (0x04 * (b)) + (0x20 * (q)))
/* RSCFDnCFDRFXXx -> RCANFD_F_RFXX(x) */ /* RSCFDnCFDRFXXx -> RCANFD_F_RFXX(x) */
#define RCANFD_F_RFOFFSET(gpriv) reg_gen4(gpriv, 0x6000, 0x3000) #define RCANFD_F_RFOFFSET(gpriv) ((gpriv)->info->regs->rfoffset)
#define RCANFD_F_RFID(gpriv, x) (RCANFD_F_RFOFFSET(gpriv) + (0x80 * (x))) #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_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_RFFDSTS(gpriv, x) (RCANFD_F_RFOFFSET(gpriv) + 0x08 + (0x80 * (x)))
@ -461,7 +456,7 @@
(RCANFD_F_RFOFFSET(gpriv) + 0x0c + (0x80 * (x)) + (0x04 * (df))) (RCANFD_F_RFOFFSET(gpriv) + 0x0c + (0x80 * (x)) + (0x04 * (df)))
/* RSCFDnCFDCFXXk -> RCANFD_F_CFXX(ch, k) */ /* RSCFDnCFDCFXXk -> RCANFD_F_CFXX(ch, k) */
#define RCANFD_F_CFOFFSET(gpriv) reg_gen4(gpriv, 0x6400, 0x3400) #define RCANFD_F_CFOFFSET(gpriv) ((gpriv)->info->regs->cfoffset)
#define RCANFD_F_CFID(gpriv, ch, idx) \ #define RCANFD_F_CFID(gpriv, ch, idx) \
(RCANFD_F_CFOFFSET(gpriv) + (0x180 * (ch)) + (0x80 * (idx))) (RCANFD_F_CFOFFSET(gpriv) + (0x180 * (ch)) + (0x80 * (idx)))
@ -510,12 +505,43 @@
struct rcar_canfd_global; struct rcar_canfd_global;
struct rcar_canfd_regs {
u16 rfcc; /* RX FIFO Configuration/Control Register */
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 rfoffset; /* Receive FIFO buffer access ID register */
u16 cfoffset; /* Transmit/receive FIFO buffer access ID register */
};
struct rcar_canfd_shift_data {
u8 ntseg2; /* Nominal Bit Rate Time Segment 2 Control */
u8 ntseg1; /* Nominal Bit Rate Time Segment 1 Control */
u8 nsjw; /* Nominal Bit Rate Resynchronization Jump Width Control */
u8 dtseg2; /* Data Bit Rate Time Segment 2 Control */
u8 dtseg1; /* Data Bit Rate Time Segment 1 Control */
u8 cftml; /* Common FIFO TX Message Buffer Link */
u8 cfm; /* Common FIFO Mode */
u8 cfdc; /* Common FIFO Depth Configuration */
};
struct rcar_canfd_hw_info { struct rcar_canfd_hw_info {
const struct can_bittiming_const *nom_bittiming;
const struct can_bittiming_const *data_bittiming;
const struct rcar_canfd_regs *regs;
const struct rcar_canfd_shift_data *sh;
u8 rnc_field_width;
u8 max_aflpn;
u8 max_cftml;
u8 max_channels; u8 max_channels;
u8 postdiv; u8 postdiv;
/* hardware features */ /* hardware features */
unsigned shared_global_irqs:1; /* Has shared global irqs */ unsigned shared_global_irqs:1; /* Has shared global irqs */
unsigned multi_channel_irqs:1; /* Has multiple channel irqs */ unsigned multi_channel_irqs:1; /* Has multiple channel irqs */
unsigned ch_interface_mode:1; /* Has channel interface mode */
unsigned shared_can_regs:1; /* Has shared classical can registers */
unsigned external_clk:1; /* Has external clock */
}; };
/* Channel priv data */ /* Channel priv data */
@ -548,7 +574,7 @@ struct rcar_canfd_global {
}; };
/* CAN FD mode nominal rate constants */ /* CAN FD mode nominal rate constants */
static const struct can_bittiming_const rcar_canfd_nom_bittiming_const = { static const struct can_bittiming_const rcar_canfd_gen3_nom_bittiming_const = {
.name = RCANFD_DRV_NAME, .name = RCANFD_DRV_NAME,
.tseg1_min = 2, .tseg1_min = 2,
.tseg1_max = 128, .tseg1_max = 128,
@ -560,8 +586,20 @@ static const struct can_bittiming_const rcar_canfd_nom_bittiming_const = {
.brp_inc = 1, .brp_inc = 1,
}; };
static const struct can_bittiming_const rcar_canfd_gen4_nom_bittiming_const = {
.name = RCANFD_DRV_NAME,
.tseg1_min = 2,
.tseg1_max = 256,
.tseg2_min = 2,
.tseg2_max = 128,
.sjw_max = 128,
.brp_min = 1,
.brp_max = 1024,
.brp_inc = 1,
};
/* CAN FD mode data rate constants */ /* CAN FD mode data rate constants */
static const struct can_bittiming_const rcar_canfd_data_bittiming_const = { static const struct can_bittiming_const rcar_canfd_gen3_data_bittiming_const = {
.name = RCANFD_DRV_NAME, .name = RCANFD_DRV_NAME,
.tseg1_min = 2, .tseg1_min = 2,
.tseg1_max = 16, .tseg1_max = 16,
@ -573,6 +611,18 @@ static const struct can_bittiming_const rcar_canfd_data_bittiming_const = {
.brp_inc = 1, .brp_inc = 1,
}; };
static const struct can_bittiming_const rcar_canfd_gen4_data_bittiming_const = {
.name = RCANFD_DRV_NAME,
.tseg1_min = 2,
.tseg1_max = 32,
.tseg2_min = 2,
.tseg2_max = 16,
.sjw_max = 16,
.brp_min = 1,
.brp_max = 256,
.brp_inc = 1,
};
/* Classical CAN mode bitrate constants */ /* Classical CAN mode bitrate constants */
static const struct can_bittiming_const rcar_canfd_bittiming_const = { static const struct can_bittiming_const rcar_canfd_bittiming_const = {
.name = RCANFD_DRV_NAME, .name = RCANFD_DRV_NAME,
@ -586,36 +636,113 @@ static const struct can_bittiming_const rcar_canfd_bittiming_const = {
.brp_inc = 1, .brp_inc = 1,
}; };
static const struct rcar_canfd_regs rcar_gen3_regs = {
.rfcc = 0x00b8,
.cfcc = 0x0118,
.cfsts = 0x0178,
.cfpctr = 0x01d8,
.f_dcfg = 0x0500,
.rfoffset = 0x3000,
.cfoffset = 0x3400,
};
static const struct rcar_canfd_regs rcar_gen4_regs = {
.rfcc = 0x00c0,
.cfcc = 0x0120,
.cfsts = 0x01e0,
.cfpctr = 0x0240,
.f_dcfg = 0x1400,
.rfoffset = 0x6000,
.cfoffset = 0x6400,
};
static const struct rcar_canfd_shift_data rcar_gen3_shift_data = {
.ntseg2 = 24,
.ntseg1 = 16,
.nsjw = 11,
.dtseg2 = 20,
.dtseg1 = 16,
.cftml = 20,
.cfm = 16,
.cfdc = 8,
};
static const struct rcar_canfd_shift_data rcar_gen4_shift_data = {
.ntseg2 = 25,
.ntseg1 = 17,
.nsjw = 10,
.dtseg2 = 16,
.dtseg1 = 8,
.cftml = 16,
.cfm = 8,
.cfdc = 21,
};
static const struct rcar_canfd_hw_info rcar_gen3_hw_info = { 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,
.regs = &rcar_gen3_regs,
.sh = &rcar_gen3_shift_data,
.rnc_field_width = 8,
.max_aflpn = 31,
.max_cftml = 15,
.max_channels = 2, .max_channels = 2,
.postdiv = 2, .postdiv = 2,
.shared_global_irqs = 1, .shared_global_irqs = 1,
.ch_interface_mode = 0,
.shared_can_regs = 0,
.external_clk = 1,
}; };
static const struct rcar_canfd_hw_info rcar_gen4_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,
.regs = &rcar_gen4_regs,
.sh = &rcar_gen4_shift_data,
.rnc_field_width = 16,
.max_aflpn = 127,
.max_cftml = 31,
.max_channels = 8, .max_channels = 8,
.postdiv = 2, .postdiv = 2,
.shared_global_irqs = 1, .shared_global_irqs = 1,
.ch_interface_mode = 1,
.shared_can_regs = 1,
.external_clk = 1,
}; };
static const struct rcar_canfd_hw_info rzg2l_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,
.regs = &rcar_gen3_regs,
.sh = &rcar_gen3_shift_data,
.rnc_field_width = 8,
.max_aflpn = 31,
.max_cftml = 15,
.max_channels = 2, .max_channels = 2,
.postdiv = 1, .postdiv = 1,
.multi_channel_irqs = 1, .multi_channel_irqs = 1,
.ch_interface_mode = 0,
.shared_can_regs = 0,
.external_clk = 1,
};
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,
.regs = &rcar_gen4_regs,
.sh = &rcar_gen4_shift_data,
.rnc_field_width = 16,
.max_aflpn = 63,
.max_cftml = 31,
.max_channels = 6,
.postdiv = 1,
.multi_channel_irqs = 1,
.ch_interface_mode = 1,
.shared_can_regs = 1,
.external_clk = 0,
}; };
/* Helper functions */ /* Helper functions */
static inline bool is_gen4(struct rcar_canfd_global *gpriv)
{
return gpriv->info == &rcar_gen4_hw_info;
}
static inline u32 reg_gen4(struct rcar_canfd_global *gpriv,
u32 gen4, u32 not_gen4)
{
return is_gen4(gpriv) ? gen4 : not_gen4;
}
static inline void rcar_canfd_update(u32 mask, u32 val, u32 __iomem *reg) static inline void rcar_canfd_update(u32 mask, u32 val, u32 __iomem *reg)
{ {
u32 data = readl(reg); u32 data = readl(reg);
@ -681,9 +808,20 @@ static void rcar_canfd_tx_failure_cleanup(struct net_device *ndev)
can_free_echo_skb(ndev, i, NULL); can_free_echo_skb(ndev, i, NULL);
} }
static void rcar_canfd_setrnc(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;
unsigned int w = ch / rnc_stride;
u32 rnc = num_rules << shift;
rcar_canfd_set_bit(gpriv->base, RCANFD_GAFLCFG(w), rnc);
}
static void rcar_canfd_set_mode(struct rcar_canfd_global *gpriv) static void rcar_canfd_set_mode(struct rcar_canfd_global *gpriv)
{ {
if (is_gen4(gpriv)) { if (gpriv->info->ch_interface_mode) {
u32 ch, val = gpriv->fdmode ? RCANFD_GEN4_FDCFG_FDOE u32 ch, val = gpriv->fdmode ? RCANFD_GEN4_FDCFG_FDOE
: RCANFD_GEN4_FDCFG_CLOE; : RCANFD_GEN4_FDCFG_CLOE;
@ -789,7 +927,7 @@ static void rcar_canfd_configure_controller(struct rcar_canfd_global *gpriv)
static void rcar_canfd_configure_afl_rules(struct rcar_canfd_global *gpriv, static void rcar_canfd_configure_afl_rules(struct rcar_canfd_global *gpriv,
u32 ch, u32 rule_entry) u32 ch, u32 rule_entry)
{ {
int offset, page, num_rules = RCANFD_CHANNEL_NUMRULES; unsigned int offset, page, num_rules = RCANFD_CHANNEL_NUMRULES;
u32 rule_entry_index = rule_entry % 16; u32 rule_entry_index = rule_entry % 16;
u32 ridx = ch + RCANFD_RFFIFO_IDX; u32 ridx = ch + RCANFD_RFFIFO_IDX;
@ -800,9 +938,8 @@ static void rcar_canfd_configure_afl_rules(struct rcar_canfd_global *gpriv,
RCANFD_GAFLECTR_AFLDAE)); RCANFD_GAFLECTR_AFLDAE));
/* Write number of rules for channel */ /* Write number of rules for channel */
rcar_canfd_set_bit(gpriv->base, RCANFD_GAFLCFG(ch), rcar_canfd_setrnc(gpriv, ch, num_rules);
RCANFD_GAFLCFG_SETRNC(gpriv, ch, num_rules)); if (gpriv->info->shared_can_regs)
if (is_gen4(gpriv))
offset = RCANFD_GEN4_GAFL_OFFSET; offset = RCANFD_GEN4_GAFL_OFFSET;
else if (gpriv->fdmode) else if (gpriv->fdmode)
offset = RCANFD_F_GAFL_OFFSET; offset = RCANFD_F_GAFL_OFFSET;
@ -942,7 +1079,7 @@ static void rcar_canfd_global_error(struct net_device *ndev)
u32 ridx = ch + RCANFD_RFFIFO_IDX; u32 ridx = ch + RCANFD_RFFIFO_IDX;
gerfl = rcar_canfd_read(priv->base, RCANFD_GERFL); gerfl = rcar_canfd_read(priv->base, RCANFD_GERFL);
if (gerfl & RCANFD_GERFL_EEF(ch)) { if (gerfl & FIELD_PREP(RCANFD_GERFL_EEF, BIT(ch))) {
netdev_dbg(ndev, "Ch%u: ECC Error flag\n", ch); netdev_dbg(ndev, "Ch%u: ECC Error flag\n", ch);
stats->tx_dropped++; stats->tx_dropped++;
} }
@ -1304,7 +1441,7 @@ static void rcar_canfd_set_bittiming(struct net_device *dev)
struct rcar_canfd_channel *priv = netdev_priv(dev); struct rcar_canfd_channel *priv = netdev_priv(dev);
struct rcar_canfd_global *gpriv = priv->gpriv; struct rcar_canfd_global *gpriv = priv->gpriv;
const struct can_bittiming *bt = &priv->can.bittiming; const struct can_bittiming *bt = &priv->can.bittiming;
const struct can_bittiming *dbt = &priv->can.data_bittiming; const struct can_bittiming *dbt = &priv->can.fd.data_bittiming;
u16 brp, sjw, tseg1, tseg2; u16 brp, sjw, tseg1, tseg2;
u32 cfg; u32 cfg;
u32 ch = priv->channel; u32 ch = priv->channel;
@ -1338,7 +1475,7 @@ static void rcar_canfd_set_bittiming(struct net_device *dev)
brp, sjw, tseg1, tseg2); brp, sjw, tseg1, tseg2);
} else { } else {
/* Classical CAN only mode */ /* Classical CAN only mode */
if (is_gen4(gpriv)) { if (gpriv->info->shared_can_regs) {
cfg = (RCANFD_NCFG_NTSEG1(gpriv, tseg1) | cfg = (RCANFD_NCFG_NTSEG1(gpriv, tseg1) |
RCANFD_NCFG_NBRP(brp) | RCANFD_NCFG_NBRP(brp) |
RCANFD_NCFG_NSJW(gpriv, sjw) | RCANFD_NCFG_NSJW(gpriv, sjw) |
@ -1503,7 +1640,7 @@ static netdev_tx_t rcar_canfd_start_xmit(struct sk_buff *skb,
dlc = RCANFD_CFPTR_CFDLC(can_fd_len2dlc(cf->len)); dlc = RCANFD_CFPTR_CFDLC(can_fd_len2dlc(cf->len));
if ((priv->can.ctrlmode & CAN_CTRLMODE_FD) || is_gen4(gpriv)) { if ((priv->can.ctrlmode & CAN_CTRLMODE_FD) || gpriv->info->shared_can_regs) {
rcar_canfd_write(priv->base, rcar_canfd_write(priv->base,
RCANFD_F_CFID(gpriv, ch, RCANFD_CFFIFO_IDX), id); RCANFD_F_CFID(gpriv, ch, RCANFD_CFFIFO_IDX), id);
rcar_canfd_write(priv->base, rcar_canfd_write(priv->base,
@ -1562,7 +1699,7 @@ static void rcar_canfd_rx_pkt(struct rcar_canfd_channel *priv)
u32 ch = priv->channel; u32 ch = priv->channel;
u32 ridx = ch + RCANFD_RFFIFO_IDX; u32 ridx = ch + RCANFD_RFFIFO_IDX;
if ((priv->can.ctrlmode & CAN_CTRLMODE_FD) || is_gen4(gpriv)) { if ((priv->can.ctrlmode & CAN_CTRLMODE_FD) || gpriv->info->shared_can_regs) {
id = rcar_canfd_read(priv->base, RCANFD_F_RFID(gpriv, ridx)); id = rcar_canfd_read(priv->base, RCANFD_F_RFID(gpriv, ridx));
dlc = rcar_canfd_read(priv->base, RCANFD_F_RFPTR(gpriv, ridx)); dlc = rcar_canfd_read(priv->base, RCANFD_F_RFPTR(gpriv, ridx));
@ -1613,7 +1750,7 @@ static void rcar_canfd_rx_pkt(struct rcar_canfd_channel *priv)
cf->len = can_cc_dlc2len(RCANFD_RFPTR_RFDLC(dlc)); cf->len = can_cc_dlc2len(RCANFD_RFPTR_RFDLC(dlc));
if (id & RCANFD_RFID_RFRTR) if (id & RCANFD_RFID_RFRTR)
cf->can_id |= CAN_RTR_FLAG; cf->can_id |= CAN_RTR_FLAG;
else if (is_gen4(gpriv)) else if (gpriv->info->shared_can_regs)
rcar_canfd_get_data(priv, cf, RCANFD_F_RFDF(gpriv, ridx, 0)); rcar_canfd_get_data(priv, cf, RCANFD_F_RFDF(gpriv, ridx, 0));
else else
rcar_canfd_get_data(priv, cf, RCANFD_C_RFDF(ridx, 0)); rcar_canfd_get_data(priv, cf, RCANFD_C_RFDF(ridx, 0));
@ -1736,16 +1873,19 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch,
if (info->multi_channel_irqs) { if (info->multi_channel_irqs) {
char *irq_name; char *irq_name;
char name[10];
int err_irq; int err_irq;
int tx_irq; int tx_irq;
err_irq = platform_get_irq_byname(pdev, ch == 0 ? "ch0_err" : "ch1_err"); scnprintf(name, sizeof(name), "ch%u_err", ch);
err_irq = platform_get_irq_byname(pdev, name);
if (err_irq < 0) { if (err_irq < 0) {
err = err_irq; err = err_irq;
goto fail; goto fail;
} }
tx_irq = platform_get_irq_byname(pdev, ch == 0 ? "ch0_trx" : "ch1_trx"); scnprintf(name, sizeof(name), "ch%u_trx", ch);
tx_irq = platform_get_irq_byname(pdev, name);
if (tx_irq < 0) { if (tx_irq < 0) {
err = tx_irq; err = tx_irq;
goto fail; goto fail;
@ -1782,9 +1922,8 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch,
} }
if (gpriv->fdmode) { if (gpriv->fdmode) {
priv->can.bittiming_const = &rcar_canfd_nom_bittiming_const; priv->can.bittiming_const = gpriv->info->nom_bittiming;
priv->can.data_bittiming_const = priv->can.fd.data_bittiming_const = gpriv->info->data_bittiming;
&rcar_canfd_data_bittiming_const;
/* Controller starts in CAN FD only mode */ /* Controller starts in CAN FD only mode */
err = can_set_static_ctrlmode(ndev, CAN_CTRLMODE_FD); err = can_set_static_ctrlmode(ndev, CAN_CTRLMODE_FD);
@ -1846,6 +1985,7 @@ static int rcar_canfd_probe(struct platform_device *pdev)
u32 rule_entry = 0; u32 rule_entry = 0;
bool fdmode = true; /* CAN FD only mode - default */ bool fdmode = true; /* CAN FD only mode - default */
char name[9] = "channelX"; char name[9] = "channelX";
struct clk *clk_ram;
int i; int i;
info = of_device_get_match_data(dev); info = of_device_get_match_data(dev);
@ -1855,13 +1995,13 @@ static int rcar_canfd_probe(struct platform_device *pdev)
for (i = 0; i < info->max_channels; ++i) { for (i = 0; i < info->max_channels; ++i) {
name[7] = '0' + i; name[7] = '0' + i;
of_child = of_get_child_by_name(dev->of_node, name); of_child = of_get_available_child_by_name(dev->of_node, name);
if (of_child && of_device_is_available(of_child)) { if (of_child) {
channels_mask |= BIT(i); channels_mask |= BIT(i);
transceivers[i] = devm_of_phy_optional_get(dev, transceivers[i] = devm_of_phy_optional_get(dev,
of_child, NULL); of_child, NULL);
of_node_put(of_child);
} }
of_node_put(of_child);
if (IS_ERR(transceivers[i])) if (IS_ERR(transceivers[i]))
return PTR_ERR(transceivers[i]); return PTR_ERR(transceivers[i]);
} }
@ -1932,9 +2072,14 @@ static int rcar_canfd_probe(struct platform_device *pdev)
fcan_freq = clk_get_rate(gpriv->can_clk) / info->postdiv; fcan_freq = clk_get_rate(gpriv->can_clk) / info->postdiv;
} else { } else {
fcan_freq = clk_get_rate(gpriv->can_clk); fcan_freq = clk_get_rate(gpriv->can_clk);
gpriv->extclk = true; gpriv->extclk = gpriv->info->external_clk;
} }
clk_ram = devm_clk_get_optional_enabled(dev, "ram_clk");
if (IS_ERR(clk_ram))
return dev_err_probe(dev, PTR_ERR(clk_ram),
"cannot get enabled ram clock\n");
addr = devm_platform_ioremap_resource(pdev, 0); addr = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(addr)) { if (IS_ERR(addr)) {
err = PTR_ERR(addr); err = PTR_ERR(addr);
@ -2097,6 +2242,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[] = { static const __maybe_unused struct of_device_id rcar_canfd_of_table[] = {
{ .compatible = "renesas,r8a779a0-canfd", .data = &rcar_gen4_hw_info }, { .compatible = "renesas,r8a779a0-canfd", .data = &rcar_gen4_hw_info },
{ .compatible = "renesas,r9a09g047-canfd", .data = &r9a09g047_hw_info },
{ .compatible = "renesas,rcar-gen3-canfd", .data = &rcar_gen3_hw_info }, { .compatible = "renesas,rcar-gen3-canfd", .data = &rcar_gen3_hw_info },
{ .compatible = "renesas,rcar-gen4-canfd", .data = &rcar_gen4_hw_info }, { .compatible = "renesas,rcar-gen4-canfd", .data = &rcar_gen4_hw_info },
{ .compatible = "renesas,rzg2l-canfd", .data = &rzg2l_hw_info }, { .compatible = "renesas,rzg2l-canfd", .data = &rzg2l_hw_info },

View File

@ -118,7 +118,7 @@ static void rkcanfd_chip_set_work_mode(const struct rkcanfd_priv *priv)
static int rkcanfd_set_bittiming(struct rkcanfd_priv *priv) static int rkcanfd_set_bittiming(struct rkcanfd_priv *priv)
{ {
const struct can_bittiming *dbt = &priv->can.data_bittiming; const struct can_bittiming *dbt = &priv->can.fd.data_bittiming;
const struct can_bittiming *bt = &priv->can.bittiming; const struct can_bittiming *bt = &priv->can.bittiming;
u32 reg_nbt, reg_dbt, reg_tdc; u32 reg_nbt, reg_dbt, reg_tdc;
u32 tdco; u32 tdco;
@ -899,7 +899,7 @@ static int rkcanfd_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, priv); platform_set_drvdata(pdev, priv);
priv->can.clock.freq = clk_get_rate(priv->clks[0].clk); priv->can.clock.freq = clk_get_rate(priv->clks[0].clk);
priv->can.bittiming_const = &rkcanfd_bittiming_const; priv->can.bittiming_const = &rkcanfd_bittiming_const;
priv->can.data_bittiming_const = &rkcanfd_data_bittiming_const; priv->can.fd.data_bittiming_const = &rkcanfd_data_bittiming_const;
priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
CAN_CTRLMODE_BERR_REPORTING; CAN_CTRLMODE_BERR_REPORTING;
priv->can.do_set_mode = rkcanfd_set_mode; priv->can.do_set_mode = rkcanfd_set_mode;

View File

@ -39,7 +39,7 @@ static void rkcanfd_timestamp_work(struct work_struct *work)
void rkcanfd_timestamp_init(struct rkcanfd_priv *priv) void rkcanfd_timestamp_init(struct rkcanfd_priv *priv)
{ {
const struct can_bittiming *dbt = &priv->can.data_bittiming; const struct can_bittiming *dbt = &priv->can.fd.data_bittiming;
const struct can_bittiming *bt = &priv->can.bittiming; const struct can_bittiming *bt = &priv->can.bittiming;
struct cyclecounter *cc = &priv->cc; struct cyclecounter *cc = &priv->cc;
u32 bitrate, div, reg, rate; u32 bitrate, div, reg, rate;

View File

@ -527,7 +527,7 @@ static int mcp251xfd_chip_timestamp_init(const struct mcp251xfd_priv *priv)
static int mcp251xfd_set_bittiming(const struct mcp251xfd_priv *priv) static int mcp251xfd_set_bittiming(const struct mcp251xfd_priv *priv)
{ {
const struct can_bittiming *bt = &priv->can.bittiming; const struct can_bittiming *bt = &priv->can.bittiming;
const struct can_bittiming *dbt = &priv->can.data_bittiming; const struct can_bittiming *dbt = &priv->can.fd.data_bittiming;
u32 tdcmod, val = 0; u32 tdcmod, val = 0;
int err; int err;
@ -600,8 +600,8 @@ static int mcp251xfd_set_bittiming(const struct mcp251xfd_priv *priv)
tdcmod = MCP251XFD_REG_TDC_TDCMOD_DISABLED; tdcmod = MCP251XFD_REG_TDC_TDCMOD_DISABLED;
val = FIELD_PREP(MCP251XFD_REG_TDC_TDCMOD_MASK, tdcmod) | val = FIELD_PREP(MCP251XFD_REG_TDC_TDCMOD_MASK, tdcmod) |
FIELD_PREP(MCP251XFD_REG_TDC_TDCV_MASK, priv->can.tdc.tdcv) | FIELD_PREP(MCP251XFD_REG_TDC_TDCV_MASK, priv->can.fd.tdc.tdcv) |
FIELD_PREP(MCP251XFD_REG_TDC_TDCO_MASK, priv->can.tdc.tdco); FIELD_PREP(MCP251XFD_REG_TDC_TDCO_MASK, priv->can.fd.tdc.tdco);
return regmap_write(priv->map_reg, MCP251XFD_REG_TDC, val); return regmap_write(priv->map_reg, MCP251XFD_REG_TDC, val);
} }
@ -2104,8 +2104,8 @@ static int mcp251xfd_probe(struct spi_device *spi)
priv->can.do_set_mode = mcp251xfd_set_mode; priv->can.do_set_mode = mcp251xfd_set_mode;
priv->can.do_get_berr_counter = mcp251xfd_get_berr_counter; priv->can.do_get_berr_counter = mcp251xfd_get_berr_counter;
priv->can.bittiming_const = &mcp251xfd_bittiming_const; priv->can.bittiming_const = &mcp251xfd_bittiming_const;
priv->can.data_bittiming_const = &mcp251xfd_data_bittiming_const; priv->can.fd.data_bittiming_const = &mcp251xfd_data_bittiming_const;
priv->can.tdc_const = &mcp251xfd_tdc_const; priv->can.fd.tdc_const = &mcp251xfd_tdc_const;
priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_BERR_REPORTING | CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_BERR_REPORTING |
CAN_CTRLMODE_FD | CAN_CTRLMODE_FD_NON_ISO | CAN_CTRLMODE_FD | CAN_CTRLMODE_FD_NON_ISO |

View File

@ -1098,7 +1098,7 @@ static int esd_usb_3_set_bittiming(struct net_device *netdev)
const struct can_bittiming_const *data_btc = &esd_usb_3_data_bittiming_const; const struct can_bittiming_const *data_btc = &esd_usb_3_data_bittiming_const;
struct esd_usb_net_priv *priv = netdev_priv(netdev); struct esd_usb_net_priv *priv = netdev_priv(netdev);
struct can_bittiming *nom_bt = &priv->can.bittiming; struct can_bittiming *nom_bt = &priv->can.bittiming;
struct can_bittiming *data_bt = &priv->can.data_bittiming; struct can_bittiming *data_bt = &priv->can.fd.data_bittiming;
struct esd_usb_3_set_baudrate_msg_x *baud_x; struct esd_usb_3_set_baudrate_msg_x *baud_x;
union esd_usb_msg *msg; union esd_usb_msg *msg;
u16 flags = 0; u16 flags = 0;
@ -1218,9 +1218,9 @@ static int esd_usb_probe_one_net(struct usb_interface *intf, int index)
priv->can.clock.freq = ESD_USB_3_CAN_CLOCK; priv->can.clock.freq = ESD_USB_3_CAN_CLOCK;
priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD; priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD;
priv->can.bittiming_const = &esd_usb_3_nom_bittiming_const; priv->can.bittiming_const = &esd_usb_3_nom_bittiming_const;
priv->can.data_bittiming_const = &esd_usb_3_data_bittiming_const; priv->can.fd.data_bittiming_const = &esd_usb_3_data_bittiming_const;
priv->can.do_set_bittiming = esd_usb_3_set_bittiming; priv->can.do_set_bittiming = esd_usb_3_set_bittiming;
priv->can.do_set_data_bittiming = esd_usb_3_set_bittiming; priv->can.fd.do_set_data_bittiming = esd_usb_3_set_bittiming;
break; break;
case ESD_USB_CANUSBM_PRODUCT_ID: case ESD_USB_CANUSBM_PRODUCT_ID:

View File

@ -2059,8 +2059,8 @@ static int es58x_init_priv(struct es58x_device *es58x_dev,
can->bittiming_const = param->bittiming_const; can->bittiming_const = param->bittiming_const;
if (param->ctrlmode_supported & CAN_CTRLMODE_FD) { if (param->ctrlmode_supported & CAN_CTRLMODE_FD) {
can->data_bittiming_const = param->data_bittiming_const; can->fd.data_bittiming_const = param->data_bittiming_const;
can->tdc_const = param->tdc_const; can->fd.tdc_const = param->tdc_const;
} }
can->bitrate_max = param->bitrate_max; can->bitrate_max = param->bitrate_max;
can->clock = param->clock; can->clock = param->clock;

View File

@ -427,12 +427,12 @@ static int es58x_fd_enable_channel(struct es58x_priv *priv)
if (tx_conf_msg.canfd_enabled) { if (tx_conf_msg.canfd_enabled) {
es58x_fd_convert_bittiming(&tx_conf_msg.data_bittiming, es58x_fd_convert_bittiming(&tx_conf_msg.data_bittiming,
&priv->can.data_bittiming); &priv->can.fd.data_bittiming);
if (can_tdc_is_enabled(&priv->can)) { if (can_tdc_is_enabled(&priv->can)) {
tx_conf_msg.tdc_enabled = 1; tx_conf_msg.tdc_enabled = 1;
tx_conf_msg.tdco = cpu_to_le16(priv->can.tdc.tdco); tx_conf_msg.tdco = cpu_to_le16(priv->can.fd.tdc.tdco);
tx_conf_msg.tdcf = cpu_to_le16(priv->can.tdc.tdcf); tx_conf_msg.tdcf = cpu_to_le16(priv->can.fd.tdc.tdcf);
} }
conf_len = ES58X_FD_CANFD_CONF_LEN; conf_len = ES58X_FD_CANFD_CONF_LEN;

View File

@ -728,7 +728,7 @@ static int gs_usb_set_bittiming(struct net_device *netdev)
static int gs_usb_set_data_bittiming(struct net_device *netdev) static int gs_usb_set_data_bittiming(struct net_device *netdev)
{ {
struct gs_can *dev = netdev_priv(netdev); struct gs_can *dev = netdev_priv(netdev);
struct can_bittiming *bt = &dev->can.data_bittiming; struct can_bittiming *bt = &dev->can.fd.data_bittiming;
struct gs_device_bittiming dbt = { struct gs_device_bittiming dbt = {
.prop_seg = cpu_to_le32(bt->prop_seg), .prop_seg = cpu_to_le32(bt->prop_seg),
.phase_seg1 = cpu_to_le32(bt->phase_seg1), .phase_seg1 = cpu_to_le32(bt->phase_seg1),
@ -1300,8 +1300,8 @@ static struct gs_can *gs_make_candev(unsigned int channel,
/* The data bit timing will be overwritten, if /* The data bit timing will be overwritten, if
* GS_CAN_FEATURE_BT_CONST_EXT is set. * GS_CAN_FEATURE_BT_CONST_EXT is set.
*/ */
dev->can.data_bittiming_const = &dev->bt_const; dev->can.fd.data_bittiming_const = &dev->bt_const;
dev->can.do_set_data_bittiming = gs_usb_set_data_bittiming; dev->can.fd.do_set_data_bittiming = gs_usb_set_data_bittiming;
} }
if (feature & GS_CAN_FEATURE_TERMINATION) { if (feature & GS_CAN_FEATURE_TERMINATION) {
@ -1381,7 +1381,7 @@ static struct gs_can *gs_make_candev(unsigned int channel,
dev->data_bt_const.brp_max = le32_to_cpu(bt_const_extended.dbrp_max); 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->data_bt_const.brp_inc = le32_to_cpu(bt_const_extended.dbrp_inc);
dev->can.data_bittiming_const = &dev->data_bt_const; dev->can.fd.data_bittiming_const = &dev->data_bt_const;
} }
can_rx_offload_add_manual(netdev, &dev->offload, GS_NAPI_WEIGHT); can_rx_offload_add_manual(netdev, &dev->offload, GS_NAPI_WEIGHT);

View File

@ -137,7 +137,7 @@ struct kvaser_usb_net_priv {
* @dev_set_mode: used for can.do_set_mode * @dev_set_mode: used for can.do_set_mode
* @dev_set_bittiming: used for can.do_set_bittiming * @dev_set_bittiming: used for can.do_set_bittiming
* @dev_get_busparams: readback arbitration busparams * @dev_get_busparams: readback arbitration busparams
* @dev_set_data_bittiming: used for can.do_set_data_bittiming * @dev_set_data_bittiming: used for can.fd.do_set_data_bittiming
* @dev_get_data_busparams: readback data busparams * @dev_get_data_busparams: readback data busparams
* @dev_get_berr_counter: used for can.do_get_berr_counter * @dev_get_berr_counter: used for can.do_get_berr_counter
* *

View File

@ -592,7 +592,7 @@ static int kvaser_usb_set_data_bittiming(struct net_device *netdev)
struct kvaser_usb_net_priv *priv = netdev_priv(netdev); struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
struct kvaser_usb *dev = priv->dev; struct kvaser_usb *dev = priv->dev;
const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops; const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops;
struct can_bittiming *dbt = &priv->can.data_bittiming; struct can_bittiming *dbt = &priv->can.fd.data_bittiming;
struct kvaser_usb_busparams busparams; struct kvaser_usb_busparams busparams;
int tseg1 = dbt->prop_seg + dbt->phase_seg1; int tseg1 = dbt->prop_seg + dbt->phase_seg1;
int tseg2 = dbt->phase_seg2; int tseg2 = dbt->phase_seg2;
@ -842,8 +842,8 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel)
priv->can.ctrlmode_supported |= dev->card_data.ctrlmode_supported; priv->can.ctrlmode_supported |= dev->card_data.ctrlmode_supported;
if (priv->can.ctrlmode_supported & CAN_CTRLMODE_FD) { if (priv->can.ctrlmode_supported & CAN_CTRLMODE_FD) {
priv->can.data_bittiming_const = dev->cfg->data_bittiming_const; priv->can.fd.data_bittiming_const = dev->cfg->data_bittiming_const;
priv->can.do_set_data_bittiming = kvaser_usb_set_data_bittiming; priv->can.fd.do_set_data_bittiming = kvaser_usb_set_data_bittiming;
} }
netdev->flags |= IFF_ECHO; netdev->flags |= IFF_ECHO;

View File

@ -770,7 +770,7 @@ static int peak_usb_set_data_bittiming(struct net_device *netdev)
const struct peak_usb_adapter *pa = dev->adapter; const struct peak_usb_adapter *pa = dev->adapter;
if (pa->dev_set_data_bittiming) { if (pa->dev_set_data_bittiming) {
struct can_bittiming *bt = &dev->can.data_bittiming; struct can_bittiming *bt = &dev->can.fd.data_bittiming;
int err = pa->dev_set_data_bittiming(dev, bt); int err = pa->dev_set_data_bittiming(dev, bt);
if (err) if (err)
@ -954,8 +954,8 @@ static int peak_usb_create_dev(const struct peak_usb_adapter *peak_usb_adapter,
dev->can.clock = peak_usb_adapter->clock; dev->can.clock = peak_usb_adapter->clock;
dev->can.bittiming_const = peak_usb_adapter->bittiming_const; dev->can.bittiming_const = peak_usb_adapter->bittiming_const;
dev->can.do_set_bittiming = peak_usb_set_bittiming; dev->can.do_set_bittiming = peak_usb_set_bittiming;
dev->can.data_bittiming_const = peak_usb_adapter->data_bittiming_const; dev->can.fd.data_bittiming_const = peak_usb_adapter->data_bittiming_const;
dev->can.do_set_data_bittiming = peak_usb_set_data_bittiming; dev->can.fd.do_set_data_bittiming = peak_usb_set_data_bittiming;
dev->can.do_set_mode = peak_usb_set_mode; dev->can.do_set_mode = peak_usb_set_mode;
dev->can.do_get_berr_counter = peak_usb_adapter->do_get_berr_counter; dev->can.do_get_berr_counter = peak_usb_adapter->do_get_berr_counter;
dev->can.ctrlmode_supported = peak_usb_adapter->ctrlmode_supported; dev->can.ctrlmode_supported = peak_usb_adapter->ctrlmode_supported;

View File

@ -481,7 +481,7 @@ static int xcan_set_bittiming(struct net_device *ndev)
{ {
struct xcan_priv *priv = netdev_priv(ndev); struct xcan_priv *priv = netdev_priv(ndev);
struct can_bittiming *bt = &priv->can.bittiming; struct can_bittiming *bt = &priv->can.bittiming;
struct can_bittiming *dbt = &priv->can.data_bittiming; struct can_bittiming *dbt = &priv->can.fd.data_bittiming;
u32 btr0, btr1; u32 btr0, btr1;
u32 is_config_mode; u32 is_config_mode;
@ -517,10 +517,10 @@ static int xcan_set_bittiming(struct net_device *ndev)
btr0 = dbt->brp - 1; btr0 = dbt->brp - 1;
if (can_tdc_is_enabled(&priv->can)) { if (can_tdc_is_enabled(&priv->can)) {
if (priv->devtype.cantype == XAXI_CANFD) if (priv->devtype.cantype == XAXI_CANFD)
btr0 |= FIELD_PREP(XCAN_BRPR_TDCO_MASK, priv->can.tdc.tdco) | btr0 |= FIELD_PREP(XCAN_BRPR_TDCO_MASK, priv->can.fd.tdc.tdco) |
XCAN_BRPR_TDC_ENABLE; XCAN_BRPR_TDC_ENABLE;
else else
btr0 |= FIELD_PREP(XCAN_2_BRPR_TDCO_MASK, priv->can.tdc.tdco) | btr0 |= FIELD_PREP(XCAN_2_BRPR_TDCO_MASK, priv->can.fd.tdc.tdco) |
XCAN_BRPR_TDC_ENABLE; XCAN_BRPR_TDC_ENABLE;
} }
@ -1967,22 +1967,22 @@ static int xcan_probe(struct platform_device *pdev)
goto err_free; goto err_free;
if (devtype->cantype == XAXI_CANFD) { if (devtype->cantype == XAXI_CANFD) {
priv->can.data_bittiming_const = priv->can.fd.data_bittiming_const =
&xcan_data_bittiming_const_canfd; &xcan_data_bittiming_const_canfd;
priv->can.tdc_const = &xcan_tdc_const_canfd; priv->can.fd.tdc_const = &xcan_tdc_const_canfd;
} }
if (devtype->cantype == XAXI_CANFD_2_0) { if (devtype->cantype == XAXI_CANFD_2_0) {
priv->can.data_bittiming_const = priv->can.fd.data_bittiming_const =
&xcan_data_bittiming_const_canfd2; &xcan_data_bittiming_const_canfd2;
priv->can.tdc_const = &xcan_tdc_const_canfd2; priv->can.fd.tdc_const = &xcan_tdc_const_canfd2;
} }
if (devtype->cantype == XAXI_CANFD || if (devtype->cantype == XAXI_CANFD ||
devtype->cantype == XAXI_CANFD_2_0) { devtype->cantype == XAXI_CANFD_2_0) {
priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD | priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD |
CAN_CTRLMODE_TDC_AUTO; CAN_CTRLMODE_TDC_AUTO;
priv->can.do_get_auto_tdcv = xcan_get_auto_tdcv; priv->can.fd.do_get_auto_tdcv = xcan_get_auto_tdcv;
} }
priv->reg_base = addr; priv->reg_base = addr;

View File

@ -38,6 +38,17 @@ enum can_termination_gpio {
CAN_TERMINATION_GPIO_MAX, CAN_TERMINATION_GPIO_MAX,
}; };
struct data_bittiming_params {
const struct can_bittiming_const *data_bittiming_const;
struct can_bittiming data_bittiming;
const struct can_tdc_const *tdc_const;
struct can_tdc tdc;
const u32 *data_bitrate_const;
unsigned int data_bitrate_const_cnt;
int (*do_set_data_bittiming)(struct net_device *dev);
int (*do_get_auto_tdcv)(const struct net_device *dev, u32 *tdcv);
};
/* /*
* CAN common private data * CAN common private data
*/ */
@ -45,16 +56,11 @@ struct can_priv {
struct net_device *dev; struct net_device *dev;
struct can_device_stats can_stats; struct can_device_stats can_stats;
const struct can_bittiming_const *bittiming_const, const struct can_bittiming_const *bittiming_const;
*data_bittiming_const; struct can_bittiming bittiming;
struct can_bittiming bittiming, data_bittiming; struct data_bittiming_params fd;
const struct can_tdc_const *tdc_const;
struct can_tdc tdc;
unsigned int bitrate_const_cnt; unsigned int bitrate_const_cnt;
const u32 *bitrate_const; const u32 *bitrate_const;
const u32 *data_bitrate_const;
unsigned int data_bitrate_const_cnt;
u32 bitrate_max; u32 bitrate_max;
struct can_clock clock; struct can_clock clock;
@ -77,14 +83,12 @@ struct can_priv {
struct delayed_work restart_work; struct delayed_work restart_work;
int (*do_set_bittiming)(struct net_device *dev); int (*do_set_bittiming)(struct net_device *dev);
int (*do_set_data_bittiming)(struct net_device *dev);
int (*do_set_mode)(struct net_device *dev, enum can_mode mode); int (*do_set_mode)(struct net_device *dev, enum can_mode mode);
int (*do_set_termination)(struct net_device *dev, u16 term); int (*do_set_termination)(struct net_device *dev, u16 term);
int (*do_get_state)(const struct net_device *dev, int (*do_get_state)(const struct net_device *dev,
enum can_state *state); enum can_state *state);
int (*do_get_berr_counter)(const struct net_device *dev, int (*do_get_berr_counter)(const struct net_device *dev,
struct can_berr_counter *bec); struct can_berr_counter *bec);
int (*do_get_auto_tdcv)(const struct net_device *dev, u32 *tdcv);
}; };
static inline bool can_tdc_is_enabled(const struct can_priv *priv) static inline bool can_tdc_is_enabled(const struct can_priv *priv)
@ -114,11 +118,11 @@ static inline bool can_tdc_is_enabled(const struct can_priv *priv)
*/ */
static inline s32 can_get_relative_tdco(const struct can_priv *priv) static inline s32 can_get_relative_tdco(const struct can_priv *priv)
{ {
const struct can_bittiming *dbt = &priv->data_bittiming; const struct can_bittiming *dbt = &priv->fd.data_bittiming;
s32 sample_point_in_tc = (CAN_SYNC_SEG + dbt->prop_seg + s32 sample_point_in_tc = (CAN_SYNC_SEG + dbt->prop_seg +
dbt->phase_seg1) * dbt->brp; dbt->phase_seg1) * dbt->brp;
return (s32)priv->tdc.tdco - sample_point_in_tc; return (s32)priv->fd.tdc.tdco - sample_point_in_tc;
} }
/* helper to define static CAN controller features at device creation time */ /* helper to define static CAN controller features at device creation time */

View File

@ -66,6 +66,7 @@ TARGETS += mseal_system_mappings
TARGETS += nci TARGETS += nci
TARGETS += net TARGETS += net
TARGETS += net/af_unix TARGETS += net/af_unix
TARGETS += net/can
TARGETS += net/forwarding TARGETS += net/forwarding
TARGETS += net/hsr TARGETS += net/hsr
TARGETS += net/mptcp TARGETS += net/mptcp

View File

@ -0,0 +1,2 @@
# SPDX-License-Identifier: GPL-2.0-only
test_raw_filter

View File

@ -0,0 +1,11 @@
# SPDX-License-Identifier: GPL-2.0
top_srcdir = ../../../../..
CFLAGS += -Wall -Wl,--no-as-needed -O2 -g -I$(top_srcdir)/usr/include $(KHDR_INCLUDES)
TEST_PROGS := test_raw_filter.sh
TEST_GEN_FILES := test_raw_filter
include ../../lib.mk

View File

@ -0,0 +1,405 @@
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
/*
* Copyright (c) 2011 Volkswagen Group Electronic Research
* All rights reserved.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <net/if.h>
#include <linux/if.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include "../../kselftest_harness.h"
#define ID 0x123
char CANIF[IFNAMSIZ];
static int send_can_frames(int sock, int testcase)
{
struct can_frame frame;
frame.can_dlc = 1;
frame.data[0] = testcase;
frame.can_id = ID;
if (write(sock, &frame, sizeof(frame)) < 0)
goto write_err;
frame.can_id = (ID | CAN_RTR_FLAG);
if (write(sock, &frame, sizeof(frame)) < 0)
goto write_err;
frame.can_id = (ID | CAN_EFF_FLAG);
if (write(sock, &frame, sizeof(frame)) < 0)
goto write_err;
frame.can_id = (ID | CAN_EFF_FLAG | CAN_RTR_FLAG);
if (write(sock, &frame, sizeof(frame)) < 0)
goto write_err;
return 0;
write_err:
perror("write");
return 1;
}
FIXTURE(can_filters) {
int sock;
};
FIXTURE_SETUP(can_filters)
{
struct sockaddr_can addr;
struct ifreq ifr;
int recv_own_msgs = 1;
int s, ret;
s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
ASSERT_GE(s, 0)
TH_LOG("failed to create CAN_RAW socket: %d", errno);
strncpy(ifr.ifr_name, CANIF, sizeof(ifr.ifr_name));
ret = ioctl(s, SIOCGIFINDEX, &ifr);
ASSERT_GE(ret, 0)
TH_LOG("failed SIOCGIFINDEX: %d", errno);
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
setsockopt(s, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS,
&recv_own_msgs, sizeof(recv_own_msgs));
ret = bind(s, (struct sockaddr *)&addr, sizeof(addr));
ASSERT_EQ(ret, 0)
TH_LOG("failed bind socket: %d", errno);
self->sock = s;
}
FIXTURE_TEARDOWN(can_filters)
{
close(self->sock);
}
FIXTURE_VARIANT(can_filters) {
int testcase;
canid_t id;
canid_t mask;
int exp_num_rx;
canid_t exp_flags[];
};
/* Receive all frames when filtering for the ID in standard frame format */
FIXTURE_VARIANT_ADD(can_filters, base) {
.testcase = 1,
.id = ID,
.mask = CAN_SFF_MASK,
.exp_num_rx = 4,
.exp_flags = {
0,
CAN_RTR_FLAG,
CAN_EFF_FLAG,
CAN_EFF_FLAG | CAN_RTR_FLAG,
},
};
/* Ignore EFF flag in filter ID if not covered by filter mask */
FIXTURE_VARIANT_ADD(can_filters, base_eff) {
.testcase = 2,
.id = ID | CAN_EFF_FLAG,
.mask = CAN_SFF_MASK,
.exp_num_rx = 4,
.exp_flags = {
0,
CAN_RTR_FLAG,
CAN_EFF_FLAG,
CAN_EFF_FLAG | CAN_RTR_FLAG,
},
};
/* Ignore RTR flag in filter ID if not covered by filter mask */
FIXTURE_VARIANT_ADD(can_filters, base_rtr) {
.testcase = 3,
.id = ID | CAN_RTR_FLAG,
.mask = CAN_SFF_MASK,
.exp_num_rx = 4,
.exp_flags = {
0,
CAN_RTR_FLAG,
CAN_EFF_FLAG,
CAN_EFF_FLAG | CAN_RTR_FLAG,
},
};
/* Ignore EFF and RTR flags in filter ID if not covered by filter mask */
FIXTURE_VARIANT_ADD(can_filters, base_effrtr) {
.testcase = 4,
.id = ID | CAN_EFF_FLAG | CAN_RTR_FLAG,
.mask = CAN_SFF_MASK,
.exp_num_rx = 4,
.exp_flags = {
0,
CAN_RTR_FLAG,
CAN_EFF_FLAG,
CAN_EFF_FLAG | CAN_RTR_FLAG,
},
};
/* Receive only SFF frames when expecting no EFF flag */
FIXTURE_VARIANT_ADD(can_filters, filter_eff) {
.testcase = 5,
.id = ID,
.mask = CAN_SFF_MASK | CAN_EFF_FLAG,
.exp_num_rx = 2,
.exp_flags = {
0,
CAN_RTR_FLAG,
},
};
/* Receive only EFF frames when filter id and filter mask include EFF flag */
FIXTURE_VARIANT_ADD(can_filters, filter_eff_eff) {
.testcase = 6,
.id = ID | CAN_EFF_FLAG,
.mask = CAN_SFF_MASK | CAN_EFF_FLAG,
.exp_num_rx = 2,
.exp_flags = {
CAN_EFF_FLAG,
CAN_EFF_FLAG | CAN_RTR_FLAG,
},
};
/* Receive only SFF frames when expecting no EFF flag, ignoring RTR flag */
FIXTURE_VARIANT_ADD(can_filters, filter_eff_rtr) {
.testcase = 7,
.id = ID | CAN_RTR_FLAG,
.mask = CAN_SFF_MASK | CAN_EFF_FLAG,
.exp_num_rx = 2,
.exp_flags = {
0,
CAN_RTR_FLAG,
},
};
/* Receive only EFF frames when filter id and filter mask include EFF flag,
* ignoring RTR flag
*/
FIXTURE_VARIANT_ADD(can_filters, filter_eff_effrtr) {
.testcase = 8,
.id = ID | CAN_EFF_FLAG | CAN_RTR_FLAG,
.mask = CAN_SFF_MASK | CAN_EFF_FLAG,
.exp_num_rx = 2,
.exp_flags = {
CAN_EFF_FLAG,
CAN_EFF_FLAG | CAN_RTR_FLAG,
},
};
/* Receive no remote frames when filtering for no RTR flag */
FIXTURE_VARIANT_ADD(can_filters, filter_rtr) {
.testcase = 9,
.id = ID,
.mask = CAN_SFF_MASK | CAN_RTR_FLAG,
.exp_num_rx = 2,
.exp_flags = {
0,
CAN_EFF_FLAG,
},
};
/* Receive no remote frames when filtering for no RTR flag, ignoring EFF flag */
FIXTURE_VARIANT_ADD(can_filters, filter_rtr_eff) {
.testcase = 10,
.id = ID | CAN_EFF_FLAG,
.mask = CAN_SFF_MASK | CAN_RTR_FLAG,
.exp_num_rx = 2,
.exp_flags = {
0,
CAN_EFF_FLAG,
},
};
/* Receive only remote frames when filter includes RTR flag */
FIXTURE_VARIANT_ADD(can_filters, filter_rtr_rtr) {
.testcase = 11,
.id = ID | CAN_RTR_FLAG,
.mask = CAN_SFF_MASK | CAN_RTR_FLAG,
.exp_num_rx = 2,
.exp_flags = {
CAN_RTR_FLAG,
CAN_EFF_FLAG | CAN_RTR_FLAG,
},
};
/* Receive only remote frames when filter includes RTR flag, ignoring EFF
* flag
*/
FIXTURE_VARIANT_ADD(can_filters, filter_rtr_effrtr) {
.testcase = 12,
.id = ID | CAN_EFF_FLAG | CAN_RTR_FLAG,
.mask = CAN_SFF_MASK | CAN_RTR_FLAG,
.exp_num_rx = 2,
.exp_flags = {
CAN_RTR_FLAG,
CAN_EFF_FLAG | CAN_RTR_FLAG,
},
};
/* Receive only SFF data frame when filtering for no flags */
FIXTURE_VARIANT_ADD(can_filters, filter_effrtr) {
.testcase = 13,
.id = ID,
.mask = CAN_SFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG,
.exp_num_rx = 1,
.exp_flags = {
0,
},
};
/* Receive only EFF data frame when filtering for EFF but no RTR flag */
FIXTURE_VARIANT_ADD(can_filters, filter_effrtr_eff) {
.testcase = 14,
.id = ID | CAN_EFF_FLAG,
.mask = CAN_SFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG,
.exp_num_rx = 1,
.exp_flags = {
CAN_EFF_FLAG,
},
};
/* Receive only SFF remote frame when filtering for RTR but no EFF flag */
FIXTURE_VARIANT_ADD(can_filters, filter_effrtr_rtr) {
.testcase = 15,
.id = ID | CAN_RTR_FLAG,
.mask = CAN_SFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG,
.exp_num_rx = 1,
.exp_flags = {
CAN_RTR_FLAG,
},
};
/* Receive only EFF remote frame when filtering for EFF and RTR flag */
FIXTURE_VARIANT_ADD(can_filters, filter_effrtr_effrtr) {
.testcase = 16,
.id = ID | CAN_EFF_FLAG | CAN_RTR_FLAG,
.mask = CAN_SFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG,
.exp_num_rx = 1,
.exp_flags = {
CAN_EFF_FLAG | CAN_RTR_FLAG,
},
};
/* Receive only SFF data frame when filtering for no EFF flag and no RTR flag
* but based on EFF mask
*/
FIXTURE_VARIANT_ADD(can_filters, eff) {
.testcase = 17,
.id = ID,
.mask = CAN_EFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG,
.exp_num_rx = 1,
.exp_flags = {
0,
},
};
/* Receive only EFF data frame when filtering for EFF flag and no RTR flag but
* based on EFF mask
*/
FIXTURE_VARIANT_ADD(can_filters, eff_eff) {
.testcase = 18,
.id = ID | CAN_EFF_FLAG,
.mask = CAN_EFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG,
.exp_num_rx = 1,
.exp_flags = {
CAN_EFF_FLAG,
},
};
/* This test verifies that the raw CAN filters work, by checking if only frames
* with the expected set of flags are received. For each test case, the given
* filter (id and mask) is added and four CAN frames are sent with every
* combination of set/unset EFF/RTR flags.
*/
TEST_F(can_filters, test_filter)
{
struct can_filter rfilter;
int ret;
rfilter.can_id = variant->id;
rfilter.can_mask = variant->mask;
setsockopt(self->sock, SOL_CAN_RAW, CAN_RAW_FILTER,
&rfilter, sizeof(rfilter));
TH_LOG("filters: can_id = 0x%08X can_mask = 0x%08X",
rfilter.can_id, rfilter.can_mask);
ret = send_can_frames(self->sock, variant->testcase);
ASSERT_EQ(ret, 0)
TH_LOG("failed to send CAN frames");
for (int i = 0; i <= variant->exp_num_rx; i++) {
struct can_frame frame;
struct timeval tv = {
.tv_sec = 0,
.tv_usec = 50000, /* 50ms timeout */
};
fd_set rdfs;
FD_ZERO(&rdfs);
FD_SET(self->sock, &rdfs);
ret = select(self->sock + 1, &rdfs, NULL, NULL, &tv);
ASSERT_GE(ret, 0)
TH_LOG("failed select for frame %d, err: %d)", i, errno);
ret = FD_ISSET(self->sock, &rdfs);
if (i == variant->exp_num_rx) {
ASSERT_EQ(ret, 0)
TH_LOG("too many frames received");
} else {
ASSERT_NE(ret, 0)
TH_LOG("too few frames received");
ret = read(self->sock, &frame, sizeof(frame));
ASSERT_GE(ret, 0)
TH_LOG("failed to read frame %d, err: %d", i, errno);
TH_LOG("rx: can_id = 0x%08X rx = %d", frame.can_id, i);
ASSERT_EQ(ID, frame.can_id & CAN_SFF_MASK)
TH_LOG("received wrong can_id");
ASSERT_EQ(variant->testcase, frame.data[0])
TH_LOG("received wrong test case");
ASSERT_EQ(frame.can_id & ~CAN_ERR_MASK,
variant->exp_flags[i])
TH_LOG("received unexpected flags");
}
}
}
int main(int argc, char **argv)
{
char *ifname = getenv("CANIF");
if (!ifname) {
printf("CANIF environment variable must contain the test interface\n");
return KSFT_FAIL;
}
strncpy(CANIF, ifname, sizeof(CANIF) - 1);
return test_harness_run(argc, argv);
}

View File

@ -0,0 +1,45 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
ALL_TESTS="
test_raw_filter
"
net_dir=$(dirname $0)/..
source $net_dir/lib.sh
export CANIF=${CANIF:-"vcan0"}
BITRATE=${BITRATE:-500000}
setup()
{
if [[ $CANIF == vcan* ]]; then
ip link add name $CANIF type vcan || exit $ksft_skip
else
ip link set dev $CANIF type can bitrate $BITRATE || exit $ksft_skip
fi
ip link set dev $CANIF up
pwd
}
cleanup()
{
ip link set dev $CANIF down
if [[ $CANIF == vcan* ]]; then
ip link delete $CANIF
fi
}
test_raw_filter()
{
./test_raw_filter
check_err $?
log_test "test_raw_filter"
}
trap cleanup EXIT
setup
tests_run
exit $EXIT_STATUS