All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC]: flexcan FD support - can-next 2020-09-22
@ 2020-09-22 14:44 Marc Kleine-Budde
  2020-09-22 14:44 ` [PATCH 01/20] can: flexcan: sort include files alphabetically Marc Kleine-Budde
                   ` (19 more replies)
  0 siblings, 20 replies; 30+ messages in thread
From: Marc Kleine-Budde @ 2020-09-22 14:44 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, michael, qiangqing.zhang

Hello

here is my current flexcan FD support branch.

changes since last post:
- add ISO mode
- clear reg_fdcbt prior to assigning bit timing values
- use ctrlmode_supported instead of quirks to check for CAN-FD support
- fix check for activated CAN-FD mode using ctrlmode instead of ctrlmode_supported

regards,
Marc



^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 01/20] can: flexcan: sort include files alphabetically
  2020-09-22 14:44 [RFC]: flexcan FD support - can-next 2020-09-22 Marc Kleine-Budde
@ 2020-09-22 14:44 ` Marc Kleine-Budde
  2020-09-22 14:44 ` [PATCH 02/20] can: flexcan: flexcan_exit_stop_mode(): remove stray empty line Marc Kleine-Budde
                   ` (18 subsequent siblings)
  19 siblings, 0 replies; 30+ messages in thread
From: Marc Kleine-Budde @ 2020-09-22 14:44 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, michael, qiangqing.zhang, Marc Kleine-Budde

This patch sorts the include files alphabetically.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 19403e88daa3..6198319d8fac 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -9,7 +9,6 @@
 //
 // Based on code originally by Andrey Volkov <avolkov@varma-el.com>
 
-#include <linux/netdevice.h>
 #include <linux/can.h>
 #include <linux/can/dev.h>
 #include <linux/can/error.h>
@@ -21,12 +20,13 @@
 #include <linux/io.h>
 #include <linux/mfd/syscon.h>
 #include <linux/module.h>
+#include <linux/netdevice.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
-#include <linux/regulator/consumer.h>
 #include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
 
 #define DRV_NAME			"flexcan"
 
-- 
2.28.0


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 02/20] can: flexcan: flexcan_exit_stop_mode(): remove stray empty line
  2020-09-22 14:44 [RFC]: flexcan FD support - can-next 2020-09-22 Marc Kleine-Budde
  2020-09-22 14:44 ` [PATCH 01/20] can: flexcan: sort include files alphabetically Marc Kleine-Budde
@ 2020-09-22 14:44 ` Marc Kleine-Budde
  2020-09-22 14:44 ` [PATCH 03/20] can: flexcan: more register names Marc Kleine-Budde
                   ` (17 subsequent siblings)
  19 siblings, 0 replies; 30+ messages in thread
From: Marc Kleine-Budde @ 2020-09-22 14:44 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, michael, qiangqing.zhang, Marc Kleine-Budde

This patch removes a stray empty line from the flexcan_exit_stop_mode()
function.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 6198319d8fac..43fa38033383 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -457,7 +457,6 @@ static inline int flexcan_exit_stop_mode(struct flexcan_priv *priv)
 	regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr,
 			   1 << priv->stm.req_bit, 0);
 
-
 	reg_mcr = priv->read(&regs->mcr);
 	reg_mcr &= ~FLEXCAN_MCR_SLF_WAK;
 	priv->write(reg_mcr, &regs->mcr);
-- 
2.28.0


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 03/20] can: flexcan: more register names
  2020-09-22 14:44 [RFC]: flexcan FD support - can-next 2020-09-22 Marc Kleine-Budde
  2020-09-22 14:44 ` [PATCH 01/20] can: flexcan: sort include files alphabetically Marc Kleine-Budde
  2020-09-22 14:44 ` [PATCH 02/20] can: flexcan: flexcan_exit_stop_mode(): remove stray empty line Marc Kleine-Budde
@ 2020-09-22 14:44 ` Marc Kleine-Budde
  2020-09-22 14:44 ` [PATCH 04/20] can: flexcan: struct flexcan_regs: document registers not affected by soft reset Marc Kleine-Budde
                   ` (16 subsequent siblings)
  19 siblings, 0 replies; 30+ messages in thread
From: Marc Kleine-Budde @ 2020-09-22 14:44 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, michael, qiangqing.zhang, Marc Kleine-Budde

This patch adds some new register names and tries to ensure with a
static_assert that the documented offset is correct.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 43fa38033383..c24d7b63e1b9 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -205,7 +205,7 @@ struct flexcan_regs {
 	u32 mcr;		/* 0x00 */
 	u32 ctrl;		/* 0x04 */
 	u32 timer;		/* 0x08 */
-	u32 _reserved1;		/* 0x0c */
+	u32 tcr;		/* 0x0c */
 	u32 rxgmask;		/* 0x10 */
 	u32 rx14mask;		/* 0x14 */
 	u32 rx15mask;		/* 0x18 */
@@ -225,7 +225,11 @@ struct flexcan_regs {
 	u32 crcr;		/* 0x44 */
 	u32 rxfgmask;		/* 0x48 */
 	u32 rxfir;		/* 0x4c */
-	u32 _reserved3[12];	/* 0x50 */
+	u32 cbt;		/* 0x50 */
+	u32 _reserved2;		/* 0x54 */
+	u32 dbg1;		/* 0x58 */
+	u32 dbg2;		/* 0x5c */
+	u32 _reserved3[8];	/* 0x60 */
 	u8 mb[2][512];		/* 0x80 */
 	/* FIFO-mode:
 	 *			MB
@@ -250,8 +254,14 @@ struct flexcan_regs {
 	u32 rerrdr;		/* 0xaf4 */
 	u32 rerrsynr;		/* 0xaf8 */
 	u32 errsr;		/* 0xafc */
+	u32 _reserved7[64];	/* 0xb00 */
+	u32 fdctrl;		/* 0xc00 */
+	u32 fdcbt;		/* 0xc04 */
+	u32 fdcrc;		/* 0xc08 */
 };
 
+static_assert(sizeof(struct flexcan_regs) == 0x4 + 0xc08);
+
 struct flexcan_devtype_data {
 	u32 quirks;		/* quirks needed for different IP cores */
 };
-- 
2.28.0


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 04/20] can: flexcan: struct flexcan_regs: document registers not affected by soft reset
  2020-09-22 14:44 [RFC]: flexcan FD support - can-next 2020-09-22 Marc Kleine-Budde
                   ` (2 preceding siblings ...)
  2020-09-22 14:44 ` [PATCH 03/20] can: flexcan: more register names Marc Kleine-Budde
@ 2020-09-22 14:44 ` Marc Kleine-Budde
  2020-09-22 14:44 ` [PATCH 05/20] can: flexcan: quirks: get rid of long lines Marc Kleine-Budde
                   ` (15 subsequent siblings)
  19 siblings, 0 replies; 30+ messages in thread
From: Marc Kleine-Budde @ 2020-09-22 14:44 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, michael, qiangqing.zhang, Marc Kleine-Budde

This patch documents which registers are not affected by a soft reset of the
flexcan IP core.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index c24d7b63e1b9..224000f53a88 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -203,12 +203,12 @@ struct flexcan_mb {
 /* Structure of the hardware registers */
 struct flexcan_regs {
 	u32 mcr;		/* 0x00 */
-	u32 ctrl;		/* 0x04 */
+	u32 ctrl;		/* 0x04 - Not affected by Soft Reset */
 	u32 timer;		/* 0x08 */
 	u32 tcr;		/* 0x0c */
-	u32 rxgmask;		/* 0x10 */
-	u32 rx14mask;		/* 0x14 */
-	u32 rx15mask;		/* 0x18 */
+	u32 rxgmask;		/* 0x10 - Not affected by Soft Reset */
+	u32 rx14mask;		/* 0x14 - Not affected by Soft Reset */
+	u32 rx15mask;		/* 0x18 - Not affected by Soft Reset */
 	u32 ecr;		/* 0x1c */
 	u32 esr;		/* 0x20 */
 	u32 imask2;		/* 0x24 */
@@ -217,20 +217,20 @@ struct flexcan_regs {
 	u32 iflag1;		/* 0x30 */
 	union {			/* 0x34 */
 		u32 gfwr_mx28;	/* MX28, MX53 */
-		u32 ctrl2;	/* MX6, VF610 */
+		u32 ctrl2;	/* MX6, VF610 - Not affected by Soft Reset */
 	};
 	u32 esr2;		/* 0x38 */
 	u32 imeur;		/* 0x3c */
 	u32 lrfr;		/* 0x40 */
 	u32 crcr;		/* 0x44 */
 	u32 rxfgmask;		/* 0x48 */
-	u32 rxfir;		/* 0x4c */
-	u32 cbt;		/* 0x50 */
+	u32 rxfir;		/* 0x4c - Not affected by Soft Reset */
+	u32 cbt;		/* 0x50 - Not affected by Soft Reset */
 	u32 _reserved2;		/* 0x54 */
 	u32 dbg1;		/* 0x58 */
 	u32 dbg2;		/* 0x5c */
 	u32 _reserved3[8];	/* 0x60 */
-	u8 mb[2][512];		/* 0x80 */
+	u8 mb[2][512];		/* 0x80 - Not affected by Soft Reset */
 	/* FIFO-mode:
 	 *			MB
 	 * 0x080...0x08f	0	RX message buffer
@@ -242,7 +242,7 @@ struct flexcan_regs {
 	 *				(mx6, vf610)
 	 */
 	u32 _reserved4[256];	/* 0x480 */
-	u32 rximr[64];		/* 0x880 */
+	u32 rximr[64];		/* 0x880 - Not affected by Soft Reset */
 	u32 _reserved5[24];	/* 0x980 */
 	u32 gfwr_mx6;		/* 0x9e0 - MX6 */
 	u32 _reserved6[63];	/* 0x9e4 */
@@ -255,8 +255,8 @@ struct flexcan_regs {
 	u32 rerrsynr;		/* 0xaf8 */
 	u32 errsr;		/* 0xafc */
 	u32 _reserved7[64];	/* 0xb00 */
-	u32 fdctrl;		/* 0xc00 */
-	u32 fdcbt;		/* 0xc04 */
+	u32 fdctrl;		/* 0xc00 - Not affected by Soft Reset */
+	u32 fdcbt;		/* 0xc04 - Not affected by Soft Reset */
 	u32 fdcrc;		/* 0xc08 */
 };
 
-- 
2.28.0


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 05/20] can: flexcan: quirks: get rid of long lines
  2020-09-22 14:44 [RFC]: flexcan FD support - can-next 2020-09-22 Marc Kleine-Budde
                   ` (3 preceding siblings ...)
  2020-09-22 14:44 ` [PATCH 04/20] can: flexcan: struct flexcan_regs: document registers not affected by soft reset Marc Kleine-Budde
@ 2020-09-22 14:44 ` Marc Kleine-Budde
  2020-09-22 14:44 ` [PATCH 06/20] can: flexcan: Ack wakeup interrupt separately Marc Kleine-Budde
                   ` (14 subsequent siblings)
  19 siblings, 0 replies; 30+ messages in thread
From: Marc Kleine-Budde @ 2020-09-22 14:44 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, michael, qiangqing.zhang, Marc Kleine-Budde

This patch reformats the quirks to get rid of long lines.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 25 +++++++++++++++++--------
 1 file changed, 17 insertions(+), 8 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 224000f53a88..b180dd1ba763 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -184,14 +184,23 @@
  *
  * Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected.
  */
-#define FLEXCAN_QUIRK_BROKEN_WERR_STATE	BIT(1) /* [TR]WRN_INT not connected */
-#define FLEXCAN_QUIRK_DISABLE_RXFG	BIT(2) /* Disable RX FIFO Global mask */
-#define FLEXCAN_QUIRK_ENABLE_EACEN_RRS	BIT(3) /* Enable EACEN and RRS bit in ctrl2 */
-#define FLEXCAN_QUIRK_DISABLE_MECR	BIT(4) /* Disable Memory error detection */
-#define FLEXCAN_QUIRK_USE_OFF_TIMESTAMP	BIT(5) /* Use timestamp based offloading */
-#define FLEXCAN_QUIRK_BROKEN_PERR_STATE	BIT(6) /* No interrupt for error passive */
-#define FLEXCAN_QUIRK_DEFAULT_BIG_ENDIAN	BIT(7) /* default to BE register access */
-#define FLEXCAN_QUIRK_SETUP_STOP_MODE		BIT(8) /* Setup stop mode to support wakeup */
+
+/* [TR]WRN_INT not connected */
+#define FLEXCAN_QUIRK_BROKEN_WERR_STATE BIT(1)
+ /* Disable RX FIFO Global mask */
+#define FLEXCAN_QUIRK_DISABLE_RXFG BIT(2)
+/* Enable EACEN and RRS bit in ctrl2 */
+#define FLEXCAN_QUIRK_ENABLE_EACEN_RRS  BIT(3)
+/* Disable Memory error detection */
+#define FLEXCAN_QUIRK_DISABLE_MECR BIT(4)
+/* Use timestamp based offloading */
+#define FLEXCAN_QUIRK_USE_OFF_TIMESTAMP BIT(5)
+/* No interrupt for error passive */
+#define FLEXCAN_QUIRK_BROKEN_PERR_STATE BIT(6)
+/* default to BE register access */
+#define FLEXCAN_QUIRK_DEFAULT_BIG_ENDIAN BIT(7)
+/* Setup stop mode to support wakeup */
+#define FLEXCAN_QUIRK_SETUP_STOP_MODE BIT(8)
 
 /* Structure of the message buffer */
 struct flexcan_mb {
-- 
2.28.0


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 06/20] can: flexcan: Ack wakeup interrupt separately
  2020-09-22 14:44 [RFC]: flexcan FD support - can-next 2020-09-22 Marc Kleine-Budde
                   ` (4 preceding siblings ...)
  2020-09-22 14:44 ` [PATCH 05/20] can: flexcan: quirks: get rid of long lines Marc Kleine-Budde
@ 2020-09-22 14:44 ` Marc Kleine-Budde
  2020-09-22 14:44 ` [PATCH 07/20] can: flexcan: flexcan_probe(): make regulator xceiver optional Marc Kleine-Budde
                   ` (13 subsequent siblings)
  19 siblings, 0 replies; 30+ messages in thread
From: Marc Kleine-Budde @ 2020-09-22 14:44 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, michael, qiangqing.zhang, Marc Kleine-Budde

From: Joakim Zhang <qiangqing.zhang@nxp.com>

As FLEXCAN_ESR_ALL_INT is for all bus errors and state change IRQ
sources, strictly speaking FLEXCAN_ESR_WAK_INT does not belong to these.
So add wakeup interrupt ack separately to existing ack of the
interrupts.

Suggested-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
Link: https://lore.kernel.org/r/20191204113249.3381-3-qiangqing.zhang@nxp.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index b180dd1ba763..06cddc468739 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -134,8 +134,7 @@
 	(FLEXCAN_ESR_ERR_BUS | FLEXCAN_ESR_ERR_STATE)
 #define FLEXCAN_ESR_ALL_INT \
 	(FLEXCAN_ESR_TWRN_INT | FLEXCAN_ESR_RWRN_INT | \
-	 FLEXCAN_ESR_BOFF_INT | FLEXCAN_ESR_ERR_INT | \
-	 FLEXCAN_ESR_WAK_INT)
+	 FLEXCAN_ESR_BOFF_INT | FLEXCAN_ESR_ERR_INT)
 
 /* FLEXCAN interrupt flag register (IFLAG) bits */
 /* Errata ERR005829 step7: Reserve first valid MB */
@@ -979,10 +978,10 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
 
 	reg_esr = priv->read(&regs->esr);
 
-	/* ACK all bus error and state change IRQ sources */
-	if (reg_esr & FLEXCAN_ESR_ALL_INT) {
+	/* ACK all bus error, state change and wake IRQ sources */
+	if (reg_esr & (FLEXCAN_ESR_ALL_INT | FLEXCAN_ESR_WAK_INT)) {
 		handled = IRQ_HANDLED;
-		priv->write(reg_esr & FLEXCAN_ESR_ALL_INT, &regs->esr);
+		priv->write(reg_esr & (FLEXCAN_ESR_ALL_INT | FLEXCAN_ESR_WAK_INT), &regs->esr);
 	}
 
 	/* state change interrupt or broken error state quirk fix is enabled */
-- 
2.28.0


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 07/20] can: flexcan: flexcan_probe(): make regulator xceiver optional
  2020-09-22 14:44 [RFC]: flexcan FD support - can-next 2020-09-22 Marc Kleine-Budde
                   ` (5 preceding siblings ...)
  2020-09-22 14:44 ` [PATCH 06/20] can: flexcan: Ack wakeup interrupt separately Marc Kleine-Budde
@ 2020-09-22 14:44 ` Marc Kleine-Budde
  2020-09-22 14:44 ` [PATCH 08/20] can: flexcan: Add check for transceiver maximum bitrate limitation Marc Kleine-Budde
                   ` (12 subsequent siblings)
  19 siblings, 0 replies; 30+ messages in thread
From: Marc Kleine-Budde @ 2020-09-22 14:44 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, michael, qiangqing.zhang, Marc Kleine-Budde

As the transcevier regulator is optional, this patch switches from
devm_regulator_get() to devm_regulator_get_optional(). This gets rid of "using
dummy regulator" warning message from the regulator core, if no regulator is
available.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 06cddc468739..52b53ff223f4 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -1579,11 +1579,13 @@ static int flexcan_probe(struct platform_device *pdev)
 	u8 clk_src = 1;
 	u32 clock_freq = 0;
 
-	reg_xceiver = devm_regulator_get(&pdev->dev, "xceiver");
+	reg_xceiver = devm_regulator_get_optional(&pdev->dev, "xceiver");
 	if (PTR_ERR(reg_xceiver) == -EPROBE_DEFER)
 		return -EPROBE_DEFER;
-	else if (IS_ERR(reg_xceiver))
+	else if (PTR_ERR(reg_xceiver) == -ENODEV)
 		reg_xceiver = NULL;
+	else if (IS_ERR(reg_xceiver))
+		return PTR_ERR(reg_xceiver);
 
 	if (pdev->dev.of_node) {
 		of_property_read_u32(pdev->dev.of_node,
-- 
2.28.0


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 08/20] can: flexcan: Add check for transceiver maximum bitrate limitation
  2020-09-22 14:44 [RFC]: flexcan FD support - can-next 2020-09-22 Marc Kleine-Budde
                   ` (6 preceding siblings ...)
  2020-09-22 14:44 ` [PATCH 07/20] can: flexcan: flexcan_probe(): make regulator xceiver optional Marc Kleine-Budde
@ 2020-09-22 14:44 ` Marc Kleine-Budde
  2020-09-22 14:44 ` [PATCH 09/20] can: flexcan: add correctable errors correction when HW supports ECC Marc Kleine-Budde
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 30+ messages in thread
From: Marc Kleine-Budde @ 2020-09-22 14:44 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, michael, qiangqing.zhang, Marc Kleine-Budde

From: Joakim Zhang <qiangqing.zhang@nxp.com>

CAN FD can transmit up to 8Mbps, but some transceivers only can support
5Mbps, so add check in driver.

Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
Link: https://lore.kernel.org/r/20191030064245.12923-2-qiangqing.zhang@nxp.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 52b53ff223f4..5c6903e23c01 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -1674,6 +1674,7 @@ static int flexcan_probe(struct platform_device *pdev)
 		goto failed_register;
 	}
 
+	of_can_transceiver(dev);
 	devm_can_led_init(dev);
 
 	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE) {
-- 
2.28.0


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 09/20] can: flexcan: add correctable errors correction when HW supports ECC
  2020-09-22 14:44 [RFC]: flexcan FD support - can-next 2020-09-22 Marc Kleine-Budde
                   ` (7 preceding siblings ...)
  2020-09-22 14:44 ` [PATCH 08/20] can: flexcan: Add check for transceiver maximum bitrate limitation Marc Kleine-Budde
@ 2020-09-22 14:44 ` Marc Kleine-Budde
  2020-09-22 14:44 ` [PATCH 10/20] can: flexcan: flexcan_chip_stop(): add error handling and propagate error value Marc Kleine-Budde
                   ` (10 subsequent siblings)
  19 siblings, 0 replies; 30+ messages in thread
From: Marc Kleine-Budde @ 2020-09-22 14:44 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, michael, qiangqing.zhang, Marc Kleine-Budde

From: Joakim Zhang <qiangqing.zhang@nxp.com>

commit cdce844865be ("can: flexcan: add vf610 support for FlexCAN")
From above commit by Stefan Agner, the patch just disables
non-correctable errors interrupt and freeze mode. It still can correct
the correctable errors since ECC enabled by default after reset (MECR[ECCDIS]=0,
enable memory error correct) if HW supports ECC.

commit 5e269324db5a ("can: flexcan: disable completely the ECC mechanism")
From above commit by Joakim Zhang, the patch disables ECC completely (assert
MECR[ECCDIS]) according to the explanation of FLEXCAN_QUIRK_DISABLE_MECR that
disable memory error detection. This cause correctable errors cannot be
corrected even HW supports ECC.

The error correction mechanism ensures that in this 13-bit word, errors
in one bit can be corrected (correctable errors) and errors in two bits can
be detected but not corrected (non-correctable errors). Errors in more than
two bits may not be detected.

If HW supports ECC, we can use this to correct the correctable errors detected
from FlexCAN memory. Then disable non-correctable errors interrupt and freeze
mode to avoid that put FlexCAN in freeze mode.

This patch adds correctable errors correction when HW supports ECC, and
modify explanation for FLEXCAN_QUIRK_DISABLE_MECR.

Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
Link: https://lore.kernel.org/r/20200416093126.15242-1-qiangqing.zhang@nxp.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 31 +++++++++++++++++++++++--------
 1 file changed, 23 insertions(+), 8 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 5c6903e23c01..52d73115c7fd 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -190,7 +190,7 @@
 #define FLEXCAN_QUIRK_DISABLE_RXFG BIT(2)
 /* Enable EACEN and RRS bit in ctrl2 */
 #define FLEXCAN_QUIRK_ENABLE_EACEN_RRS  BIT(3)
-/* Disable Memory error detection */
+/* Disable non-correctable errors interrupt and freeze mode */
 #define FLEXCAN_QUIRK_DISABLE_MECR BIT(4)
 /* Use timestamp based offloading */
 #define FLEXCAN_QUIRK_USE_OFF_TIMESTAMP BIT(5)
@@ -1221,28 +1221,43 @@ static int flexcan_chip_start(struct net_device *dev)
 	for (i = 0; i < priv->mb_count; i++)
 		priv->write(0, &regs->rximr[i]);
 
-	/* On Vybrid, disable memory error detection interrupts
-	 * and freeze mode.
-	 * This also works around errata e5295 which generates
-	 * false positive memory errors and put the device in
-	 * freeze mode.
+	/* On Vybrid, disable non-correctable errors interrupt and
+	 * freeze mode. It still can correct the correctable errors
+	 * when HW supports ECC.
+	 *
+	 * This also works around errata e5295 which generates false
+	 * positive memory errors and put the device in freeze mode.
 	 */
 	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_DISABLE_MECR) {
 		/* Follow the protocol as described in "Detection
 		 * and Correction of Memory Errors" to write to
-		 * MECR register
+		 * MECR register (step 1 - 5)
+		 *
+		 * 1. By default, CTRL2[ECRWRE] = 0, MECR[ECRWRDIS] = 1
+		 * 2. set CTRL2[ECRWRE]
 		 */
 		reg_ctrl2 = priv->read(&regs->ctrl2);
 		reg_ctrl2 |= FLEXCAN_CTRL2_ECRWRE;
 		priv->write(reg_ctrl2, &regs->ctrl2);
 
+		/* 3. clear MECR[ECRWRDIS] */
 		reg_mecr = priv->read(&regs->mecr);
 		reg_mecr &= ~FLEXCAN_MECR_ECRWRDIS;
 		priv->write(reg_mecr, &regs->mecr);
-		reg_mecr |= FLEXCAN_MECR_ECCDIS;
+
+		/* 4. all writes to MECR must keep MECR[ECRWRDIS] cleared */
 		reg_mecr &= ~(FLEXCAN_MECR_NCEFAFRZ | FLEXCAN_MECR_HANCEI_MSK |
 			      FLEXCAN_MECR_FANCEI_MSK);
 		priv->write(reg_mecr, &regs->mecr);
+
+		/* 5. after configuration done, lock MECR by either
+		 * setting MECR[ECRWRDIS] or clearing CTRL2[ECRWRE]
+		 */
+		reg_mecr |= FLEXCAN_MECR_ECRWRDIS;
+		priv->write(reg_mecr, &regs->mecr);
+
+		reg_ctrl2 &= ~FLEXCAN_CTRL2_ECRWRE;
+		priv->write(reg_ctrl2, &regs->ctrl2);
 	}
 
 	err = flexcan_transceiver_enable(priv);
-- 
2.28.0


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 10/20] can: flexcan: flexcan_chip_stop(): add error handling and propagate error value
  2020-09-22 14:44 [RFC]: flexcan FD support - can-next 2020-09-22 Marc Kleine-Budde
                   ` (8 preceding siblings ...)
  2020-09-22 14:44 ` [PATCH 09/20] can: flexcan: add correctable errors correction when HW supports ECC Marc Kleine-Budde
@ 2020-09-22 14:44 ` Marc Kleine-Budde
  2020-09-22 14:44 ` [PATCH 11/20] can: flexcan: disable clocks during stop mode Marc Kleine-Budde
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 30+ messages in thread
From: Marc Kleine-Budde @ 2020-09-22 14:44 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, michael, qiangqing.zhang, Marc Kleine-Budde

From: Joakim Zhang <qiangqing.zhang@nxp.com>

This patch implements error handling and propagates the error value of
flexcan_chip_stop(). This function will be called from flexcan_suspend()
in an upcoming patch in some SoCs which support LPSR mode.

Add a new function flexcan_chip_stop_disable_on_error() that tries to
disable the chip even in case of errors.

Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 34 ++++++++++++++++++++++++++++------
 1 file changed, 28 insertions(+), 6 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 52d73115c7fd..4be73ce7518e 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -1292,18 +1292,23 @@ static int flexcan_chip_start(struct net_device *dev)
 	return err;
 }
 
-/* flexcan_chip_stop
+/* __flexcan_chip_stop
  *
- * this functions is entered with clocks enabled
+ * this function is entered with clocks enabled
  */
-static void flexcan_chip_stop(struct net_device *dev)
+static int __flexcan_chip_stop(struct net_device *dev, bool disable_on_error)
 {
 	struct flexcan_priv *priv = netdev_priv(dev);
 	struct flexcan_regs __iomem *regs = priv->regs;
+	int err;
 
 	/* freeze + disable module */
-	flexcan_chip_freeze(priv);
-	flexcan_chip_disable(priv);
+	err = flexcan_chip_freeze(priv);
+	if (err && !disable_on_error)
+		return err;
+	err = flexcan_chip_disable(priv);
+	if (err && !disable_on_error)
+		goto out_chip_unfreeze;
 
 	/* Disable all interrupts */
 	priv->write(0, &regs->imask2);
@@ -1313,6 +1318,23 @@ static void flexcan_chip_stop(struct net_device *dev)
 
 	flexcan_transceiver_disable(priv);
 	priv->can.state = CAN_STATE_STOPPED;
+
+	return 0;
+
+ out_chip_unfreeze:
+	flexcan_chip_unfreeze(priv);
+
+	return err;
+}
+
+static inline int flexcan_chip_stop_disable_on_error(struct net_device *dev)
+{
+	return __flexcan_chip_stop(dev, true);
+}
+
+static inline int flexcan_chip_stop(struct net_device *dev)
+{
+	return __flexcan_chip_stop(dev, false);
 }
 
 static int flexcan_open(struct net_device *dev)
@@ -1394,7 +1416,7 @@ static int flexcan_close(struct net_device *dev)
 
 	netif_stop_queue(dev);
 	can_rx_offload_disable(&priv->offload);
-	flexcan_chip_stop(dev);
+	flexcan_chip_stop_disable_on_error(dev);
 
 	can_rx_offload_del(&priv->offload);
 	free_irq(dev->irq, dev);
-- 
2.28.0


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 11/20] can: flexcan: disable clocks during stop mode
  2020-09-22 14:44 [RFC]: flexcan FD support - can-next 2020-09-22 Marc Kleine-Budde
                   ` (9 preceding siblings ...)
  2020-09-22 14:44 ` [PATCH 10/20] can: flexcan: flexcan_chip_stop(): add error handling and propagate error value Marc Kleine-Budde
@ 2020-09-22 14:44 ` Marc Kleine-Budde
  2020-09-22 14:44 ` [PATCH 12/20] can: flexcan: add LPSR mode support Marc Kleine-Budde
                   ` (8 subsequent siblings)
  19 siblings, 0 replies; 30+ messages in thread
From: Marc Kleine-Budde @ 2020-09-22 14:44 UTC (permalink / raw)
  To: linux-can
  Cc: kernel, michael, qiangqing.zhang, Sean Nyekjaer, Marc Kleine-Budde

From: Joakim Zhang <qiangqing.zhang@nxp.com>

Disable clocks while CAN core is in stop mode.

Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
Tested-by: Sean Nyekjaer <sean@geanix.com>
Link: https://lore.kernel.org/r/20191210085721.9853-2-qiangqing.zhang@nxp.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 30 ++++++++++++++++++++----------
 1 file changed, 20 insertions(+), 10 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 4be73ce7518e..ed2ead7c21ef 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -1757,8 +1757,6 @@ static int __maybe_unused flexcan_suspend(struct device *device)
 			err = flexcan_chip_disable(priv);
 			if (err)
 				return err;
-
-			err = pm_runtime_force_suspend(device);
 		}
 		netif_stop_queue(dev);
 		netif_device_detach(dev);
@@ -1784,10 +1782,6 @@ static int __maybe_unused flexcan_resume(struct device *device)
 			if (err)
 				return err;
 		} else {
-			err = pm_runtime_force_resume(device);
-			if (err)
-				return err;
-
 			err = flexcan_chip_enable(priv);
 		}
 	}
@@ -1818,8 +1812,16 @@ static int __maybe_unused flexcan_noirq_suspend(struct device *device)
 	struct net_device *dev = dev_get_drvdata(device);
 	struct flexcan_priv *priv = netdev_priv(dev);
 
-	if (netif_running(dev) && device_may_wakeup(device))
-		flexcan_enable_wakeup_irq(priv, true);
+	if (netif_running(dev)) {
+		int err;
+
+		if (device_may_wakeup(device))
+			flexcan_enable_wakeup_irq(priv, true);
+
+		err = pm_runtime_force_suspend(device);
+		if (err)
+			return err;
+	}
 
 	return 0;
 }
@@ -1829,8 +1831,16 @@ static int __maybe_unused flexcan_noirq_resume(struct device *device)
 	struct net_device *dev = dev_get_drvdata(device);
 	struct flexcan_priv *priv = netdev_priv(dev);
 
-	if (netif_running(dev) && device_may_wakeup(device))
-		flexcan_enable_wakeup_irq(priv, false);
+	if (netif_running(dev)) {
+		int err;
+
+		err = pm_runtime_force_resume(device);
+		if (err)
+			return err;
+
+		if (device_may_wakeup(device))
+			flexcan_enable_wakeup_irq(priv, false);
+	}
 
 	return 0;
 }
-- 
2.28.0


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 12/20] can: flexcan: add LPSR mode support
  2020-09-22 14:44 [RFC]: flexcan FD support - can-next 2020-09-22 Marc Kleine-Budde
                   ` (10 preceding siblings ...)
  2020-09-22 14:44 ` [PATCH 11/20] can: flexcan: disable clocks during stop mode Marc Kleine-Budde
@ 2020-09-22 14:44 ` Marc Kleine-Budde
  2020-09-22 14:44 ` [PATCH 13/20] can: flexcan: flexcan_set_bittiming(): move setup of CAN-2.0 bitiming into separate function Marc Kleine-Budde
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 30+ messages in thread
From: Marc Kleine-Budde @ 2020-09-22 14:44 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, michael, qiangqing.zhang, Marc Kleine-Budde

From: Joakim Zhang <qiangqing.zhang@nxp.com>

On the i.MX7D in LPSR mode, the controller will be powered off and the
configuration state is lost after system resume. Upcoming i.MX8QM/QXP
will also completely power off the domain, the controller state is lost
and needs restore, too. So we need to set the pinctrl state again and
re-start chip to re-configuration after resume.

For the wakeup case, it should not set pinctrl to sleep state by
pinctrl_pm_select_sleep_state.

If the interface is down before suspend, we don't need to re-configure
it as it will be configured if the interface is brought up later.

Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
Link: https://lore.kernel.org/r/20191204113249.3381-7-qiangqing.zhang@nxp.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 23 +++++++++++++++++------
 1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index ed2ead7c21ef..35d0fa59e957 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -23,6 +23,7 @@
 #include <linux/netdevice.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
@@ -1742,7 +1743,7 @@ static int __maybe_unused flexcan_suspend(struct device *device)
 {
 	struct net_device *dev = dev_get_drvdata(device);
 	struct flexcan_priv *priv = netdev_priv(dev);
-	int err = 0;
+	int err;
 
 	if (netif_running(dev)) {
 		/* if wakeup is enabled, enter stop mode
@@ -1754,7 +1755,11 @@ static int __maybe_unused flexcan_suspend(struct device *device)
 			if (err)
 				return err;
 		} else {
-			err = flexcan_chip_disable(priv);
+			err = flexcan_chip_stop(dev);
+			if (err)
+				return err;
+
+			err = pinctrl_pm_select_sleep_state(device);
 			if (err)
 				return err;
 		}
@@ -1763,14 +1768,14 @@ static int __maybe_unused flexcan_suspend(struct device *device)
 	}
 	priv->can.state = CAN_STATE_SLEEPING;
 
-	return err;
+	return 0;
 }
 
 static int __maybe_unused flexcan_resume(struct device *device)
 {
 	struct net_device *dev = dev_get_drvdata(device);
 	struct flexcan_priv *priv = netdev_priv(dev);
-	int err = 0;
+	int err;
 
 	priv->can.state = CAN_STATE_ERROR_ACTIVE;
 	if (netif_running(dev)) {
@@ -1782,11 +1787,17 @@ static int __maybe_unused flexcan_resume(struct device *device)
 			if (err)
 				return err;
 		} else {
-			err = flexcan_chip_enable(priv);
+			err = pinctrl_pm_select_default_state(device);
+			if (err)
+				return err;
+
+			err = flexcan_chip_start(dev);
+			if (err)
+				return err;
 		}
 	}
 
-	return err;
+	return 0;
 }
 
 static int __maybe_unused flexcan_runtime_suspend(struct device *device)
-- 
2.28.0


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 13/20] can: flexcan: flexcan_set_bittiming(): move setup of CAN-2.0 bitiming into separate function
  2020-09-22 14:44 [RFC]: flexcan FD support - can-next 2020-09-22 Marc Kleine-Budde
                   ` (11 preceding siblings ...)
  2020-09-22 14:44 ` [PATCH 12/20] can: flexcan: add LPSR mode support Marc Kleine-Budde
@ 2020-09-22 14:44 ` Marc Kleine-Budde
  2020-09-22 14:44 ` [PATCH 14/20] can: flexcan: use struct canfd_frame for CAN classic frame Marc Kleine-Budde
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 30+ messages in thread
From: Marc Kleine-Budde @ 2020-09-22 14:44 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, michael, qiangqing.zhang, Marc Kleine-Budde

This is a patch prepares for the CAN-FD support. In a later patch the
setup for canfd bittiming will be added, with this patch the change is
easier to read.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 29 +++++++++++++++++++++--------
 1 file changed, 21 insertions(+), 8 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 35d0fa59e957..a9908deae411 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -1037,7 +1037,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
 	return handled;
 }
 
-static void flexcan_set_bittiming(struct net_device *dev)
+static void flexcan_set_bittiming_ctrl(const struct net_device *dev)
 {
 	const struct flexcan_priv *priv = netdev_priv(dev);
 	const struct can_bittiming *bt = &priv->can.bittiming;
@@ -1049,10 +1049,7 @@ static void flexcan_set_bittiming(struct net_device *dev)
 		 FLEXCAN_CTRL_RJW(0x3) |
 		 FLEXCAN_CTRL_PSEG1(0x7) |
 		 FLEXCAN_CTRL_PSEG2(0x7) |
-		 FLEXCAN_CTRL_PROPSEG(0x7) |
-		 FLEXCAN_CTRL_LPB |
-		 FLEXCAN_CTRL_SMP |
-		 FLEXCAN_CTRL_LOM);
+		 FLEXCAN_CTRL_PROPSEG(0x7));
 
 	reg |= FLEXCAN_CTRL_PRESDIV(bt->brp - 1) |
 		FLEXCAN_CTRL_PSEG1(bt->phase_seg1 - 1) |
@@ -1060,6 +1057,24 @@ static void flexcan_set_bittiming(struct net_device *dev)
 		FLEXCAN_CTRL_RJW(bt->sjw - 1) |
 		FLEXCAN_CTRL_PROPSEG(bt->prop_seg - 1);
 
+	netdev_dbg(dev, "writing ctrl=0x%08x\n", reg);
+	priv->write(reg, &regs->ctrl);
+
+	/* print chip status */
+	netdev_dbg(dev, "%s: mcr=0x%08x ctrl=0x%08x\n", __func__,
+		   priv->read(&regs->mcr), priv->read(&regs->ctrl));
+}
+
+static void flexcan_set_bittiming(struct net_device *dev)
+{
+	const struct flexcan_priv *priv = netdev_priv(dev);
+	struct flexcan_regs __iomem *regs = priv->regs;
+	u32 reg;
+
+	reg = priv->read(&regs->ctrl);
+	reg &= ~(FLEXCAN_CTRL_LPB | FLEXCAN_CTRL_SMP |
+		 FLEXCAN_CTRL_LOM);
+
 	if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
 		reg |= FLEXCAN_CTRL_LPB;
 	if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
@@ -1070,9 +1085,7 @@ static void flexcan_set_bittiming(struct net_device *dev)
 	netdev_dbg(dev, "writing ctrl=0x%08x\n", reg);
 	priv->write(reg, &regs->ctrl);
 
-	/* print chip status */
-	netdev_dbg(dev, "%s: mcr=0x%08x ctrl=0x%08x\n", __func__,
-		   priv->read(&regs->mcr), priv->read(&regs->ctrl));
+	return flexcan_set_bittiming_ctrl(dev);
 }
 
 /* flexcan_chip_start
-- 
2.28.0


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 14/20] can: flexcan: use struct canfd_frame for CAN classic frame
  2020-09-22 14:44 [RFC]: flexcan FD support - can-next 2020-09-22 Marc Kleine-Budde
                   ` (12 preceding siblings ...)
  2020-09-22 14:44 ` [PATCH 13/20] can: flexcan: flexcan_set_bittiming(): move setup of CAN-2.0 bitiming into separate function Marc Kleine-Budde
@ 2020-09-22 14:44 ` Marc Kleine-Budde
  2020-09-22 14:44 ` [PATCH 15/20] can: flexcan: add CAN-FD mode support Marc Kleine-Budde
                   ` (5 subsequent siblings)
  19 siblings, 0 replies; 30+ messages in thread
From: Marc Kleine-Budde @ 2020-09-22 14:44 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, michael, qiangqing.zhang, Marc Kleine-Budde

From: Joakim Zhang <qiangqing.zhang@nxp.com>

This patch prepares for CAN FD mode, using struct canfd_frame can both
for classic format frame and fd format frame.

Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
Link: https://lore.kernel.org/r/20190712075926.7357-3-qiangqing.zhang@nxp.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 34 +++++++++++++++++-----------------
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index a9908deae411..20c845c265e1 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -646,10 +646,10 @@ static int flexcan_get_berr_counter(const struct net_device *dev,
 static netdev_tx_t flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	const struct flexcan_priv *priv = netdev_priv(dev);
-	struct can_frame *cf = (struct can_frame *)skb->data;
+	struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
 	u32 can_id;
 	u32 data;
-	u32 ctrl = FLEXCAN_MB_CODE_TX_DATA | (cf->can_dlc << 16);
+	u32 ctrl = FLEXCAN_MB_CODE_TX_DATA | (cfd->len << 16);
 	int i;
 
 	if (can_dropped_invalid_skb(dev, skb))
@@ -657,18 +657,18 @@ static netdev_tx_t flexcan_start_xmit(struct sk_buff *skb, struct net_device *de
 
 	netif_stop_queue(dev);
 
-	if (cf->can_id & CAN_EFF_FLAG) {
-		can_id = cf->can_id & CAN_EFF_MASK;
+	if (cfd->can_id & CAN_EFF_FLAG) {
+		can_id = cfd->can_id & CAN_EFF_MASK;
 		ctrl |= FLEXCAN_MB_CNT_IDE | FLEXCAN_MB_CNT_SRR;
 	} else {
-		can_id = (cf->can_id & CAN_SFF_MASK) << 18;
+		can_id = (cfd->can_id & CAN_SFF_MASK) << 18;
 	}
 
-	if (cf->can_id & CAN_RTR_FLAG)
+	if (cfd->can_id & CAN_RTR_FLAG)
 		ctrl |= FLEXCAN_MB_CNT_RTR;
 
-	for (i = 0; i < cf->can_dlc; i += sizeof(u32)) {
-		data = be32_to_cpup((__be32 *)&cf->data[i]);
+	for (i = 0; i < cfd->len; i += sizeof(u32)) {
+		data = be32_to_cpup((__be32 *)&cfd->data[i]);
 		priv->write(data, &priv->tx_mb->data[i / sizeof(u32)]);
 	}
 
@@ -840,7 +840,7 @@ static struct sk_buff *flexcan_mailbox_read(struct can_rx_offload *offload,
 	struct flexcan_regs __iomem *regs = priv->regs;
 	struct flexcan_mb __iomem *mb;
 	struct sk_buff *skb;
-	struct can_frame *cf;
+	struct canfd_frame *cfd;
 	u32 reg_ctrl, reg_id, reg_iflag1;
 	int i;
 
@@ -877,8 +877,8 @@ static struct sk_buff *flexcan_mailbox_read(struct can_rx_offload *offload,
 		reg_ctrl = priv->read(&mb->can_ctrl);
 	}
 
-	skb = alloc_can_skb(offload->dev, &cf);
-	if (!skb) {
+	skb = alloc_can_skb(offload->dev, (struct can_frame **)&cfd);
+	if (unlikely(!skb)) {
 		skb = ERR_PTR(-ENOMEM);
 		goto mark_as_read;
 	}
@@ -888,17 +888,17 @@ static struct sk_buff *flexcan_mailbox_read(struct can_rx_offload *offload,
 
 	reg_id = priv->read(&mb->can_id);
 	if (reg_ctrl & FLEXCAN_MB_CNT_IDE)
-		cf->can_id = ((reg_id >> 0) & CAN_EFF_MASK) | CAN_EFF_FLAG;
+		cfd->can_id = ((reg_id >> 0) & CAN_EFF_MASK) | CAN_EFF_FLAG;
 	else
-		cf->can_id = (reg_id >> 18) & CAN_SFF_MASK;
+		cfd->can_id = (reg_id >> 18) & CAN_SFF_MASK;
 
 	if (reg_ctrl & FLEXCAN_MB_CNT_RTR)
-		cf->can_id |= CAN_RTR_FLAG;
-	cf->can_dlc = get_can_dlc((reg_ctrl >> 16) & 0xf);
+		cfd->can_id |= CAN_RTR_FLAG;
+	cfd->len = get_can_dlc((reg_ctrl >> 16) & 0xf);
 
-	for (i = 0; i < cf->can_dlc; i += sizeof(u32)) {
+	for (i = 0; i < cfd->len; i += sizeof(u32)) {
 		__be32 data = cpu_to_be32(priv->read(&mb->data[i / sizeof(u32)]));
-		*(__be32 *)(cf->data + i) = data;
+		*(__be32 *)(cfd->data + i) = data;
 	}
 
  mark_as_read:
-- 
2.28.0


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 15/20] can: flexcan: add CAN-FD mode support
  2020-09-22 14:44 [RFC]: flexcan FD support - can-next 2020-09-22 Marc Kleine-Budde
                   ` (13 preceding siblings ...)
  2020-09-22 14:44 ` [PATCH 14/20] can: flexcan: use struct canfd_frame for CAN classic frame Marc Kleine-Budde
@ 2020-09-22 14:44 ` Marc Kleine-Budde
  2020-09-22 14:44 ` [PATCH 16/20] can: flexcan: add ISO CAN FD feature support Marc Kleine-Budde
                   ` (4 subsequent siblings)
  19 siblings, 0 replies; 30+ messages in thread
From: Marc Kleine-Budde @ 2020-09-22 14:44 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, michael, qiangqing.zhang, Marc Kleine-Budde

From: Joakim Zhang <qiangqing.zhang@nxp.com>

This patch adds CAN-FD mode support to the driver, it means that
payload size can extend up to 64 bytes.

Bit timing always set in the CBT register, not in the CTRL1 register any
more. This has an extend range of all CAN bit timing variables (PRESDIV,
PROPSEG, PSEG1, PSEG2 and RJW), which will improve the bit timing
accuracy.

Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
Link: https://lore.kernel.org/r/20190712075926.7357-4-qiangqing.zhang@nxp.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 220 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 212 insertions(+), 8 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 20c845c265e1..8dca553fa545 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -9,6 +9,7 @@
 //
 // Based on code originally by Andrey Volkov <avolkov@varma-el.com>
 
+#include <linux/bitfield.h>
 #include <linux/can.h>
 #include <linux/can/dev.h>
 #include <linux/can/error.h>
@@ -53,6 +54,7 @@
 #define FLEXCAN_MCR_IRMQ		BIT(16)
 #define FLEXCAN_MCR_LPRIO_EN		BIT(13)
 #define FLEXCAN_MCR_AEN			BIT(12)
+#define FLEXCAN_MCR_FDEN		BIT(11)
 /* MCR_MAXMB: maximum used MBs is MAXMB + 1 */
 #define FLEXCAN_MCR_MAXMB(x)		((x) & 0x7f)
 #define FLEXCAN_MCR_IDAM_A		(0x0 << 8)
@@ -137,6 +139,30 @@
 	(FLEXCAN_ESR_TWRN_INT | FLEXCAN_ESR_RWRN_INT | \
 	 FLEXCAN_ESR_BOFF_INT | FLEXCAN_ESR_ERR_INT)
 
+/* FLEXCAN Bit Timing register (CBT) bits */
+#define FLEXCAN_CBT_BTF			BIT(31)
+#define FLEXCAN_CBT_EPRESDIV_MASK	GENMASK(30, 21)
+#define FLEXCAN_CBT_ERJW_MASK		GENMASK(20, 16)
+#define FLEXCAN_CBT_EPROPSEG_MASK	GENMASK(15, 10)
+#define FLEXCAN_CBT_EPSEG1_MASK		GENMASK(9, 5)
+#define FLEXCAN_CBT_EPSEG2_MASK		GENMASK(4, 0)
+
+/* FLEXCAN FD control register (FDCTRL) bits */
+#define FLEXCAN_FDCTRL_FDRATE		BIT(31)
+#define FLEXCAN_FDCTRL_MBDSR1		GENMASK(20, 19)
+#define FLEXCAN_FDCTRL_MBDSR0		GENMASK(17, 16)
+#define FLEXCAN_FDCTRL_MBDSR_8		0x0
+#define FLEXCAN_FDCTRL_MBDSR_12		0x1
+#define FLEXCAN_FDCTRL_MBDSR_32		0x2
+#define FLEXCAN_FDCTRL_MBDSR_64		0x3
+
+/* FLEXCAN FD Bit Timing register (FDCBT) bits */
+#define FLEXCAN_FDCBT_FPRESDIV_MASK	GENMASK(29, 20)
+#define FLEXCAN_FDCBT_FRJW_MASK		GENMASK(18, 16)
+#define FLEXCAN_FDCBT_FPROPSEG_MASK	GENMASK(14, 10)
+#define FLEXCAN_FDCBT_FPSEG1_MASK	GENMASK(7, 5)
+#define FLEXCAN_FDCBT_FPSEG2_MASK	GENMASK(2, 0)
+
 /* FLEXCAN interrupt flag register (IFLAG) bits */
 /* Errata ERR005829 step7: Reserve first valid MB */
 #define FLEXCAN_TX_MB_RESERVED_OFF_FIFO		8
@@ -161,6 +187,9 @@
 #define FLEXCAN_MB_CODE_TX_DATA		(0xc << 24)
 #define FLEXCAN_MB_CODE_TX_TANSWER	(0xe << 24)
 
+#define FLEXCAN_MB_CNT_EDL		BIT(31)
+#define FLEXCAN_MB_CNT_BRS		BIT(30)
+#define FLEXCAN_MB_CNT_ESI		BIT(29)
 #define FLEXCAN_MB_CNT_SRR		BIT(22)
 #define FLEXCAN_MB_CNT_IDE		BIT(21)
 #define FLEXCAN_MB_CNT_RTR		BIT(20)
@@ -201,6 +230,8 @@
 #define FLEXCAN_QUIRK_DEFAULT_BIG_ENDIAN BIT(7)
 /* Setup stop mode to support wakeup */
 #define FLEXCAN_QUIRK_SETUP_STOP_MODE BIT(8)
+/* Support CAN-FD mode */
+#define FLEXCAN_QUIRK_SUPPORT_FD BIT(9)
 
 /* Structure of the message buffer */
 struct flexcan_mb {
@@ -356,6 +387,30 @@ static const struct can_bittiming_const flexcan_bittiming_const = {
 	.brp_inc = 1,
 };
 
+static const struct can_bittiming_const flexcan_fd_bittiming_const = {
+	.name = DRV_NAME,
+	.tseg1_min = 2,
+	.tseg1_max = 96,
+	.tseg2_min = 2,
+	.tseg2_max = 32,
+	.sjw_max = 16,
+	.brp_min = 1,
+	.brp_max = 1024,
+	.brp_inc = 1,
+};
+
+static const struct can_bittiming_const flexcan_fd_data_bittiming_const = {
+	.name = DRV_NAME,
+	.tseg1_min = 2,
+	.tseg1_max = 39,
+	.tseg2_min = 2,
+	.tseg2_max = 8,
+	.sjw_max = 4,
+	.brp_min = 1,
+	.brp_max = 1024,
+	.brp_inc = 1,
+};
+
 /* FlexCAN module is essentially modelled as a little-endian IP in most
  * SoCs, i.e the registers as well as the message buffer areas are
  * implemented in a little-endian fashion.
@@ -649,7 +704,7 @@ static netdev_tx_t flexcan_start_xmit(struct sk_buff *skb, struct net_device *de
 	struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
 	u32 can_id;
 	u32 data;
-	u32 ctrl = FLEXCAN_MB_CODE_TX_DATA | (cfd->len << 16);
+	u32 ctrl = FLEXCAN_MB_CODE_TX_DATA | ((can_len2dlc(cfd->len)) << 16);
 	int i;
 
 	if (can_dropped_invalid_skb(dev, skb))
@@ -667,6 +722,9 @@ static netdev_tx_t flexcan_start_xmit(struct sk_buff *skb, struct net_device *de
 	if (cfd->can_id & CAN_RTR_FLAG)
 		ctrl |= FLEXCAN_MB_CNT_RTR;
 
+	if (can_is_canfd_skb(skb))
+		ctrl |= FLEXCAN_MB_CNT_EDL;
+
 	for (i = 0; i < cfd->len; i += sizeof(u32)) {
 		data = be32_to_cpup((__be32 *)&cfd->data[i]);
 		priv->write(data, &priv->tx_mb->data[i / sizeof(u32)]);
@@ -877,7 +935,10 @@ static struct sk_buff *flexcan_mailbox_read(struct can_rx_offload *offload,
 		reg_ctrl = priv->read(&mb->can_ctrl);
 	}
 
-	skb = alloc_can_skb(offload->dev, (struct can_frame **)&cfd);
+	if (reg_ctrl & FLEXCAN_MB_CNT_EDL)
+		skb = alloc_canfd_skb(offload->dev, &cfd);
+	else
+		skb = alloc_can_skb(offload->dev, (struct can_frame **)&cfd);
 	if (unlikely(!skb)) {
 		skb = ERR_PTR(-ENOMEM);
 		goto mark_as_read;
@@ -892,9 +953,17 @@ static struct sk_buff *flexcan_mailbox_read(struct can_rx_offload *offload,
 	else
 		cfd->can_id = (reg_id >> 18) & CAN_SFF_MASK;
 
-	if (reg_ctrl & FLEXCAN_MB_CNT_RTR)
-		cfd->can_id |= CAN_RTR_FLAG;
-	cfd->len = get_can_dlc((reg_ctrl >> 16) & 0xf);
+	if (reg_ctrl & FLEXCAN_MB_CNT_EDL) {
+		cfd->len = can_dlc2len(get_canfd_dlc((reg_ctrl >> 16) & 0xf));
+	} else {
+		cfd->len = get_can_dlc((reg_ctrl >> 16) & 0xf);
+
+		if (reg_ctrl & FLEXCAN_MB_CNT_RTR)
+			cfd->can_id |= CAN_RTR_FLAG;
+	}
+
+	if (reg_ctrl & FLEXCAN_MB_CNT_ESI)
+		cfd->flags |= CANFD_ESI;
 
 	for (i = 0; i < cfd->len; i += sizeof(u32)) {
 		__be32 data = cpu_to_be32(priv->read(&mb->data[i / sizeof(u32)]));
@@ -1065,6 +1134,83 @@ static void flexcan_set_bittiming_ctrl(const struct net_device *dev)
 		   priv->read(&regs->mcr), priv->read(&regs->ctrl));
 }
 
+static void flexcan_set_bittiming_cbt(const struct net_device *dev)
+{
+	struct flexcan_priv *priv = netdev_priv(dev);
+	struct can_bittiming *bt = &priv->can.bittiming;
+	struct can_bittiming *dbt = &priv->can.data_bittiming;
+	struct flexcan_regs __iomem *regs = priv->regs;
+	u32 reg_cbt, reg_fdctrl;
+
+	/* CBT */
+	/* CBT[EPSEG1] is 5 bit long and CBT[EPROPSEG] is 6 bit
+	 * long. The can_calc_bittiming() tries to divide the tseg1
+	 * equally between phase_seg1 and prop_seg, which may not fit
+	 * in CBT register. Therefore, if phase_seg1 is more than
+	 * possible value, increase prop_seg and decrease phase_seg1.
+	 */
+	if (bt->phase_seg1 > 0x20) {
+		bt->prop_seg += (bt->phase_seg1 - 0x20);
+		bt->phase_seg1 = 0x20;
+	}
+
+	reg_cbt = FLEXCAN_CBT_BTF |
+		FIELD_PREP(FLEXCAN_CBT_EPRESDIV_MASK, bt->brp - 1) |
+		FIELD_PREP(FLEXCAN_CBT_ERJW_MASK, bt->sjw - 1) |
+		FIELD_PREP(FLEXCAN_CBT_EPROPSEG_MASK, bt->prop_seg - 1) |
+		FIELD_PREP(FLEXCAN_CBT_EPSEG1_MASK, bt->phase_seg1 - 1) |
+		FIELD_PREP(FLEXCAN_CBT_EPSEG2_MASK, bt->phase_seg2 - 1);
+
+	netdev_dbg(dev, "writing cbt=0x%08x\n", reg_cbt);
+	priv->write(reg_cbt, &regs->cbt);
+
+	if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
+		u32 reg_fdcbt;
+
+		if (bt->brp != dbt->brp)
+			netdev_warn(dev, "Data brp=%d and brp=%d don't match, this may result in a phase error. Consider using different bitrate and/or data bitrate.\n",
+				    dbt->brp, bt->brp);
+
+		/* FDCBT */
+		/* FDCBT[FPSEG1] is 3 bit long and FDCBT[FPROPSEG] is
+		 * 5 bit long. The can_calc_bittiming tries to divide
+		 * the tseg1 equally between phase_seg1 and prop_seg,
+		 * which may not fit in FDCBT register. Therefore, if
+		 * phase_seg1 is more than possible value, increase
+		 * prop_seg and decrease phase_seg1
+		 */
+		if (dbt->phase_seg1 > 0x8) {
+			dbt->prop_seg += (dbt->phase_seg1 - 0x8);
+			dbt->phase_seg1 = 0x8;
+		}
+
+		reg_fdcbt = FIELD_PREP(FLEXCAN_FDCBT_FPRESDIV_MASK, dbt->brp - 1) |
+			FIELD_PREP(FLEXCAN_FDCBT_FRJW_MASK, dbt->sjw - 1) |
+			FIELD_PREP(FLEXCAN_FDCBT_FPROPSEG_MASK, dbt->prop_seg) |
+			FIELD_PREP(FLEXCAN_FDCBT_FPSEG1_MASK, dbt->phase_seg1 - 1) |
+			FIELD_PREP(FLEXCAN_FDCBT_FPSEG2_MASK, dbt->phase_seg2 - 1);
+
+		netdev_dbg(dev, "writing fdcbt=0x%08x\n", reg_fdcbt);
+		priv->write(reg_fdcbt, &regs->fdcbt);
+	}
+
+	/* FDCTRL */
+	reg_fdctrl = priv->read(&regs->fdctrl);
+	reg_fdctrl &= ~FLEXCAN_FDCTRL_FDRATE;
+
+	if (priv->can.ctrlmode & CAN_CTRLMODE_FD)
+		reg_fdctrl |= FLEXCAN_FDCTRL_FDRATE;
+
+	netdev_dbg(dev, "writing fdctrl=0x%08x\n", reg_fdctrl);
+	priv->write(reg_fdctrl, &regs->fdctrl);
+
+	netdev_dbg(dev, "%s: mcr=0x%08x ctrl=0x%08x fdctrl=0x%08x cbt=0x%08x fdcbt=0x%08x\n",
+		   __func__,
+		   priv->read(&regs->mcr), priv->read(&regs->ctrl),
+		   priv->read(&regs->fdctrl), priv->read(&regs->cbt),
+		   priv->read(&regs->fdcbt));
+}
+
 static void flexcan_set_bittiming(struct net_device *dev)
 {
 	const struct flexcan_priv *priv = netdev_priv(dev);
@@ -1085,7 +1231,10 @@ static void flexcan_set_bittiming(struct net_device *dev)
 	netdev_dbg(dev, "writing ctrl=0x%08x\n", reg);
 	priv->write(reg, &regs->ctrl);
 
-	return flexcan_set_bittiming_ctrl(dev);
+	if (priv->can.ctrlmode_supported & CAN_CTRLMODE_FD)
+		return flexcan_set_bittiming_cbt(dev);
+	else
+		return flexcan_set_bittiming_ctrl(dev);
 }
 
 /* flexcan_chip_start
@@ -1158,6 +1307,12 @@ static int flexcan_chip_start(struct net_device *dev)
 	else
 		reg_mcr |= FLEXCAN_MCR_SRX_DIS;
 
+	/* MCR - CAN-FD */
+	if (priv->can.ctrlmode & CAN_CTRLMODE_FD)
+		reg_mcr |= FLEXCAN_MCR_FDEN;
+	else
+		reg_mcr &= ~FLEXCAN_MCR_FDEN;
+
 	netdev_dbg(dev, "%s: writing mcr=0x%08x", __func__, reg_mcr);
 	priv->write(reg_mcr, &regs->mcr);
 
@@ -1200,6 +1355,32 @@ static int flexcan_chip_start(struct net_device *dev)
 		priv->write(reg_ctrl2, &regs->ctrl2);
 	}
 
+	if (priv->can.ctrlmode_supported & CAN_CTRLMODE_FD) {
+		u32 reg_fdctrl;
+
+		reg_fdctrl = priv->read(&regs->fdctrl);
+		reg_fdctrl &= ~(FIELD_PREP(FLEXCAN_FDCTRL_MBDSR1, 0x3) |
+				FIELD_PREP(FLEXCAN_FDCTRL_MBDSR0, 0x3));
+
+		if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
+			reg_fdctrl |=
+				FIELD_PREP(FLEXCAN_FDCTRL_MBDSR1,
+					   FLEXCAN_FDCTRL_MBDSR_64) |
+				FIELD_PREP(FLEXCAN_FDCTRL_MBDSR0,
+					   FLEXCAN_FDCTRL_MBDSR_64);
+		} else {
+			reg_fdctrl |=
+				FIELD_PREP(FLEXCAN_FDCTRL_MBDSR1,
+					   FLEXCAN_FDCTRL_MBDSR_8) |
+				FIELD_PREP(FLEXCAN_FDCTRL_MBDSR0,
+					   FLEXCAN_FDCTRL_MBDSR_8);
+		}
+
+		netdev_dbg(dev, "%s: writing fdctrl=0x%08x",
+			   __func__, reg_fdctrl);
+		priv->write(reg_fdctrl, &regs->fdctrl);
+	}
+
 	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) {
 		for (i = priv->offload.mb_first; i <= priv->offload.mb_last; i++) {
 			mb = flexcan_get_mb(priv, i);
@@ -1356,6 +1537,12 @@ static int flexcan_open(struct net_device *dev)
 	struct flexcan_priv *priv = netdev_priv(dev);
 	int err;
 
+	if ((priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) &&
+	    (priv->can.ctrlmode & CAN_CTRLMODE_FD)) {
+		netdev_err(dev, "Three Samples mode and CAN-FD mode can't be used together\n");
+		return -EINVAL;
+	}
+
 	err = pm_runtime_get_sync(priv->dev);
 	if (err < 0)
 		return err;
@@ -1368,7 +1555,10 @@ static int flexcan_open(struct net_device *dev)
 	if (err)
 		goto out_close;
 
-	priv->mb_size = sizeof(struct flexcan_mb) + CAN_MAX_DLEN;
+	if (priv->can.ctrlmode & CAN_CTRLMODE_FD)
+		priv->mb_size = sizeof(struct flexcan_mb) + CANFD_MAX_DLEN;
+	else
+		priv->mb_size = sizeof(struct flexcan_mb) + CAN_MAX_DLEN;
 	priv->mb_count = (sizeof(priv->regs->mb[0]) / priv->mb_size) +
 			 (sizeof(priv->regs->mb[1]) / priv->mb_size);
 
@@ -1678,6 +1868,12 @@ static int flexcan_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
+	if ((devtype_data->quirks & FLEXCAN_QUIRK_SUPPORT_FD) &&
+	    !(devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP)) {
+		dev_err(&pdev->dev, "CAN-FD mode doesn't work with FIFO mode!\n");
+		return -EINVAL;
+	}
+
 	dev = alloc_candev(sizeof(struct flexcan_priv), 1);
 	if (!dev)
 		return -ENOMEM;
@@ -1702,7 +1898,6 @@ static int flexcan_probe(struct platform_device *pdev)
 
 	priv->dev = &pdev->dev;
 	priv->can.clock.freq = clock_freq;
-	priv->can.bittiming_const = &flexcan_bittiming_const;
 	priv->can.do_set_mode = flexcan_set_mode;
 	priv->can.do_get_berr_counter = flexcan_get_berr_counter;
 	priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
@@ -1715,6 +1910,15 @@ static int flexcan_probe(struct platform_device *pdev)
 	priv->devtype_data = devtype_data;
 	priv->reg_xceiver = reg_xceiver;
 
+	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_SUPPORT_FD) {
+		priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD;
+		priv->can.bittiming_const = &flexcan_fd_bittiming_const;
+		priv->can.data_bittiming_const =
+			&flexcan_fd_data_bittiming_const;
+	} else {
+		priv->can.bittiming_const = &flexcan_bittiming_const;
+	}
+
 	pm_runtime_get_noresume(&pdev->dev);
 	pm_runtime_set_active(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
-- 
2.28.0


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 16/20] can: flexcan: add ISO CAN FD feature support
  2020-09-22 14:44 [RFC]: flexcan FD support - can-next 2020-09-22 Marc Kleine-Budde
                   ` (14 preceding siblings ...)
  2020-09-22 14:44 ` [PATCH 15/20] can: flexcan: add CAN-FD mode support Marc Kleine-Budde
@ 2020-09-22 14:44 ` Marc Kleine-Budde
  2020-09-22 14:44 ` [PATCH 17/20] can: flexcan: add CAN FD BRS support Marc Kleine-Budde
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 30+ messages in thread
From: Marc Kleine-Budde @ 2020-09-22 14:44 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, michael, qiangqing.zhang, Marc Kleine-Budde

From: Joakim Zhang <qiangqing.zhang@nxp.com>

ISO CAN FD is introduced to increase the failture detection capability
than non-ISO CAN FD. The non-ISO CAN FD is still supported by FlexCAN so
that it can be used mainly during an intermediate phase, for evaluation
and development purposes.

Therefore, it is strongly recommended to configure FlexCAN to the ISO
CAN FD protocol by setting the ISOCANFDEN field in the CTRL2 register.

NOTE: If you only set "fd on", driver will use ISO FD mode by default.
You should set "fd-non-iso on" after setting "fd on" if you want to use
NON ISO FD mode.

Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
Link: https://lore.kernel.org/r/20190712075926.7357-6-qiangqing.zhang@nxp.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 30 ++++++++++++++++++++++++------
 1 file changed, 24 insertions(+), 6 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 8dca553fa545..e3ecce80eadb 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -94,6 +94,7 @@
 #define FLEXCAN_CTRL2_MRP		BIT(18)
 #define FLEXCAN_CTRL2_RRS		BIT(17)
 #define FLEXCAN_CTRL2_EACEN		BIT(16)
+#define FLEXCAN_CTRL2_ISOCANFDEN	BIT(12)
 
 /* FLEXCAN memory error control register (MECR) bits */
 #define FLEXCAN_MECR_ECRWRDIS		BIT(31)
@@ -1165,7 +1166,7 @@ static void flexcan_set_bittiming_cbt(const struct net_device *dev)
 	priv->write(reg_cbt, &regs->cbt);
 
 	if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
-		u32 reg_fdcbt;
+		u32 reg_fdcbt, reg_ctrl2;
 
 		if (bt->brp != dbt->brp)
 			netdev_warn(dev, "Data brp=%d and brp=%d don't match, this may result in a phase error. Consider using different bitrate and/or data bitrate.\n",
@@ -1184,7 +1185,14 @@ static void flexcan_set_bittiming_cbt(const struct net_device *dev)
 			dbt->phase_seg1 = 0x8;
 		}
 
-		reg_fdcbt = FIELD_PREP(FLEXCAN_FDCBT_FPRESDIV_MASK, dbt->brp - 1) |
+		reg_fdcbt = priv->read(&regs->fdcbt);
+		reg_fdcbt &= ~(FIELD_PREP(FLEXCAN_FDCBT_FPRESDIV_MASK, 0x3ff) |
+			       FIELD_PREP(FLEXCAN_FDCBT_FRJW_MASK, 0x7) |
+			       FIELD_PREP(FLEXCAN_FDCBT_FPROPSEG_MASK, 0x1f) |
+			       FIELD_PREP(FLEXCAN_FDCBT_FPSEG1_MASK, 0x7) |
+			       FIELD_PREP(FLEXCAN_FDCBT_FPSEG2_MASK, 0x7));
+
+		reg_fdcbt |= FIELD_PREP(FLEXCAN_FDCBT_FPRESDIV_MASK, dbt->brp - 1) |
 			FIELD_PREP(FLEXCAN_FDCBT_FRJW_MASK, dbt->sjw - 1) |
 			FIELD_PREP(FLEXCAN_FDCBT_FPROPSEG_MASK, dbt->prop_seg) |
 			FIELD_PREP(FLEXCAN_FDCBT_FPSEG1_MASK, dbt->phase_seg1 - 1) |
@@ -1192,6 +1200,15 @@ static void flexcan_set_bittiming_cbt(const struct net_device *dev)
 
 		netdev_dbg(dev, "writing fdcbt=0x%08x\n", reg_fdcbt);
 		priv->write(reg_fdcbt, &regs->fdcbt);
+
+		/* CTRL2 */
+		reg_ctrl2 = priv->read(&regs->ctrl2);
+		reg_ctrl2 &= ~FLEXCAN_CTRL2_ISOCANFDEN;
+		if (!(priv->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO))
+			reg_ctrl2 |= FLEXCAN_CTRL2_ISOCANFDEN;
+
+		netdev_dbg(dev, "writing ctrl2=0x%08x\n", reg_ctrl2);
+		priv->write(reg_ctrl2, &regs->ctrl2);
 	}
 
 	/* FDCTRL */
@@ -1204,11 +1221,11 @@ static void flexcan_set_bittiming_cbt(const struct net_device *dev)
 	netdev_dbg(dev, "writing fdctrl=0x%08x\n", reg_fdctrl);
 	priv->write(reg_fdctrl, &regs->fdctrl);
 
-	netdev_dbg(dev, "%s: mcr=0x%08x ctrl=0x%08x fdctrl=0x%08x cbt=0x%08x fdcbt=0x%08x\n",
+	netdev_dbg(dev, "%s: mcr=0x%08x ctrl=0x%08x ctrl2=0x%08x fdctrl=0x%08x cbt=0x%08x fdcbt=0x%08x\n",
 		   __func__,
 		   priv->read(&regs->mcr), priv->read(&regs->ctrl),
-		   priv->read(&regs->fdctrl), priv->read(&regs->cbt),
-		   priv->read(&regs->fdcbt));
+		   priv->read(&regs->ctrl2), priv->read(&regs->fdctrl),
+		   priv->read(&regs->cbt), priv->read(&regs->fdcbt));
 }
 
 static void flexcan_set_bittiming(struct net_device *dev)
@@ -1911,7 +1928,8 @@ static int flexcan_probe(struct platform_device *pdev)
 	priv->reg_xceiver = reg_xceiver;
 
 	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_SUPPORT_FD) {
-		priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD;
+		priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD |
+			CAN_CTRLMODE_FD_NON_ISO;
 		priv->can.bittiming_const = &flexcan_fd_bittiming_const;
 		priv->can.data_bittiming_const =
 			&flexcan_fd_data_bittiming_const;
-- 
2.28.0


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 17/20] can: flexcan: add CAN FD BRS support
  2020-09-22 14:44 [RFC]: flexcan FD support - can-next 2020-09-22 Marc Kleine-Budde
                   ` (15 preceding siblings ...)
  2020-09-22 14:44 ` [PATCH 16/20] can: flexcan: add ISO CAN FD feature support Marc Kleine-Budde
@ 2020-09-22 14:44 ` Marc Kleine-Budde
  2020-09-22 14:44 ` [PATCH 18/20] can: flexcan: add Transceiver Delay Compensation support Marc Kleine-Budde
                   ` (2 subsequent siblings)
  19 siblings, 0 replies; 30+ messages in thread
From: Marc Kleine-Budde @ 2020-09-22 14:44 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, michael, qiangqing.zhang, Marc Kleine-Budde

From: Joakim Zhang <qiangqing.zhang@nxp.com>

This patch adds CAN FD BitRate Switch (BRS) support to driver.

Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
Link: https://lore.kernel.org/r/20190712075926.7357-5-qiangqing.zhang@nxp.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index e3ecce80eadb..fc0e9d5fd02b 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -723,9 +723,13 @@ static netdev_tx_t flexcan_start_xmit(struct sk_buff *skb, struct net_device *de
 	if (cfd->can_id & CAN_RTR_FLAG)
 		ctrl |= FLEXCAN_MB_CNT_RTR;
 
-	if (can_is_canfd_skb(skb))
+	if (can_is_canfd_skb(skb)) {
 		ctrl |= FLEXCAN_MB_CNT_EDL;
 
+		if (cfd->flags & CANFD_BRS)
+			ctrl |= FLEXCAN_MB_CNT_BRS;
+	}
+
 	for (i = 0; i < cfd->len; i += sizeof(u32)) {
 		data = be32_to_cpup((__be32 *)&cfd->data[i]);
 		priv->write(data, &priv->tx_mb->data[i / sizeof(u32)]);
@@ -956,6 +960,9 @@ static struct sk_buff *flexcan_mailbox_read(struct can_rx_offload *offload,
 
 	if (reg_ctrl & FLEXCAN_MB_CNT_EDL) {
 		cfd->len = can_dlc2len(get_canfd_dlc((reg_ctrl >> 16) & 0xf));
+
+		if (reg_ctrl & FLEXCAN_MB_CNT_BRS)
+			cfd->flags |= CANFD_BRS;
 	} else {
 		cfd->len = get_can_dlc((reg_ctrl >> 16) & 0xf);
 
-- 
2.28.0


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 18/20] can: flexcan: add Transceiver Delay Compensation support
  2020-09-22 14:44 [RFC]: flexcan FD support - can-next 2020-09-22 Marc Kleine-Budde
                   ` (16 preceding siblings ...)
  2020-09-22 14:44 ` [PATCH 17/20] can: flexcan: add CAN FD BRS support Marc Kleine-Budde
@ 2020-09-22 14:44 ` Marc Kleine-Budde
  2020-09-22 14:44 ` [PATCH 19/20] can: flexcan: add imx8qm support Marc Kleine-Budde
  2020-09-22 14:44 ` [PATCH 20/20] can: flexcan: add lx2160ar1 support Marc Kleine-Budde
  19 siblings, 0 replies; 30+ messages in thread
From: Marc Kleine-Budde @ 2020-09-22 14:44 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, michael, qiangqing.zhang, Marc Kleine-Budde

From: Joakim Zhang <qiangqing.zhang@nxp.com>

The CAN-FD protocol allows the transmission and reception of data at a
higher bit rate than the nominal rate used in the arbitration phase when
the message's BRS bit is set.

The TDC mechanism is effective only during the data phase of FD frames
having BRS bit set. It has no effect either on non-FD frames, or on FD
frames transmitted at normal bit rate.

Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
Link: https://lore.kernel.org/r/20190712075926.7357-7-qiangqing.zhang@nxp.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index fc0e9d5fd02b..fc98b5d521f2 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -156,6 +156,10 @@
 #define FLEXCAN_FDCTRL_MBDSR_12		0x1
 #define FLEXCAN_FDCTRL_MBDSR_32		0x2
 #define FLEXCAN_FDCTRL_MBDSR_64		0x3
+#define FLEXCAN_FDCTRL_TDCEN		BIT(15)
+#define FLEXCAN_FDCTRL_TDCFAIL		BIT(14)
+#define FLEXCAN_FDCTRL_TDCOFF		GENMASK(12, 8)
+#define FLEXCAN_FDCTRL_TDCVAL		GENMASK(5, 0)
 
 /* FLEXCAN FD Bit Timing register (FDCBT) bits */
 #define FLEXCAN_FDCBT_FPRESDIV_MASK	GENMASK(29, 20)
@@ -1220,11 +1224,24 @@ static void flexcan_set_bittiming_cbt(const struct net_device *dev)
 
 	/* FDCTRL */
 	reg_fdctrl = priv->read(&regs->fdctrl);
-	reg_fdctrl &= ~FLEXCAN_FDCTRL_FDRATE;
+	reg_fdctrl &= ~(FLEXCAN_FDCTRL_FDRATE |
+			FIELD_PREP(FLEXCAN_FDCTRL_TDCOFF, 0x1f));
 
-	if (priv->can.ctrlmode & CAN_CTRLMODE_FD)
+	if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
 		reg_fdctrl |= FLEXCAN_FDCTRL_FDRATE;
 
+		if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
+			/* TDC must be disabled for Loop Back mode */
+			reg_fdctrl &= ~FLEXCAN_FDCTRL_TDCEN;
+		} else {
+			reg_fdctrl |= FLEXCAN_FDCTRL_TDCEN |
+				FIELD_PREP(FLEXCAN_FDCTRL_TDCOFF,
+					   ((dbt->phase_seg1 - 1) +
+					    dbt->prop_seg + 2) *
+					   ((dbt->brp - 1 ) + 1));
+		}
+	}
+
 	netdev_dbg(dev, "writing fdctrl=0x%08x\n", reg_fdctrl);
 	priv->write(reg_fdctrl, &regs->fdctrl);
 
-- 
2.28.0


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 19/20] can: flexcan: add imx8qm support
  2020-09-22 14:44 [RFC]: flexcan FD support - can-next 2020-09-22 Marc Kleine-Budde
                   ` (17 preceding siblings ...)
  2020-09-22 14:44 ` [PATCH 18/20] can: flexcan: add Transceiver Delay Compensation support Marc Kleine-Budde
@ 2020-09-22 14:44 ` Marc Kleine-Budde
  2020-09-22 14:44 ` [PATCH 20/20] can: flexcan: add lx2160ar1 support Marc Kleine-Budde
  19 siblings, 0 replies; 30+ messages in thread
From: Marc Kleine-Budde @ 2020-09-22 14:44 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, michael, qiangqing.zhang, Marc Kleine-Budde

From: Joakim Zhang <qiangqing.zhang@nxp.com>

The Flexcan on i.MX8QM supports CAN FD protocol.

Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
Link: https://lore.kernel.org/r/20190712075926.7357-8-qiangqing.zhang@nxp.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index fc98b5d521f2..5f778c961a0c 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -206,15 +206,16 @@
 /* FLEXCAN hardware feature flags
  *
  * Below is some version info we got:
- *    SOC   Version   IP-Version  Glitch- [TR]WRN_INT IRQ Err Memory err RTR re-
- *                                Filter? connected?  Passive detection  ception in MB
- *   MX25  FlexCAN2  03.00.00.00     no        no        no       no        no
- *   MX28  FlexCAN2  03.00.04.00    yes       yes        no       no        no
- *   MX35  FlexCAN2  03.00.00.00     no        no        no       no        no
- *   MX53  FlexCAN2  03.00.00.00    yes        no        no       no        no
- *   MX6s  FlexCAN3  10.00.12.00    yes       yes        no       no       yes
- *   VF610 FlexCAN3  ?               no       yes        no      yes       yes?
- * LS1021A FlexCAN2  03.00.04.00     no       yes        no       no       yes
+ *    SOC   Version   IP-Version  Glitch- [TR]WRN_INT IRQ Err Memory err RTR rece-   FD Mode
+ *                                Filter? connected?  Passive detection  ption in MB Supported?
+ *   MX25  FlexCAN2  03.00.00.00     no        no        no       no        no           no
+ *   MX28  FlexCAN2  03.00.04.00    yes       yes        no       no        no           no
+ *   MX35  FlexCAN2  03.00.00.00     no        no        no       no        no           no
+ *   MX53  FlexCAN2  03.00.00.00    yes        no        no       no        no           no
+ *   MX6s  FlexCAN3  10.00.12.00    yes       yes        no       no       yes           no
+ *   MX8QM FlexCAN3  03.00.23.00    yes       yes        no       no       yes          yes
+ *   VF610 FlexCAN3  ?               no       yes        no      yes       yes?          no
+ * LS1021A FlexCAN2  03.00.04.00     no       yes        no       no       yes           no
  *
  * Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected.
  */
@@ -368,6 +369,12 @@ static const struct flexcan_devtype_data fsl_imx6q_devtype_data = {
 		FLEXCAN_QUIRK_SETUP_STOP_MODE,
 };
 
+static const struct flexcan_devtype_data fsl_imx8qm_devtype_data = {
+	.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
+		FLEXCAN_QUIRK_USE_OFF_TIMESTAMP | FLEXCAN_QUIRK_BROKEN_PERR_STATE |
+		FLEXCAN_QUIRK_SUPPORT_FD,
+};
+
 static const struct flexcan_devtype_data fsl_vf610_devtype_data = {
 	.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
 		FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_USE_OFF_TIMESTAMP |
@@ -1830,6 +1837,7 @@ static int flexcan_setup_stop_mode(struct platform_device *pdev)
 }
 
 static const struct of_device_id flexcan_of_match[] = {
+	{ .compatible = "fsl,imx8qm-flexcan", .data = &fsl_imx8qm_devtype_data, },
 	{ .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, },
 	{ .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, },
 	{ .compatible = "fsl,imx53-flexcan", .data = &fsl_imx25_devtype_data, },
-- 
2.28.0


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 20/20] can: flexcan: add lx2160ar1 support
  2020-09-22 14:44 [RFC]: flexcan FD support - can-next 2020-09-22 Marc Kleine-Budde
                   ` (18 preceding siblings ...)
  2020-09-22 14:44 ` [PATCH 19/20] can: flexcan: add imx8qm support Marc Kleine-Budde
@ 2020-09-22 14:44 ` Marc Kleine-Budde
  2020-09-23  7:45   ` Michael Walle
  19 siblings, 1 reply; 30+ messages in thread
From: Marc Kleine-Budde @ 2020-09-22 14:44 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, michael, qiangqing.zhang, Marc Kleine-Budde

From: Joakim Zhang <qiangqing.zhang@nxp.com>

The Flexcan on lx2160ar1 supports CAN FD protocol.

Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
Link: https://lore.kernel.org/r/20190712075926.7357-9-qiangqing.zhang@nxp.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 5f778c961a0c..e86925134009 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -216,6 +216,7 @@
  *   MX8QM FlexCAN3  03.00.23.00    yes       yes        no       no       yes          yes
  *   VF610 FlexCAN3  ?               no       yes        no      yes       yes?          no
  * LS1021A FlexCAN2  03.00.04.00     no       yes        no       no       yes           no
+ * LX2160A FlexCAN3  03.00.23.00     no       yes        no       no       yes          yes
  *
  * Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected.
  */
@@ -387,6 +388,12 @@ static const struct flexcan_devtype_data fsl_ls1021a_r2_devtype_data = {
 		FLEXCAN_QUIRK_USE_OFF_TIMESTAMP,
 };
 
+static const struct flexcan_devtype_data fsl_lx2160a_r1_devtype_data = {
+	.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
+		FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_BROKEN_PERR_STATE |
+		FLEXCAN_QUIRK_USE_OFF_TIMESTAMP | FLEXCAN_QUIRK_SUPPORT_FD,
+};
+
 static const struct can_bittiming_const flexcan_bittiming_const = {
 	.name = DRV_NAME,
 	.tseg1_min = 4,
@@ -1846,6 +1853,7 @@ static const struct of_device_id flexcan_of_match[] = {
 	{ .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, },
 	{ .compatible = "fsl,vf610-flexcan", .data = &fsl_vf610_devtype_data, },
 	{ .compatible = "fsl,ls1021ar2-flexcan", .data = &fsl_ls1021a_r2_devtype_data, },
+	{ .compatible = "fsl,lx2160ar1-flexcan", .data = &fsl_lx2160a_r1_devtype_data, },
 	{ /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, flexcan_of_match);
-- 
2.28.0


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 20/20] can: flexcan: add lx2160ar1 support
  2020-09-22 14:44 ` [PATCH 20/20] can: flexcan: add lx2160ar1 support Marc Kleine-Budde
@ 2020-09-23  7:45   ` Michael Walle
  2020-09-23  7:54     ` Marc Kleine-Budde
  0 siblings, 1 reply; 30+ messages in thread
From: Michael Walle @ 2020-09-23  7:45 UTC (permalink / raw)
  To: Marc Kleine-Budde; +Cc: linux-can, kernel, qiangqing.zhang

Hi Joakim, Hi Marc,

Am 2020-09-22 16:44, schrieb Marc Kleine-Budde:
> From: Joakim Zhang <qiangqing.zhang@nxp.com>
> 
> The Flexcan on lx2160ar1 supports CAN FD protocol.
> 
> Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
> Link: 
> https://lore.kernel.org/r/20190712075926.7357-9-qiangqing.zhang@nxp.com
> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
> ---
>  drivers/net/can/flexcan.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
> index 5f778c961a0c..e86925134009 100644
> --- a/drivers/net/can/flexcan.c
> +++ b/drivers/net/can/flexcan.c
> @@ -216,6 +216,7 @@
>   *   MX8QM FlexCAN3  03.00.23.00    yes       yes        no       no
>      yes          yes
>   *   VF610 FlexCAN3  ?               no       yes        no      yes
>      yes?          no
>   * LS1021A FlexCAN2  03.00.04.00     no       yes        no       no
>      yes           no
> + * LX2160A FlexCAN3  03.00.23.00     no       yes        no       no
>      yes          yes

I'd really like to see LS1028A support. At the moment, I'm having the
following additional patch for the ls1028a device tree.

can0: can@2180000 {
     compatible = "fsl,ls1028ar1-flexcan", "fsl,lx2160ar1-flexcan";
     reg = <0x0 0x2180000 0x0 0x10000>;
     interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
                   clocks = <&sysclk>, <&clockgen 4 1>;
                   clock-names = "ipg", "per";
                   status = "disabled";
};

Do we need to add a dedicated compatible entry for the LS1028A
the driver?

-michael

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 20/20] can: flexcan: add lx2160ar1 support
  2020-09-23  7:45   ` Michael Walle
@ 2020-09-23  7:54     ` Marc Kleine-Budde
  2020-09-23  8:02       ` Michael Walle
  0 siblings, 1 reply; 30+ messages in thread
From: Marc Kleine-Budde @ 2020-09-23  7:54 UTC (permalink / raw)
  To: Michael Walle; +Cc: qiangqing.zhang, kernel, linux-can


[-- Attachment #1.1: Type: text/plain, Size: 3379 bytes --]

On 9/23/20 9:45 AM, Michael Walle wrote:
> Hi Joakim, Hi Marc,
> 
> Am 2020-09-22 16:44, schrieb Marc Kleine-Budde:
>> From: Joakim Zhang <qiangqing.zhang@nxp.com>
>>
>> The Flexcan on lx2160ar1 supports CAN FD protocol.
>>
>> Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
>> Link: 
>> https://lore.kernel.org/r/20190712075926.7357-9-qiangqing.zhang@nxp.com
>> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
>> ---
>>  drivers/net/can/flexcan.c | 8 ++++++++
>>  1 file changed, 8 insertions(+)
>>
>> diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
>> index 5f778c961a0c..e86925134009 100644
>> --- a/drivers/net/can/flexcan.c
>> +++ b/drivers/net/can/flexcan.c
>> @@ -216,6 +216,7 @@
>>   *   MX8QM FlexCAN3  03.00.23.00    yes       yes        no       no
>>      yes          yes
>>   *   VF610 FlexCAN3  ?               no       yes        no      yes
>>      yes?          no
>>   * LS1021A FlexCAN2  03.00.04.00     no       yes        no       no
>>      yes           no
>> + * LX2160A FlexCAN3  03.00.23.00     no       yes        no       no
>>      yes          yes
> 
> I'd really like to see LS1028A support. At the moment, I'm having the
> following additional patch for the ls1028a device tree.
> 
> can0: can@2180000 {
>      compatible = "fsl,ls1028ar1-flexcan", "fsl,lx2160ar1-flexcan";
                                              ^^^^^^^^^^^^^^^^^^^^^
>      reg = <0x0 0x2180000 0x0 0x10000>;
>      interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
>                    clocks = <&sysclk>, <&clockgen 4 1>;
>                    clock-names = "ipg", "per";
>                    status = "disabled";
> };
> 
> Do we need to add a dedicated compatible entry for the LS1028A
> the driver?

At the end of the series, there are the following compatibles:

> static const struct of_device_id flexcan_of_match[] = {
> 	{ .compatible = "fsl,imx8qm-flexcan", .data = &fsl_imx8qm_devtype_data, },
> 	{ .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, },
> 	{ .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, },
> 	{ .compatible = "fsl,imx53-flexcan", .data = &fsl_imx25_devtype_data, },
> 	{ .compatible = "fsl,imx35-flexcan", .data = &fsl_imx25_devtype_data, },
> 	{ .compatible = "fsl,imx25-flexcan", .data = &fsl_imx25_devtype_data, },
> 	{ .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, },
> 	{ .compatible = "fsl,vf610-flexcan", .data = &fsl_vf610_devtype_data, },
> 	{ .compatible = "fsl,ls1021ar2-flexcan", .data = &fsl_ls1021a_r2_devtype_data, },
> 	{ .compatible = "fsl,lx2160ar1-flexcan", .data = &fsl_lx2160a_r1_devtype_data, },
                         ^^^^^^^^^^^^^^^^^^^^^
> 	{ /* sentinel */ },
> };

The compatible of your can device matches the one listed in
the driver. So there's no need for the "fsl,ls1028ar1-flexcan"
in the driver.

If it turns out, that the "fsl,ls1028ar1-flexcan" needs
different handling than the "fsl,lx2160ar1-flexcan", we would
add it with different quirks to the driver.

regards,
Marc

-- 
Pengutronix e.K.                 | Marc Kleine-Budde           |
Embedded Linux                   | https://www.pengutronix.de  |
Vertretung West/Dortmund         | Phone: +49-231-2826-924     |
Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-5555 |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 20/20] can: flexcan: add lx2160ar1 support
  2020-09-23  7:54     ` Marc Kleine-Budde
@ 2020-09-23  8:02       ` Michael Walle
  2020-09-23  8:10         ` Marc Kleine-Budde
  0 siblings, 1 reply; 30+ messages in thread
From: Michael Walle @ 2020-09-23  8:02 UTC (permalink / raw)
  To: Marc Kleine-Budde; +Cc: qiangqing.zhang, kernel, linux-can

Am 2020-09-23 09:54, schrieb Marc Kleine-Budde:
> On 9/23/20 9:45 AM, Michael Walle wrote:
>> Hi Joakim, Hi Marc,
>> 
>> Am 2020-09-22 16:44, schrieb Marc Kleine-Budde:
>>> From: Joakim Zhang <qiangqing.zhang@nxp.com>
>>> 
>>> The Flexcan on lx2160ar1 supports CAN FD protocol.
>>> 
>>> Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
>>> Link:
>>> https://lore.kernel.org/r/20190712075926.7357-9-qiangqing.zhang@nxp.com
>>> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
>>> ---
>>>  drivers/net/can/flexcan.c | 8 ++++++++
>>>  1 file changed, 8 insertions(+)
>>> 
>>> diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
>>> index 5f778c961a0c..e86925134009 100644
>>> --- a/drivers/net/can/flexcan.c
>>> +++ b/drivers/net/can/flexcan.c
>>> @@ -216,6 +216,7 @@
>>>   *   MX8QM FlexCAN3  03.00.23.00    yes       yes        no       no
>>>      yes          yes
>>>   *   VF610 FlexCAN3  ?               no       yes        no      yes
>>>      yes?          no
>>>   * LS1021A FlexCAN2  03.00.04.00     no       yes        no       no
>>>      yes           no
>>> + * LX2160A FlexCAN3  03.00.23.00     no       yes        no       no
>>>      yes          yes
>> 
>> I'd really like to see LS1028A support. At the moment, I'm having the
>> following additional patch for the ls1028a device tree.
>> 
>> can0: can@2180000 {
>>      compatible = "fsl,ls1028ar1-flexcan", "fsl,lx2160ar1-flexcan";
>                                               ^^^^^^^^^^^^^^^^^^^^^
>>      reg = <0x0 0x2180000 0x0 0x10000>;
>>      interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
>>                    clocks = <&sysclk>, <&clockgen 4 1>;
>>                    clock-names = "ipg", "per";
>>                    status = "disabled";
>> };
>> 
>> Do we need to add a dedicated compatible entry for the LS1028A
>> the driver?
> 
> At the end of the series, there are the following compatibles:
> 
>> static const struct of_device_id flexcan_of_match[] = {
>> 	{ .compatible = "fsl,imx8qm-flexcan", .data = 
>> &fsl_imx8qm_devtype_data, },
>> 	{ .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, 
>> },
>> 	{ .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, 
>> },
>> 	{ .compatible = "fsl,imx53-flexcan", .data = &fsl_imx25_devtype_data, 
>> },
>> 	{ .compatible = "fsl,imx35-flexcan", .data = &fsl_imx25_devtype_data, 
>> },
>> 	{ .compatible = "fsl,imx25-flexcan", .data = &fsl_imx25_devtype_data, 
>> },
>> 	{ .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, 
>> },
>> 	{ .compatible = "fsl,vf610-flexcan", .data = &fsl_vf610_devtype_data, 
>> },
>> 	{ .compatible = "fsl,ls1021ar2-flexcan", .data = 
>> &fsl_ls1021a_r2_devtype_data, },
>> 	{ .compatible = "fsl,lx2160ar1-flexcan", .data = 
>> &fsl_lx2160a_r1_devtype_data, },
>                          ^^^^^^^^^^^^^^^^^^^^^
>> 	{ /* sentinel */ },
>> };
> 
> The compatible of your can device matches the one listed in
> the driver. So there's no need for the "fsl,ls1028ar1-flexcan"
> in the driver.
> 
> If it turns out, that the "fsl,ls1028ar1-flexcan" needs
> different handling than the "fsl,lx2160ar1-flexcan", we would
> add it with different quirks to the driver.

That was what I was asking. Ie. if Joakim already knows any and
if it makes sense to have some added right now.

And maybe you/he want to see the LS1028A added to the table in
the header of the file. I've had a look at the vendor manual but
couldn't even find the IP version. Seems to me that only Joakim
is able to fill out that row ;)

-michael

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 20/20] can: flexcan: add lx2160ar1 support
  2020-09-23  8:02       ` Michael Walle
@ 2020-09-23  8:10         ` Marc Kleine-Budde
  2020-09-23  8:31           ` Joakim Zhang
  0 siblings, 1 reply; 30+ messages in thread
From: Marc Kleine-Budde @ 2020-09-23  8:10 UTC (permalink / raw)
  To: Michael Walle; +Cc: qiangqing.zhang, kernel, linux-can


[-- Attachment #1.1: Type: text/plain, Size: 1276 bytes --]

On 9/23/20 10:02 AM, Michael Walle wrote:
[...]

>> The compatible of your can device matches the one listed in
>> the driver. So there's no need for the "fsl,ls1028ar1-flexcan"
>> in the driver.
>>
>> If it turns out, that the "fsl,ls1028ar1-flexcan" needs
>> different handling than the "fsl,lx2160ar1-flexcan", we would
>> add it with different quirks to the driver.
> 
> That was what I was asking. Ie. if Joakim already knows any and
> if it makes sense to have some added right now.

ACK, I don't know of any difference.

> And maybe you/he want to see the LS1028A added to the table in
> the header of the file. I've had a look at the vendor manual but
> couldn't even find the IP version. Seems to me that only Joakim
> is able to fill out that row ;)

Right, the more IP cores in the table are appreciated. I don't think the IP core
version used in the SoCs is available to the public. Joakim, feel free to add a
line for the ls1028ar1 and the imx8mp.

regards,
Marc

-- 
Pengutronix e.K.                 | Marc Kleine-Budde           |
Embedded Linux                   | https://www.pengutronix.de  |
Vertretung West/Dortmund         | Phone: +49-231-2826-924     |
Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-5555 |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread

* RE: [PATCH 20/20] can: flexcan: add lx2160ar1 support
  2020-09-23  8:10         ` Marc Kleine-Budde
@ 2020-09-23  8:31           ` Joakim Zhang
  2020-09-23  8:58             ` Marc Kleine-Budde
  0 siblings, 1 reply; 30+ messages in thread
From: Joakim Zhang @ 2020-09-23  8:31 UTC (permalink / raw)
  To: Marc Kleine-Budde, Michael Walle; +Cc: kernel, linux-can


> -----Original Message-----
> From: Marc Kleine-Budde <mkl@pengutronix.de>
> Sent: 2020年9月23日 16:11
> To: Michael Walle <michael@walle.cc>
> Cc: Joakim Zhang <qiangqing.zhang@nxp.com>; kernel@pengutronix.de;
> linux-can@vger.kernel.org
> Subject: Re: [PATCH 20/20] can: flexcan: add lx2160ar1 support
> 
> On 9/23/20 10:02 AM, Michael Walle wrote:
> [...]
> 
> >> The compatible of your can device matches the one listed in the
> >> driver. So there's no need for the "fsl,ls1028ar1-flexcan"
> >> in the driver.
> >>
> >> If it turns out, that the "fsl,ls1028ar1-flexcan" needs different
> >> handling than the "fsl,lx2160ar1-flexcan", we would add it with
> >> different quirks to the driver.
> >
> > That was what I was asking. Ie. if Joakim already knows any and if it
> > makes sense to have some added right now.
> 
> ACK, I don't know of any difference.
> 
> > And maybe you/he want to see the LS1028A added to the table in the
> > header of the file. I've had a look at the vendor manual but couldn't
> > even find the IP version. Seems to me that only Joakim is able to fill
> > out that row ;)
> 
> Right, the more IP cores in the table are appreciated. I don't think the IP core
> version used in the SoCs is available to the public. Joakim, feel free to add a line
> for the ls1028ar1 and the imx8mp.

Hi Marc, Michael,

I check locally, for LS1028A, it also uses the "fsl,lx2160ar1-flexcan" compatible string, so I think LS1028A should reuse IP core from LX2160A.

I am more familiar to i.MX, I will add a compatible string for i.MX8MP, since it configures ECC, extra patches are needed.
After this patch set is merged into mainline, I will send out related patches to community.

Best Regards,
Joakim Zhang
> regards,
> Marc
> 
> --
> Pengutronix e.K.                 | Marc Kleine-Budde           |
> Embedded Linux                   | https://www.pengutronix.de  |
> Vertretung West/Dortmund         | Phone: +49-231-2826-924     |
> Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-5555 |


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 20/20] can: flexcan: add lx2160ar1 support
  2020-09-23  8:31           ` Joakim Zhang
@ 2020-09-23  8:58             ` Marc Kleine-Budde
  2020-09-23  9:38               ` Michael Walle
  2020-09-23  9:50               ` Joakim Zhang
  0 siblings, 2 replies; 30+ messages in thread
From: Marc Kleine-Budde @ 2020-09-23  8:58 UTC (permalink / raw)
  To: Joakim Zhang, Michael Walle; +Cc: kernel, linux-can


[-- Attachment #1.1: Type: text/plain, Size: 950 bytes --]

On 9/23/20 10:31 AM, Joakim Zhang wrote:
> I check locally, for LS1028A, it also uses the "fsl,lx2160ar1-flexcan"
> compatible string, so I think LS1028A should reuse IP core from LX2160A.

This means at least the IP core is compatible :) I think we don't know for sure,
if it's the same version of the IP core.

> I am more familiar to i.MX, I will add a compatible string for i.MX8MP, since
> it configures ECC, extra patches are needed.

Ok

> After this patch set is merged into mainline, I will send out related patches
> to community.

I just send out a pull request, so feel free to base your patches on the tag
linux-can-next-for-5.10-20200923

Marc

-- 
Pengutronix e.K.                 | Marc Kleine-Budde           |
Embedded Linux                   | https://www.pengutronix.de  |
Vertretung West/Dortmund         | Phone: +49-231-2826-924     |
Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-5555 |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 20/20] can: flexcan: add lx2160ar1 support
  2020-09-23  8:58             ` Marc Kleine-Budde
@ 2020-09-23  9:38               ` Michael Walle
  2020-09-23  9:50               ` Joakim Zhang
  1 sibling, 0 replies; 30+ messages in thread
From: Michael Walle @ 2020-09-23  9:38 UTC (permalink / raw)
  To: Marc Kleine-Budde; +Cc: Joakim Zhang, kernel, linux-can

Am 2020-09-23 10:58, schrieb Marc Kleine-Budde:
> On 9/23/20 10:31 AM, Joakim Zhang wrote:
>> I check locally, for LS1028A, it also uses the "fsl,lx2160ar1-flexcan"
>> compatible string, so I think LS1028A should reuse IP core from 
>> LX2160A.
> 
> This means at least the IP core is compatible :) I think we don't know 
> for sure,
> if it's the same version of the IP core.

Ok I've just tested this series on the LS1028A and can confirm it 
(still) works.

FWIW, because the pull request is already out:
Tested-by: Michael Walle <michael@walle.cc> [on LS1028A SoC]

-michael

^ permalink raw reply	[flat|nested] 30+ messages in thread

* RE: [PATCH 20/20] can: flexcan: add lx2160ar1 support
  2020-09-23  8:58             ` Marc Kleine-Budde
  2020-09-23  9:38               ` Michael Walle
@ 2020-09-23  9:50               ` Joakim Zhang
  1 sibling, 0 replies; 30+ messages in thread
From: Joakim Zhang @ 2020-09-23  9:50 UTC (permalink / raw)
  To: Marc Kleine-Budde, Michael Walle; +Cc: kernel, linux-can


> -----Original Message-----
> From: Marc Kleine-Budde <mkl@pengutronix.de>
> Sent: 2020年9月23日 16:58
> To: Joakim Zhang <qiangqing.zhang@nxp.com>; Michael Walle
> <michael@walle.cc>
> Cc: kernel@pengutronix.de; linux-can@vger.kernel.org
> Subject: Re: [PATCH 20/20] can: flexcan: add lx2160ar1 support
> 
> On 9/23/20 10:31 AM, Joakim Zhang wrote:
> > I check locally, for LS1028A, it also uses the "fsl,lx2160ar1-flexcan"
> > compatible string, so I think LS1028A should reuse IP core from LX2160A.
> 
> This means at least the IP core is compatible :) I think we don't know for sure, if
> it's the same version of the IP core.
> 
> > I am more familiar to i.MX, I will add a compatible string for
> > i.MX8MP, since it configures ECC, extra patches are needed.
> 
> Ok
> 
> > After this patch set is merged into mainline, I will send out related
> > patches to community.
> 
> I just send out a pull request, so feel free to base your patches on the tag
> linux-can-next-for-5.10-20200923

OK, thanks, I will send out soon.

Best Regards,
Joakim Zhang
> Marc
> 
> --
> Pengutronix e.K.                 | Marc Kleine-Budde           |
> Embedded Linux                   | https://www.pengutronix.de  |
> Vertretung West/Dortmund         | Phone: +49-231-2826-924     |
> Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-5555 |


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 15/20] can: flexcan: add CAN-FD mode support
  2020-09-23  8:53 pull-request: can-next 2020-09-23 Marc Kleine-Budde
@ 2020-09-23  8:54 ` Marc Kleine-Budde
  0 siblings, 0 replies; 30+ messages in thread
From: Marc Kleine-Budde @ 2020-09-23  8:54 UTC (permalink / raw)
  To: netdev
  Cc: davem, linux-can, kernel, michael, qiangqing.zhang, Marc Kleine-Budde

From: Joakim Zhang <qiangqing.zhang@nxp.com>

This patch adds CAN-FD mode support to the driver, it means that
payload size can extend up to 64 bytes.

Bit timing always set in the CBT register, not in the CTRL1 register any
more. This has an extend range of all CAN bit timing variables (PRESDIV,
PROPSEG, PSEG1, PSEG2 and RJW), which will improve the bit timing
accuracy.

Signed-off-by: Joakim Zhang <qiangqing.zhang@nxp.com>
[mkl: move cbt-based bitrate support into separate function]
Link: https://lore.kernel.org/r/20200922144429.2613631-16-mkl@pengutronix.de
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/flexcan.c | 220 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 212 insertions(+), 8 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 20c845c265e1..8dca553fa545 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -9,6 +9,7 @@
 //
 // Based on code originally by Andrey Volkov <avolkov@varma-el.com>
 
+#include <linux/bitfield.h>
 #include <linux/can.h>
 #include <linux/can/dev.h>
 #include <linux/can/error.h>
@@ -53,6 +54,7 @@
 #define FLEXCAN_MCR_IRMQ		BIT(16)
 #define FLEXCAN_MCR_LPRIO_EN		BIT(13)
 #define FLEXCAN_MCR_AEN			BIT(12)
+#define FLEXCAN_MCR_FDEN		BIT(11)
 /* MCR_MAXMB: maximum used MBs is MAXMB + 1 */
 #define FLEXCAN_MCR_MAXMB(x)		((x) & 0x7f)
 #define FLEXCAN_MCR_IDAM_A		(0x0 << 8)
@@ -137,6 +139,30 @@
 	(FLEXCAN_ESR_TWRN_INT | FLEXCAN_ESR_RWRN_INT | \
 	 FLEXCAN_ESR_BOFF_INT | FLEXCAN_ESR_ERR_INT)
 
+/* FLEXCAN Bit Timing register (CBT) bits */
+#define FLEXCAN_CBT_BTF			BIT(31)
+#define FLEXCAN_CBT_EPRESDIV_MASK	GENMASK(30, 21)
+#define FLEXCAN_CBT_ERJW_MASK		GENMASK(20, 16)
+#define FLEXCAN_CBT_EPROPSEG_MASK	GENMASK(15, 10)
+#define FLEXCAN_CBT_EPSEG1_MASK		GENMASK(9, 5)
+#define FLEXCAN_CBT_EPSEG2_MASK		GENMASK(4, 0)
+
+/* FLEXCAN FD control register (FDCTRL) bits */
+#define FLEXCAN_FDCTRL_FDRATE		BIT(31)
+#define FLEXCAN_FDCTRL_MBDSR1		GENMASK(20, 19)
+#define FLEXCAN_FDCTRL_MBDSR0		GENMASK(17, 16)
+#define FLEXCAN_FDCTRL_MBDSR_8		0x0
+#define FLEXCAN_FDCTRL_MBDSR_12		0x1
+#define FLEXCAN_FDCTRL_MBDSR_32		0x2
+#define FLEXCAN_FDCTRL_MBDSR_64		0x3
+
+/* FLEXCAN FD Bit Timing register (FDCBT) bits */
+#define FLEXCAN_FDCBT_FPRESDIV_MASK	GENMASK(29, 20)
+#define FLEXCAN_FDCBT_FRJW_MASK		GENMASK(18, 16)
+#define FLEXCAN_FDCBT_FPROPSEG_MASK	GENMASK(14, 10)
+#define FLEXCAN_FDCBT_FPSEG1_MASK	GENMASK(7, 5)
+#define FLEXCAN_FDCBT_FPSEG2_MASK	GENMASK(2, 0)
+
 /* FLEXCAN interrupt flag register (IFLAG) bits */
 /* Errata ERR005829 step7: Reserve first valid MB */
 #define FLEXCAN_TX_MB_RESERVED_OFF_FIFO		8
@@ -161,6 +187,9 @@
 #define FLEXCAN_MB_CODE_TX_DATA		(0xc << 24)
 #define FLEXCAN_MB_CODE_TX_TANSWER	(0xe << 24)
 
+#define FLEXCAN_MB_CNT_EDL		BIT(31)
+#define FLEXCAN_MB_CNT_BRS		BIT(30)
+#define FLEXCAN_MB_CNT_ESI		BIT(29)
 #define FLEXCAN_MB_CNT_SRR		BIT(22)
 #define FLEXCAN_MB_CNT_IDE		BIT(21)
 #define FLEXCAN_MB_CNT_RTR		BIT(20)
@@ -201,6 +230,8 @@
 #define FLEXCAN_QUIRK_DEFAULT_BIG_ENDIAN BIT(7)
 /* Setup stop mode to support wakeup */
 #define FLEXCAN_QUIRK_SETUP_STOP_MODE BIT(8)
+/* Support CAN-FD mode */
+#define FLEXCAN_QUIRK_SUPPORT_FD BIT(9)
 
 /* Structure of the message buffer */
 struct flexcan_mb {
@@ -356,6 +387,30 @@ static const struct can_bittiming_const flexcan_bittiming_const = {
 	.brp_inc = 1,
 };
 
+static const struct can_bittiming_const flexcan_fd_bittiming_const = {
+	.name = DRV_NAME,
+	.tseg1_min = 2,
+	.tseg1_max = 96,
+	.tseg2_min = 2,
+	.tseg2_max = 32,
+	.sjw_max = 16,
+	.brp_min = 1,
+	.brp_max = 1024,
+	.brp_inc = 1,
+};
+
+static const struct can_bittiming_const flexcan_fd_data_bittiming_const = {
+	.name = DRV_NAME,
+	.tseg1_min = 2,
+	.tseg1_max = 39,
+	.tseg2_min = 2,
+	.tseg2_max = 8,
+	.sjw_max = 4,
+	.brp_min = 1,
+	.brp_max = 1024,
+	.brp_inc = 1,
+};
+
 /* FlexCAN module is essentially modelled as a little-endian IP in most
  * SoCs, i.e the registers as well as the message buffer areas are
  * implemented in a little-endian fashion.
@@ -649,7 +704,7 @@ static netdev_tx_t flexcan_start_xmit(struct sk_buff *skb, struct net_device *de
 	struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
 	u32 can_id;
 	u32 data;
-	u32 ctrl = FLEXCAN_MB_CODE_TX_DATA | (cfd->len << 16);
+	u32 ctrl = FLEXCAN_MB_CODE_TX_DATA | ((can_len2dlc(cfd->len)) << 16);
 	int i;
 
 	if (can_dropped_invalid_skb(dev, skb))
@@ -667,6 +722,9 @@ static netdev_tx_t flexcan_start_xmit(struct sk_buff *skb, struct net_device *de
 	if (cfd->can_id & CAN_RTR_FLAG)
 		ctrl |= FLEXCAN_MB_CNT_RTR;
 
+	if (can_is_canfd_skb(skb))
+		ctrl |= FLEXCAN_MB_CNT_EDL;
+
 	for (i = 0; i < cfd->len; i += sizeof(u32)) {
 		data = be32_to_cpup((__be32 *)&cfd->data[i]);
 		priv->write(data, &priv->tx_mb->data[i / sizeof(u32)]);
@@ -877,7 +935,10 @@ static struct sk_buff *flexcan_mailbox_read(struct can_rx_offload *offload,
 		reg_ctrl = priv->read(&mb->can_ctrl);
 	}
 
-	skb = alloc_can_skb(offload->dev, (struct can_frame **)&cfd);
+	if (reg_ctrl & FLEXCAN_MB_CNT_EDL)
+		skb = alloc_canfd_skb(offload->dev, &cfd);
+	else
+		skb = alloc_can_skb(offload->dev, (struct can_frame **)&cfd);
 	if (unlikely(!skb)) {
 		skb = ERR_PTR(-ENOMEM);
 		goto mark_as_read;
@@ -892,9 +953,17 @@ static struct sk_buff *flexcan_mailbox_read(struct can_rx_offload *offload,
 	else
 		cfd->can_id = (reg_id >> 18) & CAN_SFF_MASK;
 
-	if (reg_ctrl & FLEXCAN_MB_CNT_RTR)
-		cfd->can_id |= CAN_RTR_FLAG;
-	cfd->len = get_can_dlc((reg_ctrl >> 16) & 0xf);
+	if (reg_ctrl & FLEXCAN_MB_CNT_EDL) {
+		cfd->len = can_dlc2len(get_canfd_dlc((reg_ctrl >> 16) & 0xf));
+	} else {
+		cfd->len = get_can_dlc((reg_ctrl >> 16) & 0xf);
+
+		if (reg_ctrl & FLEXCAN_MB_CNT_RTR)
+			cfd->can_id |= CAN_RTR_FLAG;
+	}
+
+	if (reg_ctrl & FLEXCAN_MB_CNT_ESI)
+		cfd->flags |= CANFD_ESI;
 
 	for (i = 0; i < cfd->len; i += sizeof(u32)) {
 		__be32 data = cpu_to_be32(priv->read(&mb->data[i / sizeof(u32)]));
@@ -1065,6 +1134,83 @@ static void flexcan_set_bittiming_ctrl(const struct net_device *dev)
 		   priv->read(&regs->mcr), priv->read(&regs->ctrl));
 }
 
+static void flexcan_set_bittiming_cbt(const struct net_device *dev)
+{
+	struct flexcan_priv *priv = netdev_priv(dev);
+	struct can_bittiming *bt = &priv->can.bittiming;
+	struct can_bittiming *dbt = &priv->can.data_bittiming;
+	struct flexcan_regs __iomem *regs = priv->regs;
+	u32 reg_cbt, reg_fdctrl;
+
+	/* CBT */
+	/* CBT[EPSEG1] is 5 bit long and CBT[EPROPSEG] is 6 bit
+	 * long. The can_calc_bittiming() tries to divide the tseg1
+	 * equally between phase_seg1 and prop_seg, which may not fit
+	 * in CBT register. Therefore, if phase_seg1 is more than
+	 * possible value, increase prop_seg and decrease phase_seg1.
+	 */
+	if (bt->phase_seg1 > 0x20) {
+		bt->prop_seg += (bt->phase_seg1 - 0x20);
+		bt->phase_seg1 = 0x20;
+	}
+
+	reg_cbt = FLEXCAN_CBT_BTF |
+		FIELD_PREP(FLEXCAN_CBT_EPRESDIV_MASK, bt->brp - 1) |
+		FIELD_PREP(FLEXCAN_CBT_ERJW_MASK, bt->sjw - 1) |
+		FIELD_PREP(FLEXCAN_CBT_EPROPSEG_MASK, bt->prop_seg - 1) |
+		FIELD_PREP(FLEXCAN_CBT_EPSEG1_MASK, bt->phase_seg1 - 1) |
+		FIELD_PREP(FLEXCAN_CBT_EPSEG2_MASK, bt->phase_seg2 - 1);
+
+	netdev_dbg(dev, "writing cbt=0x%08x\n", reg_cbt);
+	priv->write(reg_cbt, &regs->cbt);
+
+	if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
+		u32 reg_fdcbt;
+
+		if (bt->brp != dbt->brp)
+			netdev_warn(dev, "Data brp=%d and brp=%d don't match, this may result in a phase error. Consider using different bitrate and/or data bitrate.\n",
+				    dbt->brp, bt->brp);
+
+		/* FDCBT */
+		/* FDCBT[FPSEG1] is 3 bit long and FDCBT[FPROPSEG] is
+		 * 5 bit long. The can_calc_bittiming tries to divide
+		 * the tseg1 equally between phase_seg1 and prop_seg,
+		 * which may not fit in FDCBT register. Therefore, if
+		 * phase_seg1 is more than possible value, increase
+		 * prop_seg and decrease phase_seg1
+		 */
+		if (dbt->phase_seg1 > 0x8) {
+			dbt->prop_seg += (dbt->phase_seg1 - 0x8);
+			dbt->phase_seg1 = 0x8;
+		}
+
+		reg_fdcbt = FIELD_PREP(FLEXCAN_FDCBT_FPRESDIV_MASK, dbt->brp - 1) |
+			FIELD_PREP(FLEXCAN_FDCBT_FRJW_MASK, dbt->sjw - 1) |
+			FIELD_PREP(FLEXCAN_FDCBT_FPROPSEG_MASK, dbt->prop_seg) |
+			FIELD_PREP(FLEXCAN_FDCBT_FPSEG1_MASK, dbt->phase_seg1 - 1) |
+			FIELD_PREP(FLEXCAN_FDCBT_FPSEG2_MASK, dbt->phase_seg2 - 1);
+
+		netdev_dbg(dev, "writing fdcbt=0x%08x\n", reg_fdcbt);
+		priv->write(reg_fdcbt, &regs->fdcbt);
+	}
+
+	/* FDCTRL */
+	reg_fdctrl = priv->read(&regs->fdctrl);
+	reg_fdctrl &= ~FLEXCAN_FDCTRL_FDRATE;
+
+	if (priv->can.ctrlmode & CAN_CTRLMODE_FD)
+		reg_fdctrl |= FLEXCAN_FDCTRL_FDRATE;
+
+	netdev_dbg(dev, "writing fdctrl=0x%08x\n", reg_fdctrl);
+	priv->write(reg_fdctrl, &regs->fdctrl);
+
+	netdev_dbg(dev, "%s: mcr=0x%08x ctrl=0x%08x fdctrl=0x%08x cbt=0x%08x fdcbt=0x%08x\n",
+		   __func__,
+		   priv->read(&regs->mcr), priv->read(&regs->ctrl),
+		   priv->read(&regs->fdctrl), priv->read(&regs->cbt),
+		   priv->read(&regs->fdcbt));
+}
+
 static void flexcan_set_bittiming(struct net_device *dev)
 {
 	const struct flexcan_priv *priv = netdev_priv(dev);
@@ -1085,7 +1231,10 @@ static void flexcan_set_bittiming(struct net_device *dev)
 	netdev_dbg(dev, "writing ctrl=0x%08x\n", reg);
 	priv->write(reg, &regs->ctrl);
 
-	return flexcan_set_bittiming_ctrl(dev);
+	if (priv->can.ctrlmode_supported & CAN_CTRLMODE_FD)
+		return flexcan_set_bittiming_cbt(dev);
+	else
+		return flexcan_set_bittiming_ctrl(dev);
 }
 
 /* flexcan_chip_start
@@ -1158,6 +1307,12 @@ static int flexcan_chip_start(struct net_device *dev)
 	else
 		reg_mcr |= FLEXCAN_MCR_SRX_DIS;
 
+	/* MCR - CAN-FD */
+	if (priv->can.ctrlmode & CAN_CTRLMODE_FD)
+		reg_mcr |= FLEXCAN_MCR_FDEN;
+	else
+		reg_mcr &= ~FLEXCAN_MCR_FDEN;
+
 	netdev_dbg(dev, "%s: writing mcr=0x%08x", __func__, reg_mcr);
 	priv->write(reg_mcr, &regs->mcr);
 
@@ -1200,6 +1355,32 @@ static int flexcan_chip_start(struct net_device *dev)
 		priv->write(reg_ctrl2, &regs->ctrl2);
 	}
 
+	if (priv->can.ctrlmode_supported & CAN_CTRLMODE_FD) {
+		u32 reg_fdctrl;
+
+		reg_fdctrl = priv->read(&regs->fdctrl);
+		reg_fdctrl &= ~(FIELD_PREP(FLEXCAN_FDCTRL_MBDSR1, 0x3) |
+				FIELD_PREP(FLEXCAN_FDCTRL_MBDSR0, 0x3));
+
+		if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
+			reg_fdctrl |=
+				FIELD_PREP(FLEXCAN_FDCTRL_MBDSR1,
+					   FLEXCAN_FDCTRL_MBDSR_64) |
+				FIELD_PREP(FLEXCAN_FDCTRL_MBDSR0,
+					   FLEXCAN_FDCTRL_MBDSR_64);
+		} else {
+			reg_fdctrl |=
+				FIELD_PREP(FLEXCAN_FDCTRL_MBDSR1,
+					   FLEXCAN_FDCTRL_MBDSR_8) |
+				FIELD_PREP(FLEXCAN_FDCTRL_MBDSR0,
+					   FLEXCAN_FDCTRL_MBDSR_8);
+		}
+
+		netdev_dbg(dev, "%s: writing fdctrl=0x%08x",
+			   __func__, reg_fdctrl);
+		priv->write(reg_fdctrl, &regs->fdctrl);
+	}
+
 	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) {
 		for (i = priv->offload.mb_first; i <= priv->offload.mb_last; i++) {
 			mb = flexcan_get_mb(priv, i);
@@ -1356,6 +1537,12 @@ static int flexcan_open(struct net_device *dev)
 	struct flexcan_priv *priv = netdev_priv(dev);
 	int err;
 
+	if ((priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) &&
+	    (priv->can.ctrlmode & CAN_CTRLMODE_FD)) {
+		netdev_err(dev, "Three Samples mode and CAN-FD mode can't be used together\n");
+		return -EINVAL;
+	}
+
 	err = pm_runtime_get_sync(priv->dev);
 	if (err < 0)
 		return err;
@@ -1368,7 +1555,10 @@ static int flexcan_open(struct net_device *dev)
 	if (err)
 		goto out_close;
 
-	priv->mb_size = sizeof(struct flexcan_mb) + CAN_MAX_DLEN;
+	if (priv->can.ctrlmode & CAN_CTRLMODE_FD)
+		priv->mb_size = sizeof(struct flexcan_mb) + CANFD_MAX_DLEN;
+	else
+		priv->mb_size = sizeof(struct flexcan_mb) + CAN_MAX_DLEN;
 	priv->mb_count = (sizeof(priv->regs->mb[0]) / priv->mb_size) +
 			 (sizeof(priv->regs->mb[1]) / priv->mb_size);
 
@@ -1678,6 +1868,12 @@ static int flexcan_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
+	if ((devtype_data->quirks & FLEXCAN_QUIRK_SUPPORT_FD) &&
+	    !(devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP)) {
+		dev_err(&pdev->dev, "CAN-FD mode doesn't work with FIFO mode!\n");
+		return -EINVAL;
+	}
+
 	dev = alloc_candev(sizeof(struct flexcan_priv), 1);
 	if (!dev)
 		return -ENOMEM;
@@ -1702,7 +1898,6 @@ static int flexcan_probe(struct platform_device *pdev)
 
 	priv->dev = &pdev->dev;
 	priv->can.clock.freq = clock_freq;
-	priv->can.bittiming_const = &flexcan_bittiming_const;
 	priv->can.do_set_mode = flexcan_set_mode;
 	priv->can.do_get_berr_counter = flexcan_get_berr_counter;
 	priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
@@ -1715,6 +1910,15 @@ static int flexcan_probe(struct platform_device *pdev)
 	priv->devtype_data = devtype_data;
 	priv->reg_xceiver = reg_xceiver;
 
+	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_SUPPORT_FD) {
+		priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD;
+		priv->can.bittiming_const = &flexcan_fd_bittiming_const;
+		priv->can.data_bittiming_const =
+			&flexcan_fd_data_bittiming_const;
+	} else {
+		priv->can.bittiming_const = &flexcan_bittiming_const;
+	}
+
 	pm_runtime_get_noresume(&pdev->dev);
 	pm_runtime_set_active(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
-- 
2.28.0


^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2020-09-23  9:50 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-22 14:44 [RFC]: flexcan FD support - can-next 2020-09-22 Marc Kleine-Budde
2020-09-22 14:44 ` [PATCH 01/20] can: flexcan: sort include files alphabetically Marc Kleine-Budde
2020-09-22 14:44 ` [PATCH 02/20] can: flexcan: flexcan_exit_stop_mode(): remove stray empty line Marc Kleine-Budde
2020-09-22 14:44 ` [PATCH 03/20] can: flexcan: more register names Marc Kleine-Budde
2020-09-22 14:44 ` [PATCH 04/20] can: flexcan: struct flexcan_regs: document registers not affected by soft reset Marc Kleine-Budde
2020-09-22 14:44 ` [PATCH 05/20] can: flexcan: quirks: get rid of long lines Marc Kleine-Budde
2020-09-22 14:44 ` [PATCH 06/20] can: flexcan: Ack wakeup interrupt separately Marc Kleine-Budde
2020-09-22 14:44 ` [PATCH 07/20] can: flexcan: flexcan_probe(): make regulator xceiver optional Marc Kleine-Budde
2020-09-22 14:44 ` [PATCH 08/20] can: flexcan: Add check for transceiver maximum bitrate limitation Marc Kleine-Budde
2020-09-22 14:44 ` [PATCH 09/20] can: flexcan: add correctable errors correction when HW supports ECC Marc Kleine-Budde
2020-09-22 14:44 ` [PATCH 10/20] can: flexcan: flexcan_chip_stop(): add error handling and propagate error value Marc Kleine-Budde
2020-09-22 14:44 ` [PATCH 11/20] can: flexcan: disable clocks during stop mode Marc Kleine-Budde
2020-09-22 14:44 ` [PATCH 12/20] can: flexcan: add LPSR mode support Marc Kleine-Budde
2020-09-22 14:44 ` [PATCH 13/20] can: flexcan: flexcan_set_bittiming(): move setup of CAN-2.0 bitiming into separate function Marc Kleine-Budde
2020-09-22 14:44 ` [PATCH 14/20] can: flexcan: use struct canfd_frame for CAN classic frame Marc Kleine-Budde
2020-09-22 14:44 ` [PATCH 15/20] can: flexcan: add CAN-FD mode support Marc Kleine-Budde
2020-09-22 14:44 ` [PATCH 16/20] can: flexcan: add ISO CAN FD feature support Marc Kleine-Budde
2020-09-22 14:44 ` [PATCH 17/20] can: flexcan: add CAN FD BRS support Marc Kleine-Budde
2020-09-22 14:44 ` [PATCH 18/20] can: flexcan: add Transceiver Delay Compensation support Marc Kleine-Budde
2020-09-22 14:44 ` [PATCH 19/20] can: flexcan: add imx8qm support Marc Kleine-Budde
2020-09-22 14:44 ` [PATCH 20/20] can: flexcan: add lx2160ar1 support Marc Kleine-Budde
2020-09-23  7:45   ` Michael Walle
2020-09-23  7:54     ` Marc Kleine-Budde
2020-09-23  8:02       ` Michael Walle
2020-09-23  8:10         ` Marc Kleine-Budde
2020-09-23  8:31           ` Joakim Zhang
2020-09-23  8:58             ` Marc Kleine-Budde
2020-09-23  9:38               ` Michael Walle
2020-09-23  9:50               ` Joakim Zhang
2020-09-23  8:53 pull-request: can-next 2020-09-23 Marc Kleine-Budde
2020-09-23  8:54 ` [PATCH 15/20] can: flexcan: add CAN-FD mode support Marc Kleine-Budde

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.