From 2aea13a107090d05e968d7d2aa3f72380a3f1b4c Mon Sep 17 00:00:00 2001 From: Joakim Zhang Date: Fri, 12 Jul 2019 08:02:44 +0000 Subject: [PATCH] can: flexcan: add CAN FD mode support This patch intends to add CAN FD mode support in driver, it means that payload size can extend up to 64 bytes. Bit timing always set in CBT register other than CTRL1 register when CANFD supports BRS, it will extend the 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 Signed-off-by: Marc Kleine-Budde --- drivers/net/can/flexcan.c | 247 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 218 insertions(+), 29 deletions(-) --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -52,6 +52,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 +138,26 @@ FLEXCAN_ESR_BOFF_INT | FLEXCAN_ESR_ERR_INT | \ FLEXCAN_ESR_WAK_INT) +/* FLEXCAN Bit Timing register (CBT) bits */ +#define FLEXCAN_CBT_BTF BIT(31) +#define FLEXCAN_CBT_EPRESDIV(x) (((x) & 0x3ff) << 21) +#define FLEXCAN_CBT_ERJW(x) (((x) & 0x0f) << 16) +#define FLEXCAN_CBT_EPROPSEG(x) (((x) & 0x3f) << 10) +#define FLEXCAN_CBT_EPSEG1(x) (((x) & 0x1f) << 5) +#define FLEXCAN_CBT_EPSEG2(x) ((x) & 0x1f) + +/* FLEXCAN FD control register (FDCTRL) bits */ +#define FLEXCAN_FDCTRL_FDRATE BIT(31) +#define FLEXCAN_FDCTRL_MBDSR1(x) (((x) & 0x3) << 19) +#define FLEXCAN_FDCTRL_MBDSR0(x) (((x) & 0x3) << 16) + +/* FLEXCAN FD Bit Timing register (FDCBT) bits */ +#define FLEXCAN_FDCBT_FPRESDIV(x) (((x) & 0x3ff) << 20) +#define FLEXCAN_FDCBT_FRJW(x) (((x) & 0x07) << 16) +#define FLEXCAN_FDCBT_FPROPSEG(x) (((x) & 0x1f) << 10) +#define FLEXCAN_FDCBT_FPSEG1(x) (((x) & 0x07) << 5) +#define FLEXCAN_FDCBT_FPSEG2(x) ((x) & 0x07) + /* FLEXCAN interrupt flag register (IFLAG) bits */ /* Errata ERR005829 step7: Reserve first valid MB */ #define FLEXCAN_TX_MB_RESERVED_OFF_FIFO 8 @@ -161,6 +182,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) @@ -192,6 +216,7 @@ #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 */ +#define FLEXCAN_QUIRK_TIMESTAMP_SUPPORT_FD BIT(9) /* Use timestamp then support can fd mode */ /* Structure of the message buffer */ struct flexcan_mb { @@ -225,7 +250,8 @@ struct flexcan_regs { u32 crcr; /* 0x44 */ u32 rxfgmask; /* 0x48 */ u32 rxfir; /* 0x4c */ - u32 _reserved3[12]; /* 0x50 */ + u32 cbt; /* 0x50 */ + u32 _reserved3[11]; /* 0x54 */ u8 mb[2][512]; /* 0x80 */ /* FIFO-mode: * MB @@ -250,6 +276,10 @@ 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 */ }; struct flexcan_devtype_data { @@ -337,6 +367,30 @@ static const struct can_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. @@ -631,7 +685,7 @@ static netdev_tx_t flexcan_start_xmit(st 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)) @@ -649,6 +703,9 @@ static netdev_tx_t flexcan_start_xmit(st 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)]); @@ -859,7 +916,10 @@ static struct sk_buff *flexcan_mailbox_r 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; @@ -874,9 +934,17 @@ static struct sk_buff *flexcan_mailbox_r 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)])); @@ -1021,27 +1089,14 @@ static irqreturn_t flexcan_irq(int irq, static void flexcan_set_bittiming(struct net_device *dev) { - const struct flexcan_priv *priv = netdev_priv(dev); - const struct can_bittiming *bt = &priv->can.bittiming; + 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; + u32 reg, reg_cbt, reg_fdcbt; reg = priv->read(®s->ctrl); - reg &= ~(FLEXCAN_CTRL_PRESDIV(0xff) | - 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); - - reg |= FLEXCAN_CTRL_PRESDIV(bt->brp - 1) | - FLEXCAN_CTRL_PSEG1(bt->phase_seg1 - 1) | - FLEXCAN_CTRL_PSEG2(bt->phase_seg2 - 1) | - FLEXCAN_CTRL_RJW(bt->sjw - 1) | - FLEXCAN_CTRL_PROPSEG(bt->prop_seg - 1); - + 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) @@ -1052,9 +1107,102 @@ static void flexcan_set_bittiming(struct netdev_dbg(dev, "writing ctrl=0x%08x\n", reg); priv->write(reg, ®s->ctrl); - /* print chip status */ - netdev_dbg(dev, "%s: mcr=0x%08x ctrl=0x%08x\n", __func__, - priv->read(®s->mcr), priv->read(®s->ctrl)); + if (priv->can.ctrlmode_supported & CAN_CTRLMODE_FD) { + reg_cbt = priv->read(®s->cbt); + reg_cbt &= ~(FLEXCAN_CBT_EPRESDIV(0x3ff) | + FLEXCAN_CBT_EPSEG1(0x1f) | + FLEXCAN_CBT_EPSEG2(0x1f) | + FLEXCAN_CBT_ERJW(0x1f) | + FLEXCAN_CBT_EPROPSEG(0x3f) | + FLEXCAN_CBT_BTF); + + /* 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_EPRESDIV(bt->brp - 1) | + FLEXCAN_CBT_EPSEG1(bt->phase_seg1 - 1) | + FLEXCAN_CBT_EPSEG2(bt->phase_seg2 - 1) | + FLEXCAN_CBT_ERJW(bt->sjw - 1) | + FLEXCAN_CBT_EPROPSEG(bt->prop_seg - 1) | + FLEXCAN_CBT_BTF; + priv->write(reg_cbt, ®s->cbt); + + netdev_dbg(dev, "bt: prediv %d seg1 %d seg2 %d rjw %d propseg %d\n", + bt->brp - 1, bt->phase_seg1 - 1, bt->phase_seg2 - 1, + bt->sjw - 1, bt->prop_seg - 1); + + if (priv->can.ctrlmode & CAN_CTRLMODE_FD) { + reg_fdcbt = priv->read(®s->fdcbt); + reg_fdcbt &= ~(FLEXCAN_FDCBT_FPRESDIV(0x3ff) | + FLEXCAN_FDCBT_FPSEG1(0x07) | + FLEXCAN_FDCBT_FPSEG2(0x07) | + FLEXCAN_FDCBT_FRJW(0x07) | + FLEXCAN_FDCBT_FPROPSEG(0x1f)); + + /* 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_
From 29d1bb6fc97d4391e4ecf96298b6ac42d0daefca Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 20 Jun 2013 18:44:43 +0200
Subject: [PATCH 33/79] DT: MIPS: ralink: clean up RT3050 dtsi and dts file

* remove nodes for cores whose drivers are not upstream yet
* add compat string for an additional soc
* fix a whitespace error

Signed-off-by: John Crispin <blogic@openwrt.org>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
Patchwork: http://patchwork.linux-mips.org/patch/5186/
---
 arch/mips/ralink/dts/rt3050.dtsi     |   52 ++--------------------------------
 arch/mips/ralink/dts/rt3052_eval.dts |   10 ++-----
 2 files changed, 4 insertions(+), 58 deletions(-)

diff --git a/arch/mips/ralink/dts/rt3050.dtsi b/arch/mips/ralink/dts/rt3050.dtsi
index 069d066..ef7da1e 100644
--- a/arch/mips/ralink/dts/rt3050.dtsi
+++ b/arch/mips/ralink/dts/rt3050.dtsi
@@ -1,7 +1,7 @@
 / {
 	#address-cells = <1>;
 	#size-cells = <1>;
-	compatible = "ralink,rt3050-soc", "ralink,rt3052-soc";
+	compatible = "ralink,rt3050-soc", "ralink,rt3052-soc", "ralink,rt3350-soc";
 
 	cpus {
 		cpu@0 {
@@ -9,10 +9,6 @@
 		};
 	};
 
-	chosen {
-		bootargs = "console=ttyS0,57600 init=/init";
-	};
-
 	cpuintc: cpuintc@0 {
 		#address-cells = <0>;
 		#interrupt-cells = <1>;
@@ -23,7 +19,7 @@
 	palmbus@10000000 {
 		compatible = "palmbus";
 		reg = <0x10000000 0x200000>;
-                ranges = <0x0 0x10000000 0x1FFFFF>;
+		ranges = <0x0 0x10000000 0x1FFFFF>;
 
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -33,11 +29,6 @@
 			reg = <0x0 0x100>;
 		};
 
-		timer@100 {
-			compatible = "ralink,rt3052-wdt", "ralink,rt2880-wdt";
-			reg = <0x100 0x100>;
-		};
-
 		intc: intc@200 {
 			compatible = "ralink,rt3052-intc", "ralink,rt2880-intc";
 			reg = <0x200 0x100>;
@@ -54,45 +45,6 @@
 			reg = <0x300 0x100>;
 		};
 
-		gpio0: gpio@600 {
-			compatible = "ralink,rt3052-gpio", "ralink,rt2880-gpio";
-			reg = <0x600 0x34>;
-
-			gpio-controller;
-			#gpio-cells = <2>;
-
-			ralink,ngpio = <24>;
-			ralink,regs = [ 00 04 08 0c
-					20 24 28 2c
-					30 34 ];
-		};
-
-		gpio1: gpio@638 {
-			compatible = "ralink,rt3052-gpio", "ralink,rt2880-gpio";
-			reg = <0x638 0x24>;
-
-			gpio-controller;
-			#gpio-cells = <2>;
-
-			ralink,ngpio = <16>;
-			ralink,regs = [ 00 04 08 0c
-					10 14 18 1c
-					20 24 ];
-		};
-
-		gpio2: gpio@660 {
-			compatible = "ralink,rt3052-gpio", "ralink,rt2880-gpio";
-			reg = <0x660 0x24>;
-
-			gpio-controller;
-			#gpio-cells = <2>;
-
-			ralink,ngpio = <12>;
-			ralink,regs = [ 00 04 08 0c
-					10 14 18 1c
-					20 24 ];
-		};
-
 		uartlite@c00 {
 			compatible = "ralink,rt3052-uart", "ralink,rt2880-uart", "ns16550a";
 			reg = <0xc00 0x100>;
diff --git a/arch/mips/ralink/dts/rt3052_eval.dts b/arch/mips/ralink/dts/rt3052_eval.dts
index dc56e58..df17f5f 100644
--- a/arch/mips/ralink/dts/rt3052_eval.dts
+++ b/arch/mips/ralink/dts/rt3052_eval.dts
@@ -3,8 +3,6 @@
 /include/ "rt3050.dtsi"
 
 / {
-	#address-cells = <1>;
-	#size-cells = <1>;
 	compatible = "ralink,rt3052-eval-board", "ralink,rt3052-soc";
 	model = "Ralink RT3052 evaluation board";
 
@@ -12,12 +10,8 @@
 		reg = <0x0 0x2000000>;
 	};
 
-	palmbus@10000000 {
-		sysc@0 {
-			ralink,pinmux = "uartlite", "spi";
-			ralink,uartmux = "gpio";
-			ralink,wdtmux = <0>;
-		};
+	chosen {
+		bootargs = "console=ttyS0,57600";
 	};
 
 	cfi@1f000000 {
-- 
1.7.10.4