From d38f9180da881f130801f964339a98015f7e53da Mon Sep 17 00:00:00 2001 From: Appana Durga Kedareswara rao Date: Mon, 18 Mar 2019 17:02:41 +0530 Subject: can: xilinx_can: Fix style issues This patch fixes below checkpatch warnings and checks in the driver. CHECK: Alignment should match open parenthesis + void (*write_reg)(const struct xcan_priv *priv, enum xcan_reg reg, + u32 val); CHECK: Alignment should match open parenthesis +static void xcan_write_reg_le(const struct xcan_priv *priv, enum xcan_reg reg, + u32 val) CHECK: Alignment should match open parenthesis +static void xcan_write_reg_be(const struct xcan_priv *priv, enum xcan_reg reg, + u32 val) CHECK: Alignment should match open parenthesis + netdev_dbg(ndev, "BRPR=0x%08x, BTR=0x%08x\n", + priv->read_reg(priv, XCAN_BRPR_OFFSET), CHECK: Alignment should match open parenthesis + netdev_warn(ndev, + "timed out for correct mode\n"); CHECK: Alignment should match open parenthesis + netdev_dbg(ndev, "status:#x%08x\n", + priv->read_reg(priv, XCAN_SR_OFFSET)); CHECK: spaces preferred around that '-' (ctx:VxV) + (CAN_EFF_ID_BITS-CAN_SFF_ID_BITS)) << ^ CHECK: Alignment should match open parenthesis + netdev_dbg(ndev, "%s: error status register:0x%x\n", + __func__, priv->read_reg(priv, XCAN_ESR_OFFSET)); WARNING: line over 80 characters + offset = XCAN_RXMSG_2_FRAME_OFFSET(fsr & XCAN_FSR_RI_MASK); WARNING: line over 80 characters + offset = XCAN_RXMSG_FRAME_OFFSET(fsr & XCAN_FSR_RI_MASK); WARNING: line over 80 characters + while ((isr & XCAN_IXR_TXOK_MASK) && !WARN_ON(++retries == 100)) { WARNING: line over 80 characters + priv->write_reg(priv, XCAN_ICR_OFFSET, XCAN_IXR_TXOK_MASK); CHECK: Alignment should match open parenthesis + netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n", + __func__, ret); CHECK: Alignment should match open parenthesis + ret = request_irq(ndev->irq, xcan_interrupt, priv->irq_flags, + ndev->name, ndev); CHECK: Alignment should match open parenthesis +static int xcan_get_berr_counter(const struct net_device *ndev, + struct can_berr_counter *bec) CHECK: Alignment should match open parenthesis + netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n", + __func__, ret); CHECK: Please don't use multiple blank lines + + CHECK: Alignment should match open parenthesis + netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n", + __func__, ret);` Signed-off-by: Appana Durga Kedareswara rao Signed-off-by: Marc Kleine-Budde --- drivers/net/can/xilinx_can.c | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) (limited to 'drivers/net/can/xilinx_can.c') diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index 63203ff452b5..1823f4fc448a 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -183,7 +183,7 @@ struct xcan_priv { struct napi_struct napi; u32 (*read_reg)(const struct xcan_priv *priv, enum xcan_reg reg); void (*write_reg)(const struct xcan_priv *priv, enum xcan_reg reg, - u32 val); + u32 val); struct device *dev; void __iomem *reg_base; unsigned long irq_flags; @@ -238,7 +238,7 @@ static const struct can_bittiming_const xcan_bittiming_const_canfd2 = { * Write data to the paricular CAN register */ static void xcan_write_reg_le(const struct xcan_priv *priv, enum xcan_reg reg, - u32 val) + u32 val) { iowrite32(val, priv->reg_base + reg); } @@ -265,7 +265,7 @@ static u32 xcan_read_reg_le(const struct xcan_priv *priv, enum xcan_reg reg) * Write data to the paricular CAN register */ static void xcan_write_reg_be(const struct xcan_priv *priv, enum xcan_reg reg, - u32 val) + u32 val) { iowrite32be(val, priv->reg_base + reg); } @@ -373,8 +373,8 @@ static int xcan_set_bittiming(struct net_device *ndev) priv->write_reg(priv, XCAN_BTR_OFFSET, btr1); netdev_dbg(ndev, "BRPR=0x%08x, BTR=0x%08x\n", - priv->read_reg(priv, XCAN_BRPR_OFFSET), - priv->read_reg(priv, XCAN_BTR_OFFSET)); + priv->read_reg(priv, XCAN_BRPR_OFFSET), + priv->read_reg(priv, XCAN_BTR_OFFSET)); return 0; } @@ -439,12 +439,12 @@ static int xcan_chip_start(struct net_device *ndev) while (!(priv->read_reg(priv, XCAN_SR_OFFSET) & reg_sr_mask)) { if (time_after(jiffies, timeout)) { netdev_warn(ndev, - "timed out for correct mode\n"); + "timed out for correct mode\n"); return -ETIMEDOUT; } } netdev_dbg(ndev, "status:#x%08x\n", - priv->read_reg(priv, XCAN_SR_OFFSET)); + priv->read_reg(priv, XCAN_SR_OFFSET)); priv->can.state = CAN_STATE_ERROR_ACTIVE; return 0; @@ -498,7 +498,7 @@ static void xcan_write_frame(struct xcan_priv *priv, struct sk_buff *skb, id = ((cf->can_id & CAN_EFF_MASK) << XCAN_IDR_ID2_SHIFT) & XCAN_IDR_ID2_MASK; id |= (((cf->can_id & CAN_EFF_MASK) >> - (CAN_EFF_ID_BITS-CAN_SFF_ID_BITS)) << + (CAN_EFF_ID_BITS - CAN_SFF_ID_BITS)) << XCAN_IDR_ID1_SHIFT) & XCAN_IDR_ID1_MASK; /* The substibute remote TX request bit should be "1" @@ -934,7 +934,7 @@ static void xcan_err_interrupt(struct net_device *ndev, u32 isr) } netdev_dbg(ndev, "%s: error status register:0x%x\n", - __func__, priv->read_reg(priv, XCAN_ESR_OFFSET)); + __func__, priv->read_reg(priv, XCAN_ESR_OFFSET)); } /** @@ -982,9 +982,11 @@ static int xcan_rx_fifo_get_next_frame(struct xcan_priv *priv) return -ENOENT; if (priv->devtype.flags & XCAN_FLAG_CANFD_2) - offset = XCAN_RXMSG_2_FRAME_OFFSET(fsr & XCAN_FSR_RI_MASK); + offset = + XCAN_RXMSG_2_FRAME_OFFSET(fsr & XCAN_FSR_RI_MASK); else - offset = XCAN_RXMSG_FRAME_OFFSET(fsr & XCAN_FSR_RI_MASK); + offset = + XCAN_RXMSG_FRAME_OFFSET(fsr & XCAN_FSR_RI_MASK); } else { /* check if RX FIFO is empty */ @@ -1094,8 +1096,10 @@ static void xcan_tx_interrupt(struct net_device *ndev, u32 isr) * via TXFEMP handling as we read TXFEMP *after* TXOK * clear to satisfy (1). */ - while ((isr & XCAN_IXR_TXOK_MASK) && !WARN_ON(++retries == 100)) { - priv->write_reg(priv, XCAN_ICR_OFFSET, XCAN_IXR_TXOK_MASK); + while ((isr & XCAN_IXR_TXOK_MASK) && + !WARN_ON(++retries == 100)) { + priv->write_reg(priv, XCAN_ICR_OFFSET, + XCAN_IXR_TXOK_MASK); isr = priv->read_reg(priv, XCAN_ISR_OFFSET); } @@ -1208,12 +1212,12 @@ static int xcan_open(struct net_device *ndev) ret = pm_runtime_get_sync(priv->dev); if (ret < 0) { netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n", - __func__, ret); + __func__, ret); return ret; } ret = request_irq(ndev->irq, xcan_interrupt, priv->irq_flags, - ndev->name, ndev); + ndev->name, ndev); if (ret < 0) { netdev_err(ndev, "irq allocation for CAN failed\n"); goto err; @@ -1284,7 +1288,7 @@ static int xcan_close(struct net_device *ndev) * Return: 0 on success and failure value on error */ static int xcan_get_berr_counter(const struct net_device *ndev, - struct can_berr_counter *bec) + struct can_berr_counter *bec) { struct xcan_priv *priv = netdev_priv(ndev); int ret; @@ -1292,7 +1296,7 @@ static int xcan_get_berr_counter(const struct net_device *ndev, ret = pm_runtime_get_sync(priv->dev); if (ret < 0) { netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n", - __func__, ret); + __func__, ret); return ret; } @@ -1305,7 +1309,6 @@ static int xcan_get_berr_counter(const struct net_device *ndev, return 0; } - static const struct net_device_ops xcan_netdev_ops = { .ndo_open = xcan_open, .ndo_stop = xcan_close, @@ -1589,7 +1592,7 @@ static int xcan_probe(struct platform_device *pdev) ret = pm_runtime_get_sync(&pdev->dev); if (ret < 0) { netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n", - __func__, ret); + __func__, ret); goto err_pmdisable; } -- cgit v1.2.3 From c942a575b95f762dd8721487619d24068471af60 Mon Sep 17 00:00:00 2001 From: Appana Durga Kedareswara rao Date: Mon, 18 Mar 2019 17:02:46 +0530 Subject: can: xilinx_can: Fix kernel doc warnings This patch fixes below kernel doc warnings warning: Function parameter or member 'priv' not described in 'xcan_write_frame' warning: Function parameter or member 'skb' not described in 'xcan_start_xmit_fifo' warning: Function parameter or member 'ndev' not described in 'xcan_start_xmit_fifo' warning: Function parameter or member 'skb' not described in 'xcan_start_xmit_mailbox' warning: Function parameter or member 'ndev' not described in 'xcan_start_xmit_mailbox' warning: Function parameter or member 'priv' not described in 'xcan_rx_fifo_get_next_frame' Signed-off-by: Appana Durga Kedareswara rao Signed-off-by: Marc Kleine-Budde --- drivers/net/can/xilinx_can.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/net/can/xilinx_can.c') diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index 1823f4fc448a..48a4c097a7d8 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -483,6 +483,7 @@ static int xcan_do_set_mode(struct net_device *ndev, enum can_mode mode) /** * xcan_write_frame - Write a frame to HW + * @priv: Driver private data structure * @skb: sk_buff pointer that contains data to be Txed * @frame_offset: Register offset to write the frame to */ @@ -544,6 +545,8 @@ static void xcan_write_frame(struct xcan_priv *priv, struct sk_buff *skb, /** * xcan_start_xmit_fifo - Starts the transmission (FIFO mode) + * @skb: sk_buff pointer that contains data to be Txed + * @ndev: Pointer to net_device structure * * Return: 0 on success, -ENOSPC if FIFO is full. */ @@ -580,6 +583,8 @@ static int xcan_start_xmit_fifo(struct sk_buff *skb, struct net_device *ndev) /** * xcan_start_xmit_mailbox - Starts the transmission (mailbox mode) + * @skb: sk_buff pointer that contains data to be Txed + * @ndev: Pointer to net_device structure * * Return: 0 on success, -ENOSPC if there is no space */ @@ -960,6 +965,7 @@ static void xcan_state_interrupt(struct net_device *ndev, u32 isr) /** * xcan_rx_fifo_get_next_frame - Get register offset of next RX frame + * @priv: Driver private data structure * * Return: Register offset of the next frame in RX FIFO. */ -- cgit v1.2.3 From 3281b380ec9f8a9d89f58d5f5353c7e3b2046f93 Mon Sep 17 00:00:00 2001 From: Appana Durga Kedareswara rao Date: Mon, 18 Mar 2019 17:02:42 +0530 Subject: can: xilinx_can: Fix flags field initialization for axi can and canps AXI CAN IP and CANPS IP supports tx fifo empty feature, this patch updates the flags field for the same. Signed-off-by: Appana Durga Kedareswara rao Signed-off-by: Marc Kleine-Budde --- drivers/net/can/xilinx_can.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net/can/xilinx_can.c') diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index 48a4c097a7d8..0e3f3a536a1d 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -1426,6 +1426,7 @@ static const struct dev_pm_ops xcan_dev_pm_ops = { }; static const struct xcan_devtype_data xcan_zynq_data = { + .flags = XCAN_FLAG_TXFEMP, .bittiming_const = &xcan_bittiming_const, .btr_ts2_shift = XCAN_BTR_TS2_SHIFT, .btr_sjw_shift = XCAN_BTR_SJW_SHIFT, @@ -1433,6 +1434,7 @@ static const struct xcan_devtype_data xcan_zynq_data = { }; static const struct xcan_devtype_data xcan_axi_data = { + .flags = XCAN_FLAG_TXFEMP, .bittiming_const = &xcan_bittiming_const, .btr_ts2_shift = XCAN_BTR_TS2_SHIFT, .btr_sjw_shift = XCAN_BTR_SJW_SHIFT, -- cgit v1.2.3 From 8dce7ea41a1e313cb1ba512b1098c7181ee0fd21 Mon Sep 17 00:00:00 2001 From: Appana Durga Kedareswara rao Date: Mon, 18 Mar 2019 17:02:43 +0530 Subject: can: xilinx_can: Add cantype parameter in xcan_devtype_data struct To differentiate between different CAN IP's this patch adds cantype enum variable in the xcan_devtype_data structure Signed-off-by: Appana Durga Kedareswara rao Signed-off-by: Marc Kleine-Budde --- drivers/net/can/xilinx_can.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/net/can/xilinx_can.c') diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index 0e3f3a536a1d..e76418c94dae 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -149,7 +149,15 @@ enum xcan_reg { #define XCAN_FLAG_RX_FIFO_MULTI 0x0010 #define XCAN_FLAG_CANFD_2 0x0020 +enum xcan_ip_type { + XAXI_CAN = 0, + XZYNQ_CANPS, + XAXI_CANFD, + XAXI_CANFD_2_0, +}; + struct xcan_devtype_data { + enum xcan_ip_type cantype; unsigned int flags; const struct can_bittiming_const *bittiming_const; const char *bus_clk_name; @@ -1426,6 +1434,7 @@ static const struct dev_pm_ops xcan_dev_pm_ops = { }; static const struct xcan_devtype_data xcan_zynq_data = { + .cantype = XZYNQ_CANPS, .flags = XCAN_FLAG_TXFEMP, .bittiming_const = &xcan_bittiming_const, .btr_ts2_shift = XCAN_BTR_TS2_SHIFT, @@ -1434,6 +1443,7 @@ static const struct xcan_devtype_data xcan_zynq_data = { }; static const struct xcan_devtype_data xcan_axi_data = { + .cantype = XAXI_CAN, .flags = XCAN_FLAG_TXFEMP, .bittiming_const = &xcan_bittiming_const, .btr_ts2_shift = XCAN_BTR_TS2_SHIFT, @@ -1442,6 +1452,7 @@ static const struct xcan_devtype_data xcan_axi_data = { }; static const struct xcan_devtype_data xcan_canfd_data = { + .cantype = XAXI_CANFD, .flags = XCAN_FLAG_EXT_FILTERS | XCAN_FLAG_RXMNF | XCAN_FLAG_TX_MAILBOXES | @@ -1453,6 +1464,7 @@ static const struct xcan_devtype_data xcan_canfd_data = { }; static const struct xcan_devtype_data xcan_canfd2_data = { + .cantype = XAXI_CANFD_2_0, .flags = XCAN_FLAG_EXT_FILTERS | XCAN_FLAG_RXMNF | XCAN_FLAG_TX_MAILBOXES | -- cgit v1.2.3 From c223da689324f2ec669a3d10ac312a316410614b Mon Sep 17 00:00:00 2001 From: Appana Durga Kedareswara rao Date: Mon, 18 Mar 2019 17:02:44 +0530 Subject: can: xilinx_can: Add support for CANFD FD frames CANFD IP supports both CAN and CAN FD frames, Existing driver supports only CAN frames, This patch adds support for CAN FD frames. Signed-off-by: Naga Sureshkumar Relli Signed-off-by: Appana Durga Kedareswara rao Signed-off-by: Marc Kleine-Budde --- drivers/net/can/xilinx_can.c | 230 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 214 insertions(+), 16 deletions(-) (limited to 'drivers/net/can/xilinx_can.c') diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index e76418c94dae..fadd54103c38 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -50,6 +50,10 @@ enum xcan_reg { XCAN_AFR_OFFSET = 0x60, /* Acceptance Filter */ /* only on CAN FD cores */ + XCAN_F_BRPR_OFFSET = 0x088, /* Data Phase Baud Rate + * Prescalar + */ + XCAN_F_BTR_OFFSET = 0x08C, /* Data Phase Bit Timing */ XCAN_TRR_OFFSET = 0x0090, /* TX Buffer Ready Request */ XCAN_AFR_EXT_OFFSET = 0x00E0, /* Acceptance Filter */ XCAN_FSR_OFFSET = 0x00E8, /* RX FIFO Status */ @@ -62,6 +66,8 @@ enum xcan_reg { #define XCAN_FRAME_DLC_OFFSET(frame_base) ((frame_base) + 0x04) #define XCAN_FRAME_DW1_OFFSET(frame_base) ((frame_base) + 0x08) #define XCAN_FRAME_DW2_OFFSET(frame_base) ((frame_base) + 0x0C) +#define XCANFD_FRAME_DW_OFFSET(frame_base, n) (((frame_base) + 0x08) + \ + ((n) * XCAN_CANFD_FRAME_SIZE)) #define XCAN_CANFD_FRAME_SIZE 0x48 #define XCAN_TXMSG_FRAME_OFFSET(n) (XCAN_TXMSG_BASE_OFFSET + \ @@ -120,6 +126,8 @@ enum xcan_reg { #define XCAN_FSR_FL_MASK 0x00003F00 /* RX Fill Level */ #define XCAN_FSR_IRI_MASK 0x00000080 /* RX Increment Read Index */ #define XCAN_FSR_RI_MASK 0x0000001F /* RX Read Index */ +#define XCAN_DLCR_EDL_MASK 0x08000000 /* EDL Mask in DLC */ +#define XCAN_DLCR_BRS_MASK 0x04000000 /* BRS Mask in DLC */ /* CAN register bit shift - XCAN___SHIFT */ #define XCAN_BTR_SJW_SHIFT 7 /* Synchronous jump width */ @@ -133,6 +141,7 @@ enum xcan_reg { /* CAN frame length constants */ #define XCAN_FRAME_MAX_DATA_LEN 8 +#define XCANFD_DW_BYTES 4 #define XCAN_TIMEOUT (1 * HZ) /* TX-FIFO-empty interrupt available */ @@ -213,6 +222,7 @@ static const struct can_bittiming_const xcan_bittiming_const = { .brp_inc = 1, }; +/* AXI CANFD Arbitration Bittiming constants as per AXI CANFD 1.0 spec */ static const struct can_bittiming_const xcan_bittiming_const_canfd = { .name = DRIVER_NAME, .tseg1_min = 1, @@ -225,6 +235,20 @@ static const struct can_bittiming_const xcan_bittiming_const_canfd = { .brp_inc = 1, }; +/* AXI CANFD Data Bittiming constants as per AXI CANFD 1.0 specs */ +static struct can_bittiming_const xcan_data_bittiming_const_canfd = { + .name = DRIVER_NAME, + .tseg1_min = 1, + .tseg1_max = 16, + .tseg2_min = 1, + .tseg2_max = 8, + .sjw_max = 8, + .brp_min = 1, + .brp_max = 256, + .brp_inc = 1, +}; + +/* AXI CANFD 2.0 Arbitration Bittiming constants as per AXI CANFD 2.0 spec */ static const struct can_bittiming_const xcan_bittiming_const_canfd2 = { .name = DRIVER_NAME, .tseg1_min = 1, @@ -237,6 +261,19 @@ static const struct can_bittiming_const xcan_bittiming_const_canfd2 = { .brp_inc = 1, }; +/* AXI CANFD 2.0 Data Bittiming constants as per AXI CANFD 2.0 spec */ +static struct can_bittiming_const xcan_data_bittiming_const_canfd2 = { + .name = DRIVER_NAME, + .tseg1_min = 1, + .tseg1_max = 32, + .tseg2_min = 1, + .tseg2_max = 16, + .sjw_max = 16, + .brp_min = 1, + .brp_max = 256, + .brp_inc = 1, +}; + /** * xcan_write_reg_le - Write a value to the device register little endian * @priv: Driver private data structure @@ -351,6 +388,7 @@ static int xcan_set_bittiming(struct net_device *ndev) { struct xcan_priv *priv = netdev_priv(ndev); struct can_bittiming *bt = &priv->can.bittiming; + struct can_bittiming *dbt = &priv->can.data_bittiming; u32 btr0, btr1; u32 is_config_mode; @@ -380,6 +418,24 @@ static int xcan_set_bittiming(struct net_device *ndev) priv->write_reg(priv, XCAN_BRPR_OFFSET, btr0); priv->write_reg(priv, XCAN_BTR_OFFSET, btr1); + if (priv->devtype.cantype == XAXI_CANFD || + priv->devtype.cantype == XAXI_CANFD_2_0) { + /* Setting Baud Rate prescalar value in F_BRPR Register */ + btr0 = dbt->brp - 1; + + /* Setting Time Segment 1 in BTR Register */ + btr1 = dbt->prop_seg + bt->phase_seg1 - 1; + + /* Setting Time Segment 2 in BTR Register */ + btr1 |= (dbt->phase_seg2 - 1) << priv->devtype.btr_ts2_shift; + + /* Setting Synchronous jump width in BTR Register */ + btr1 |= (dbt->sjw - 1) << priv->devtype.btr_sjw_shift; + + priv->write_reg(priv, XCAN_F_BRPR_OFFSET, btr0); + priv->write_reg(priv, XCAN_F_BTR_OFFSET, btr1); + } + netdev_dbg(ndev, "BRPR=0x%08x, BTR=0x%08x\n", priv->read_reg(priv, XCAN_BRPR_OFFSET), priv->read_reg(priv, XCAN_BTR_OFFSET)); @@ -499,7 +555,8 @@ static void xcan_write_frame(struct xcan_priv *priv, struct sk_buff *skb, int frame_offset) { u32 id, dlc, data[2] = {0, 0}; - struct can_frame *cf = (struct can_frame *)skb->data; + struct canfd_frame *cf = (struct canfd_frame *)skb->data; + u32 ramoff, dwindex = 0, i; /* Watch carefully on the bit sequence */ if (cf->can_id & CAN_EFF_FLAG) { @@ -528,26 +585,44 @@ static void xcan_write_frame(struct xcan_priv *priv, struct sk_buff *skb, id |= XCAN_IDR_SRR_MASK; } - dlc = cf->can_dlc << XCAN_DLCR_DLC_SHIFT; - - if (cf->can_dlc > 0) - data[0] = be32_to_cpup((__be32 *)(cf->data + 0)); - if (cf->can_dlc > 4) - data[1] = be32_to_cpup((__be32 *)(cf->data + 4)); + dlc = can_len2dlc(cf->len) << XCAN_DLCR_DLC_SHIFT; + if (can_is_canfd_skb(skb)) { + if (cf->flags & CANFD_BRS) + dlc |= XCAN_DLCR_BRS_MASK; + dlc |= XCAN_DLCR_EDL_MASK; + } priv->write_reg(priv, XCAN_FRAME_ID_OFFSET(frame_offset), id); /* If the CAN frame is RTR frame this write triggers transmission * (not on CAN FD) */ priv->write_reg(priv, XCAN_FRAME_DLC_OFFSET(frame_offset), dlc); - if (!(cf->can_id & CAN_RTR_FLAG)) { - priv->write_reg(priv, XCAN_FRAME_DW1_OFFSET(frame_offset), - data[0]); - /* If the CAN frame is Standard/Extended frame this - * write triggers transmission (not on CAN FD) - */ - priv->write_reg(priv, XCAN_FRAME_DW2_OFFSET(frame_offset), - data[1]); + if (priv->devtype.cantype == XAXI_CANFD || + priv->devtype.cantype == XAXI_CANFD_2_0) { + for (i = 0; i < cf->len; i += 4) { + ramoff = XCANFD_FRAME_DW_OFFSET(frame_offset, dwindex) + + (dwindex * XCANFD_DW_BYTES); + priv->write_reg(priv, ramoff, + be32_to_cpup((__be32 *)(cf->data + i))); + dwindex++; + } + } else { + if (cf->len > 0) + data[0] = be32_to_cpup((__be32 *)(cf->data + 0)); + if (cf->len > 4) + data[1] = be32_to_cpup((__be32 *)(cf->data + 4)); + + if (!(cf->can_id & CAN_RTR_FLAG)) { + priv->write_reg(priv, + XCAN_FRAME_DW1_OFFSET(frame_offset), + data[0]); + /* If the CAN frame is Standard/Extended frame this + * write triggers transmission (not on CAN FD) + */ + priv->write_reg(priv, + XCAN_FRAME_DW2_OFFSET(frame_offset), + data[1]); + } } } @@ -724,6 +799,113 @@ static int xcan_rx(struct net_device *ndev, int frame_base) return 1; } +/** + * xcanfd_rx - Is called from CAN isr to complete the received + * frame processing + * @ndev: Pointer to net_device structure + * @frame_base: Register offset to the frame to be read + * + * This function is invoked from the CAN isr(poll) to process the Rx frames. It + * does minimal processing and invokes "netif_receive_skb" to complete further + * processing. + * Return: 1 on success and 0 on failure. + */ +static int xcanfd_rx(struct net_device *ndev, int frame_base) +{ + struct xcan_priv *priv = netdev_priv(ndev); + struct net_device_stats *stats = &ndev->stats; + struct canfd_frame *cf; + struct sk_buff *skb; + u32 id_xcan, dlc, data[2] = {0, 0}, dwindex = 0, i, fsr, readindex; + + fsr = priv->read_reg(priv, XCAN_FSR_OFFSET); + if (fsr & XCAN_FSR_FL_MASK) { + readindex = fsr & XCAN_FSR_RI_MASK; + id_xcan = priv->read_reg(priv, + XCAN_FRAME_ID_OFFSET(frame_base)); + dlc = priv->read_reg(priv, XCAN_FRAME_DLC_OFFSET(frame_base)); + if (dlc & XCAN_DLCR_EDL_MASK) + skb = alloc_canfd_skb(ndev, &cf); + else + skb = alloc_can_skb(ndev, (struct can_frame **)&cf); + + if (unlikely(!skb)) { + stats->rx_dropped++; + return 0; + } + + /* Change Xilinx CANFD data length format to socketCAN data + * format + */ + if (dlc & XCAN_DLCR_EDL_MASK) + cf->len = can_dlc2len((dlc & XCAN_DLCR_DLC_MASK) >> + XCAN_DLCR_DLC_SHIFT); + else + cf->len = get_can_dlc((dlc & XCAN_DLCR_DLC_MASK) >> + XCAN_DLCR_DLC_SHIFT); + + /* Change Xilinx CAN ID format to socketCAN ID format */ + if (id_xcan & XCAN_IDR_IDE_MASK) { + /* The received frame is an Extended format frame */ + cf->can_id = (id_xcan & XCAN_IDR_ID1_MASK) >> 3; + cf->can_id |= (id_xcan & XCAN_IDR_ID2_MASK) >> + XCAN_IDR_ID2_SHIFT; + cf->can_id |= CAN_EFF_FLAG; + if (id_xcan & XCAN_IDR_RTR_MASK) + cf->can_id |= CAN_RTR_FLAG; + } else { + /* The received frame is a standard format frame */ + cf->can_id = (id_xcan & XCAN_IDR_ID1_MASK) >> + XCAN_IDR_ID1_SHIFT; + if (!(dlc & XCAN_DLCR_EDL_MASK) && (id_xcan & + XCAN_IDR_SRR_MASK)) + cf->can_id |= CAN_RTR_FLAG; + } + + /* Check the frame received is FD or not*/ + if (dlc & XCAN_DLCR_EDL_MASK) { + for (i = 0; i < cf->len; i += 4) { + if (priv->devtype.flags & XCAN_FLAG_CANFD_2) + data[0] = priv->read_reg(priv, + (XCAN_RXMSG_2_FRAME_OFFSET(readindex) + + (dwindex * XCANFD_DW_BYTES))); + else + data[0] = priv->read_reg(priv, + (XCAN_RXMSG_FRAME_OFFSET(readindex) + + (dwindex * XCANFD_DW_BYTES))); + *(__be32 *)(cf->data + i) = + cpu_to_be32(data[0]); + dwindex++; + } + } else { + for (i = 0; i < cf->len; i += 4) { + if (priv->devtype.flags & XCAN_FLAG_CANFD_2) + data[0] = priv->read_reg(priv, + XCAN_RXMSG_2_FRAME_OFFSET(readindex) + i); + else + data[0] = priv->read_reg(priv, + XCAN_RXMSG_FRAME_OFFSET(readindex) + i); + *(__be32 *)(cf->data + i) = + cpu_to_be32(data[0]); + } + } + /* Update FSR Register so that next packet will save to + * buffer + */ + fsr = priv->read_reg(priv, XCAN_FSR_OFFSET); + fsr |= XCAN_FSR_IRI_MASK; + priv->write_reg(priv, XCAN_FSR_OFFSET, fsr); + fsr = priv->read_reg(priv, XCAN_FSR_OFFSET); + stats->rx_bytes += cf->len; + stats->rx_packets++; + netif_receive_skb(skb); + + return 1; + } + /* If FSR Register is not updated with fill level */ + return 0; +} + /** * xcan_current_error_state - Get current error state from HW * @ndev: Pointer to net_device structure @@ -1035,7 +1217,10 @@ static int xcan_rx_poll(struct napi_struct *napi, int quota) while ((frame_offset = xcan_rx_fifo_get_next_frame(priv)) >= 0 && (work_done < quota)) { - work_done += xcan_rx(ndev, frame_offset); + if (xcan_rx_int_mask(priv) & XCAN_IXR_RXOK_MASK) + work_done += xcanfd_rx(ndev, frame_offset); + else + work_done += xcan_rx(ndev, frame_offset); if (priv->devtype.flags & XCAN_FLAG_RX_FIFO_MULTI) /* increment read index */ @@ -1577,6 +1762,19 @@ static int xcan_probe(struct platform_device *pdev) priv->can.do_get_berr_counter = xcan_get_berr_counter; priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_BERR_REPORTING; + + if (devtype->cantype == XAXI_CANFD) + priv->can.data_bittiming_const = + &xcan_data_bittiming_const_canfd; + + if (devtype->cantype == XAXI_CANFD_2_0) + priv->can.data_bittiming_const = + &xcan_data_bittiming_const_canfd2; + + if (devtype->cantype == XAXI_CANFD || + devtype->cantype == XAXI_CANFD_2_0) + priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD; + priv->reg_base = addr; priv->tx_max = tx_max; priv->devtype = *devtype; -- cgit v1.2.3 From 64d6ce8fe48e4768d3bcba7873a1a368162af334 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 19 Jun 2019 17:45:17 +0100 Subject: can: xilinx_can: clean up indentation issue A statement is indented one level too deep, fix this. Signed-off-by: Colin Ian King Reviewed-by: Michal Simek Signed-off-by: Marc Kleine-Budde --- drivers/net/can/xilinx_can.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/can/xilinx_can.c') diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index fadd54103c38..bd95cfaff857 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -1119,7 +1119,7 @@ static void xcan_err_interrupt(struct net_device *ndev, u32 isr) cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ; } } - priv->can.can_stats.bus_error++; + priv->can.can_stats.bus_error++; } if (skb) { -- cgit v1.2.3 From 3486cc40ccbfe4cbf55feecce88a792e3043c178 Mon Sep 17 00:00:00 2001 From: Anssi Hannula Date: Wed, 3 Apr 2019 15:18:53 +0300 Subject: can: xilinx_can: xcan_chip_start(): fix failure with invalid bus Currently the xilinx_can xcan_chip_start() function, called from .ndo_open() and via CAN_MODE_START (bus-off restart), waits for the SR register to show the wanted operating state, with a 1 sec timeout. However, that register bit will only be set once the HW has observed 11 consecutive recessive bits (BusIdle) on the bus. If the bus will not see the 11 bits (e.g. it is stuck dominant), the function will timeout and return an error. If this was done as part of a scheduled restart from bus-off, the interface will stay in bus-off state forever even if the bus recovers later. According to M_CAN and FLEXCAN documentation they also wait for 11 consecutive recessive bits, but their drivers do not seem to wait for that. To make the behavior consistent, modify xilinx_can to also not wait for the synchronization to complete. The only way for users to know for sure that the bus has been joined successfully is to see successfully received or transmitted frames. That does not seem optimal, but it is consistent with other drivers and we should have a properly working restart-ms with xilinx_can. Tested on ZynqMP with Xilinx CAN-FD 1.0. Fixes: b1201e44f50b ("can: xilinx CAN controller support") Signed-off-by: Anssi Hannula Tested-by: Appana Durga Kedareswara Rao Signed-off-by: Marc Kleine-Budde --- drivers/net/can/xilinx_can.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers/net/can/xilinx_can.c') diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index bd95cfaff857..c7d043a40837 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -456,9 +456,8 @@ static int xcan_set_bittiming(struct net_device *ndev) static int xcan_chip_start(struct net_device *ndev) { struct xcan_priv *priv = netdev_priv(ndev); - u32 reg_msr, reg_sr_mask; + u32 reg_msr; int err; - unsigned long timeout; u32 ier; /* Check if it is in reset mode */ @@ -484,10 +483,8 @@ static int xcan_chip_start(struct net_device *ndev) /* Check whether it is loopback mode or normal mode */ if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) { reg_msr = XCAN_MSR_LBACK_MASK; - reg_sr_mask = XCAN_SR_LBACK_MASK; } else { reg_msr = 0x0; - reg_sr_mask = XCAN_SR_NORMAL_MASK; } /* enable the first extended filter, if any, as cores with extended @@ -499,14 +496,6 @@ static int xcan_chip_start(struct net_device *ndev) priv->write_reg(priv, XCAN_MSR_OFFSET, reg_msr); priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_CEN_MASK); - timeout = jiffies + XCAN_TIMEOUT; - while (!(priv->read_reg(priv, XCAN_SR_OFFSET) & reg_sr_mask)) { - if (time_after(jiffies, timeout)) { - netdev_warn(ndev, - "timed out for correct mode\n"); - return -ETIMEDOUT; - } - } netdev_dbg(ndev, "status:#x%08x\n", priv->read_reg(priv, XCAN_SR_OFFSET)); -- cgit v1.2.3 From 6b0d35891c835319291f2c3b459e666fc809f831 Mon Sep 17 00:00:00 2001 From: Venkatesh Yadav Abbarapu Date: Mon, 12 Aug 2019 15:36:42 +0530 Subject: can: xilinx_can: xcan_probe(): skip error message on deferred probe When can clock is provided from the clock wizard, clock wizard driver may not be available when can driver probes resulting to the error message "Device clock not found error". As this error message is not very userful to the end user, skip printing it in the case of deferred probe. Fixes: b1201e44 ("can: xilinx CAN controller support") Signed-off-by: Appana Durga Kedareswara rao Signed-off-by: Venkatesh Yadav Abbarapu Signed-off-by: Michal Simek Signed-off-by: Marc Kleine-Budde --- drivers/net/can/xilinx_can.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net/can/xilinx_can.c') diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index c7d043a40837..161bb5e1f378 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -1780,7 +1780,8 @@ static int xcan_probe(struct platform_device *pdev) /* Getting the CAN can_clk info */ priv->can_clk = devm_clk_get(&pdev->dev, "can_clk"); if (IS_ERR(priv->can_clk)) { - dev_err(&pdev->dev, "Device clock not found.\n"); + if (PTR_ERR(priv->can_clk) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Device clock not found.\n"); ret = PTR_ERR(priv->can_clk); goto err_free; } -- cgit v1.2.3 From 93bbd6c5eeb1dbc1f826b4924c21dc71d14b25c8 Mon Sep 17 00:00:00 2001 From: Appana Durga Kedareswara rao Date: Mon, 12 Aug 2019 15:36:43 +0530 Subject: can: xilinx_can: xcanfd_rx(): fix FSR register handling in the RX path After commit c223da689324 ("can: xilinx_can: Add support for CANFD FD frames") the driver is updating the FSR IRI index multiple times (i.e in xcanfd_rx() and xcan_rx_fifo_get_next_frame()), It should be updated once per RX packet. This patch fixes this issue, also this patch removes the unnecessary fsr register checks in xcanfd_rx() API. Fixes: c223da6 ("can: xilinx_can: Add support for CANFD FD frames") Reviewed-by: Radhey Shyam Pandey Reviewed-by: Shubhrajyoti Datta Signed-off-by: Appana Durga Kedareswara rao Signed-off-by: Michal Simek Signed-off-by: Marc Kleine-Budde --- drivers/net/can/xilinx_can.c | 139 ++++++++++++++++++++----------------------- 1 file changed, 63 insertions(+), 76 deletions(-) (limited to 'drivers/net/can/xilinx_can.c') diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index 161bb5e1f378..2e5cbffc2f4e 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -808,91 +808,78 @@ static int xcanfd_rx(struct net_device *ndev, int frame_base) u32 id_xcan, dlc, data[2] = {0, 0}, dwindex = 0, i, fsr, readindex; fsr = priv->read_reg(priv, XCAN_FSR_OFFSET); - if (fsr & XCAN_FSR_FL_MASK) { - readindex = fsr & XCAN_FSR_RI_MASK; - id_xcan = priv->read_reg(priv, - XCAN_FRAME_ID_OFFSET(frame_base)); - dlc = priv->read_reg(priv, XCAN_FRAME_DLC_OFFSET(frame_base)); - if (dlc & XCAN_DLCR_EDL_MASK) - skb = alloc_canfd_skb(ndev, &cf); - else - skb = alloc_can_skb(ndev, (struct can_frame **)&cf); + readindex = fsr & XCAN_FSR_RI_MASK; + id_xcan = priv->read_reg(priv, XCAN_FRAME_ID_OFFSET(frame_base)); + dlc = priv->read_reg(priv, XCAN_FRAME_DLC_OFFSET(frame_base)); + if (dlc & XCAN_DLCR_EDL_MASK) + skb = alloc_canfd_skb(ndev, &cf); + else + skb = alloc_can_skb(ndev, (struct can_frame **)&cf); - if (unlikely(!skb)) { - stats->rx_dropped++; - return 0; - } + if (unlikely(!skb)) { + stats->rx_dropped++; + return 0; + } - /* Change Xilinx CANFD data length format to socketCAN data - * format - */ - if (dlc & XCAN_DLCR_EDL_MASK) - cf->len = can_dlc2len((dlc & XCAN_DLCR_DLC_MASK) >> + /* Change Xilinx CANFD data length format to socketCAN data + * format + */ + if (dlc & XCAN_DLCR_EDL_MASK) + cf->len = can_dlc2len((dlc & XCAN_DLCR_DLC_MASK) >> + XCAN_DLCR_DLC_SHIFT); + else + cf->len = get_can_dlc((dlc & XCAN_DLCR_DLC_MASK) >> XCAN_DLCR_DLC_SHIFT); - else - cf->len = get_can_dlc((dlc & XCAN_DLCR_DLC_MASK) >> - XCAN_DLCR_DLC_SHIFT); - - /* Change Xilinx CAN ID format to socketCAN ID format */ - if (id_xcan & XCAN_IDR_IDE_MASK) { - /* The received frame is an Extended format frame */ - cf->can_id = (id_xcan & XCAN_IDR_ID1_MASK) >> 3; - cf->can_id |= (id_xcan & XCAN_IDR_ID2_MASK) >> - XCAN_IDR_ID2_SHIFT; - cf->can_id |= CAN_EFF_FLAG; - if (id_xcan & XCAN_IDR_RTR_MASK) - cf->can_id |= CAN_RTR_FLAG; - } else { - /* The received frame is a standard format frame */ - cf->can_id = (id_xcan & XCAN_IDR_ID1_MASK) >> - XCAN_IDR_ID1_SHIFT; - if (!(dlc & XCAN_DLCR_EDL_MASK) && (id_xcan & - XCAN_IDR_SRR_MASK)) - cf->can_id |= CAN_RTR_FLAG; - } - /* Check the frame received is FD or not*/ - if (dlc & XCAN_DLCR_EDL_MASK) { - for (i = 0; i < cf->len; i += 4) { - if (priv->devtype.flags & XCAN_FLAG_CANFD_2) - data[0] = priv->read_reg(priv, + /* Change Xilinx CAN ID format to socketCAN ID format */ + if (id_xcan & XCAN_IDR_IDE_MASK) { + /* The received frame is an Extended format frame */ + cf->can_id = (id_xcan & XCAN_IDR_ID1_MASK) >> 3; + cf->can_id |= (id_xcan & XCAN_IDR_ID2_MASK) >> + XCAN_IDR_ID2_SHIFT; + cf->can_id |= CAN_EFF_FLAG; + if (id_xcan & XCAN_IDR_RTR_MASK) + cf->can_id |= CAN_RTR_FLAG; + } else { + /* The received frame is a standard format frame */ + cf->can_id = (id_xcan & XCAN_IDR_ID1_MASK) >> + XCAN_IDR_ID1_SHIFT; + if (!(dlc & XCAN_DLCR_EDL_MASK) && (id_xcan & + XCAN_IDR_SRR_MASK)) + cf->can_id |= CAN_RTR_FLAG; + } + + /* Check the frame received is FD or not*/ + if (dlc & XCAN_DLCR_EDL_MASK) { + for (i = 0; i < cf->len; i += 4) { + if (priv->devtype.flags & XCAN_FLAG_CANFD_2) + data[0] = priv->read_reg(priv, (XCAN_RXMSG_2_FRAME_OFFSET(readindex) + (dwindex * XCANFD_DW_BYTES))); - else - data[0] = priv->read_reg(priv, + else + data[0] = priv->read_reg(priv, (XCAN_RXMSG_FRAME_OFFSET(readindex) + - (dwindex * XCANFD_DW_BYTES))); - *(__be32 *)(cf->data + i) = - cpu_to_be32(data[0]); - dwindex++; - } - } else { - for (i = 0; i < cf->len; i += 4) { - if (priv->devtype.flags & XCAN_FLAG_CANFD_2) - data[0] = priv->read_reg(priv, - XCAN_RXMSG_2_FRAME_OFFSET(readindex) + i); - else - data[0] = priv->read_reg(priv, - XCAN_RXMSG_FRAME_OFFSET(readindex) + i); - *(__be32 *)(cf->data + i) = - cpu_to_be32(data[0]); - } + (dwindex * XCANFD_DW_BYTES))); + *(__be32 *)(cf->data + i) = cpu_to_be32(data[0]); + dwindex++; + } + } else { + for (i = 0; i < cf->len; i += 4) { + if (priv->devtype.flags & XCAN_FLAG_CANFD_2) + data[0] = priv->read_reg(priv, + XCAN_RXMSG_2_FRAME_OFFSET(readindex) + + i); + else + data[0] = priv->read_reg(priv, + XCAN_RXMSG_FRAME_OFFSET(readindex) + i); + *(__be32 *)(cf->data + i) = cpu_to_be32(data[0]); } - /* Update FSR Register so that next packet will save to - * buffer - */ - fsr = priv->read_reg(priv, XCAN_FSR_OFFSET); - fsr |= XCAN_FSR_IRI_MASK; - priv->write_reg(priv, XCAN_FSR_OFFSET, fsr); - fsr = priv->read_reg(priv, XCAN_FSR_OFFSET); - stats->rx_bytes += cf->len; - stats->rx_packets++; - netif_receive_skb(skb); - - return 1; } - /* If FSR Register is not updated with fill level */ - return 0; + stats->rx_bytes += cf->len; + stats->rx_packets++; + netif_receive_skb(skb); + + return 1; } /** -- cgit v1.2.3 From e6997dd2688403bf8f760bd9fd7ddb5c654bc8bd Mon Sep 17 00:00:00 2001 From: Appana Durga Kedareswara rao Date: Mon, 12 Aug 2019 15:36:44 +0530 Subject: can: xilinx_can: fix the data update logic for CANFD FD frames commit c223da689324 ("can: xilinx_can: Add support for CANFD FD frames") is writing data to a wrong offset for FD frames. This patch fixes this issue. Fixes: c223da6 ("can: xilinx_can: Add support for CANFD FD frames") Reviewed-by: Radhey Shyam Pandey Reviewed-by: Shubhrajyoti Datta Signed-off-by: Appana Durga Kedareswara rao Signed-off-by: Michal Simek Signed-off-by: Marc Kleine-Budde --- drivers/net/can/xilinx_can.c | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) (limited to 'drivers/net/can/xilinx_can.c') diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index 2e5cbffc2f4e..a312fe32cf12 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -66,8 +66,7 @@ enum xcan_reg { #define XCAN_FRAME_DLC_OFFSET(frame_base) ((frame_base) + 0x04) #define XCAN_FRAME_DW1_OFFSET(frame_base) ((frame_base) + 0x08) #define XCAN_FRAME_DW2_OFFSET(frame_base) ((frame_base) + 0x0C) -#define XCANFD_FRAME_DW_OFFSET(frame_base, n) (((frame_base) + 0x08) + \ - ((n) * XCAN_CANFD_FRAME_SIZE)) +#define XCANFD_FRAME_DW_OFFSET(frame_base) ((frame_base) + 0x08) #define XCAN_CANFD_FRAME_SIZE 0x48 #define XCAN_TXMSG_FRAME_OFFSET(n) (XCAN_TXMSG_BASE_OFFSET + \ @@ -589,7 +588,7 @@ static void xcan_write_frame(struct xcan_priv *priv, struct sk_buff *skb, if (priv->devtype.cantype == XAXI_CANFD || priv->devtype.cantype == XAXI_CANFD_2_0) { for (i = 0; i < cf->len; i += 4) { - ramoff = XCANFD_FRAME_DW_OFFSET(frame_offset, dwindex) + + ramoff = XCANFD_FRAME_DW_OFFSET(frame_offset) + (dwindex * XCANFD_DW_BYTES); priv->write_reg(priv, ramoff, be32_to_cpup((__be32 *)(cf->data + i))); @@ -805,10 +804,8 @@ static int xcanfd_rx(struct net_device *ndev, int frame_base) struct net_device_stats *stats = &ndev->stats; struct canfd_frame *cf; struct sk_buff *skb; - u32 id_xcan, dlc, data[2] = {0, 0}, dwindex = 0, i, fsr, readindex; + u32 id_xcan, dlc, data[2] = {0, 0}, dwindex = 0, i, dw_offset; - fsr = priv->read_reg(priv, XCAN_FSR_OFFSET); - readindex = fsr & XCAN_FSR_RI_MASK; id_xcan = priv->read_reg(priv, XCAN_FRAME_ID_OFFSET(frame_base)); dlc = priv->read_reg(priv, XCAN_FRAME_DLC_OFFSET(frame_base)); if (dlc & XCAN_DLCR_EDL_MASK) @@ -852,26 +849,16 @@ static int xcanfd_rx(struct net_device *ndev, int frame_base) /* Check the frame received is FD or not*/ if (dlc & XCAN_DLCR_EDL_MASK) { for (i = 0; i < cf->len; i += 4) { - if (priv->devtype.flags & XCAN_FLAG_CANFD_2) - data[0] = priv->read_reg(priv, - (XCAN_RXMSG_2_FRAME_OFFSET(readindex) + - (dwindex * XCANFD_DW_BYTES))); - else - data[0] = priv->read_reg(priv, - (XCAN_RXMSG_FRAME_OFFSET(readindex) + - (dwindex * XCANFD_DW_BYTES))); + dw_offset = XCANFD_FRAME_DW_OFFSET(frame_base) + + (dwindex * XCANFD_DW_BYTES); + data[0] = priv->read_reg(priv, dw_offset); *(__be32 *)(cf->data + i) = cpu_to_be32(data[0]); dwindex++; } } else { for (i = 0; i < cf->len; i += 4) { - if (priv->devtype.flags & XCAN_FLAG_CANFD_2) - data[0] = priv->read_reg(priv, - XCAN_RXMSG_2_FRAME_OFFSET(readindex) + - i); - else - data[0] = priv->read_reg(priv, - XCAN_RXMSG_FRAME_OFFSET(readindex) + i); + dw_offset = XCANFD_FRAME_DW_OFFSET(frame_base); + data[0] = priv->read_reg(priv, dw_offset + i); *(__be32 *)(cf->data + i) = cpu_to_be32(data[0]); } } -- cgit v1.2.3 From 9d06bcb9aa48dc4fc474dc8441a036bc4a090270 Mon Sep 17 00:00:00 2001 From: Appana Durga Kedareswara rao Date: Mon, 12 Aug 2019 15:36:45 +0530 Subject: can: xilinx_can: xcan_rx_fifo_get_next_frame(): fix FSR register FL and RI mask values for canfd 2.0 For CANFD 2.0 IP configuration existing driver is using incorrect mask values for FSR register FL and RI fields. Fixes: c223da6 ("can: xilinx_can: Add support for CANFD FD frames") Signed-off-by: Appana Durga Kedareswara rao Acked-by: Shubhrajyoti Datta Signed-off-by: Michal Simek Signed-off-by: Marc Kleine-Budde --- drivers/net/can/xilinx_can.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers/net/can/xilinx_can.c') diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index a312fe32cf12..f939f7ac5b64 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -123,8 +123,10 @@ enum xcan_reg { #define XCAN_IDR_RTR_MASK 0x00000001 /* Remote TX request */ #define XCAN_DLCR_DLC_MASK 0xF0000000 /* Data length code */ #define XCAN_FSR_FL_MASK 0x00003F00 /* RX Fill Level */ +#define XCAN_2_FSR_FL_MASK 0x00007F00 /* RX Fill Level */ #define XCAN_FSR_IRI_MASK 0x00000080 /* RX Increment Read Index */ #define XCAN_FSR_RI_MASK 0x0000001F /* RX Read Index */ +#define XCAN_2_FSR_RI_MASK 0x0000003F /* RX Read Index */ #define XCAN_DLCR_EDL_MASK 0x08000000 /* EDL Mask in DLC */ #define XCAN_DLCR_BRS_MASK 0x04000000 /* BRS Mask in DLC */ @@ -1127,7 +1129,7 @@ static int xcan_rx_fifo_get_next_frame(struct xcan_priv *priv) int offset; if (priv->devtype.flags & XCAN_FLAG_RX_FIFO_MULTI) { - u32 fsr; + u32 fsr, mask; /* clear RXOK before the is-empty check so that any newly * received frame will reassert it without a race @@ -1137,12 +1139,17 @@ static int xcan_rx_fifo_get_next_frame(struct xcan_priv *priv) fsr = priv->read_reg(priv, XCAN_FSR_OFFSET); /* check if RX FIFO is empty */ - if (!(fsr & XCAN_FSR_FL_MASK)) + if (priv->devtype.flags & XCAN_FLAG_CANFD_2) + mask = XCAN_2_FSR_FL_MASK; + else + mask = XCAN_FSR_FL_MASK; + + if (!(fsr & mask)) return -ENOENT; if (priv->devtype.flags & XCAN_FLAG_CANFD_2) offset = - XCAN_RXMSG_2_FRAME_OFFSET(fsr & XCAN_FSR_RI_MASK); + XCAN_RXMSG_2_FRAME_OFFSET(fsr & XCAN_2_FSR_RI_MASK); else offset = XCAN_RXMSG_FRAME_OFFSET(fsr & XCAN_FSR_RI_MASK); -- cgit v1.2.3 From 3e994ff28f867a20ae0dd055a5e4a4a34aad9c3c Mon Sep 17 00:00:00 2001 From: Srinivas Neeli Date: Mon, 12 Aug 2019 15:36:46 +0530 Subject: can: xilinx_can: xcan_set_bittiming(): fix the data phase btr1 calculation While calculating bitrate for the data phase, the driver is using phase segment 1 of the arbitration phase instead of the data phase. Fixes: c223da6 ("can: xilinx_can: Add support for CANFD FD frames") Signed-off-by: Appana Durga Kedareswara rao Signed-off-by: Srinivas Neeli Acked-by: Shubhrajyoti Datta Signed-off-by: Michal Simek Signed-off-by: Marc Kleine-Budde --- drivers/net/can/xilinx_can.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/can/xilinx_can.c') diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index f939f7ac5b64..911b34316c9d 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -425,7 +425,7 @@ static int xcan_set_bittiming(struct net_device *ndev) btr0 = dbt->brp - 1; /* Setting Time Segment 1 in BTR Register */ - btr1 = dbt->prop_seg + bt->phase_seg1 - 1; + btr1 = dbt->prop_seg + dbt->phase_seg1 - 1; /* Setting Time Segment 2 in BTR Register */ btr1 |= (dbt->phase_seg2 - 1) << priv->devtype.btr_ts2_shift; -- cgit v1.2.3