From 99312c377f82f91e7754aefe42f64b619b295fd6 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 3 Mar 2016 20:45:55 +0100 Subject: [PATCH 1/5] can: ifi: Fix clock generator configuration The clock generation does not match reality when using the CAN IP core outside of the FPGA design. This patch fixes the computation of values which are programmed into the clock generator registers. First, there are some off-by-one errors which manifest themselves only when communicating with different controller, so those are fixed. Second, the bits in the clock generator registers have different meaning depending on whether the core is in ISO CANFD mode or any of the other modes (BOSCH CANFD or CAN2.0). Detect the ISO CANFD mode and fix handling of this special case of clock configuration. Finally, the CAN clock speed is in CANCLOCK register, not SYSCLOCK register, so fix this as well. Signed-off-by: Marek Vasut Cc: Marc Kleine-Budde Cc: Mark Rutland Cc: Oliver Hartkopp Cc: Wolfgang Grandegger Reviewed-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde --- drivers/net/can/ifi_canfd/ifi_canfd.c | 44 ++++++++++++++------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/drivers/net/can/ifi_canfd/ifi_canfd.c b/drivers/net/can/ifi_canfd/ifi_canfd.c index 0d1c164374b7..57581cb80956 100644 --- a/drivers/net/can/ifi_canfd/ifi_canfd.c +++ b/drivers/net/can/ifi_canfd/ifi_canfd.c @@ -514,25 +514,25 @@ static irqreturn_t ifi_canfd_isr(int irq, void *dev_id) static const struct can_bittiming_const ifi_canfd_bittiming_const = { .name = KBUILD_MODNAME, - .tseg1_min = 2, /* Time segment 1 = prop_seg + phase_seg1 */ + .tseg1_min = 1, /* Time segment 1 = prop_seg + phase_seg1 */ .tseg1_max = 64, - .tseg2_min = 1, /* Time segment 2 = phase_seg2 */ - .tseg2_max = 16, + .tseg2_min = 2, /* Time segment 2 = phase_seg2 */ + .tseg2_max = 64, .sjw_max = 16, - .brp_min = 1, - .brp_max = 1024, + .brp_min = 2, + .brp_max = 256, .brp_inc = 1, }; static const struct can_bittiming_const ifi_canfd_data_bittiming_const = { .name = KBUILD_MODNAME, - .tseg1_min = 2, /* Time segment 1 = prop_seg + phase_seg1 */ - .tseg1_max = 16, - .tseg2_min = 1, /* Time segment 2 = phase_seg2 */ - .tseg2_max = 8, - .sjw_max = 4, - .brp_min = 1, - .brp_max = 32, + .tseg1_min = 1, /* Time segment 1 = prop_seg + phase_seg1 */ + .tseg1_max = 64, + .tseg2_min = 2, /* Time segment 2 = phase_seg2 */ + .tseg2_max = 64, + .sjw_max = 16, + .brp_min = 2, + .brp_max = 256, .brp_inc = 1, }; @@ -545,32 +545,34 @@ static void ifi_canfd_set_bittiming(struct net_device *ndev) u32 noniso_arg = 0; u32 time_off; - if (priv->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO) { + if ((priv->can.ctrlmode & CAN_CTRLMODE_FD) && + !(priv->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO)) { + time_off = IFI_CANFD_TIME_SJW_OFF_ISO; + } else { noniso_arg = IFI_CANFD_TIME_SET_TIMEB_BOSCH | IFI_CANFD_TIME_SET_TIMEA_BOSCH | IFI_CANFD_TIME_SET_PRESC_BOSCH | IFI_CANFD_TIME_SET_SJW_BOSCH; time_off = IFI_CANFD_TIME_SJW_OFF_BOSCH; - } else { - time_off = IFI_CANFD_TIME_SJW_OFF_ISO; } /* Configure bit timing */ - brp = bt->brp - 1; + brp = bt->brp - 2; sjw = bt->sjw - 1; tseg1 = bt->prop_seg + bt->phase_seg1 - 1; - tseg2 = bt->phase_seg2 - 1; + tseg2 = bt->phase_seg2 - 2; writel((tseg2 << IFI_CANFD_TIME_TIMEB_OFF) | (tseg1 << IFI_CANFD_TIME_TIMEA_OFF) | (brp << IFI_CANFD_TIME_PRESCALE_OFF) | - (sjw << time_off), + (sjw << time_off) | + noniso_arg, priv->base + IFI_CANFD_TIME); /* Configure data bit timing */ - brp = dbt->brp - 1; + brp = dbt->brp - 2; sjw = dbt->sjw - 1; tseg1 = dbt->prop_seg + dbt->phase_seg1 - 1; - tseg2 = dbt->phase_seg2 - 1; + tseg2 = dbt->phase_seg2 - 2; writel((tseg2 << IFI_CANFD_TIME_TIMEB_OFF) | (tseg1 << IFI_CANFD_TIME_TIMEA_OFF) | (brp << IFI_CANFD_TIME_PRESCALE_OFF) | @@ -847,7 +849,7 @@ static int ifi_canfd_plat_probe(struct platform_device *pdev) priv->can.state = CAN_STATE_STOPPED; - priv->can.clock.freq = readl(addr + IFI_CANFD_SYSCLOCK); + priv->can.clock.freq = readl(addr + IFI_CANFD_CANCLOCK); priv->can.bittiming_const = &ifi_canfd_bittiming_const; priv->can.data_bittiming_const = &ifi_canfd_data_bittiming_const; From f1deaee0c3ab1950987d7207d613df0417bd251c Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 3 Mar 2016 20:45:56 +0100 Subject: [PATCH 2/5] can: ifi: Fix TX DLC configuration The TX DLC, the transmission length information, was not written into the transmit configuration register. When using the CAN core with different CAN controller, the receiving CAN controller will receive only the ID part of the CAN frame, but no data at all. This patch adds the TX DLC into the register to fix this issue. Signed-off-by: Marek Vasut Cc: Marc Kleine-Budde Cc: Mark Rutland Cc: Oliver Hartkopp Cc: Wolfgang Grandegger Reviewed-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde --- drivers/net/can/ifi_canfd/ifi_canfd.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/net/can/ifi_canfd/ifi_canfd.c b/drivers/net/can/ifi_canfd/ifi_canfd.c index 57581cb80956..fb93122a2bd3 100644 --- a/drivers/net/can/ifi_canfd/ifi_canfd.c +++ b/drivers/net/can/ifi_canfd/ifi_canfd.c @@ -749,8 +749,7 @@ static netdev_tx_t ifi_canfd_start_xmit(struct sk_buff *skb, { struct ifi_canfd_priv *priv = netdev_priv(ndev); struct canfd_frame *cf = (struct canfd_frame *)skb->data; - u32 txst, txid; - u32 txdlc = 0; + u32 txst, txid, txdlc; int i; if (can_dropped_invalid_skb(ndev, skb)) @@ -773,12 +772,11 @@ static netdev_tx_t ifi_canfd_start_xmit(struct sk_buff *skb, txid = cf->can_id & CAN_SFF_MASK; } - if (priv->can.ctrlmode & (CAN_CTRLMODE_FD | CAN_CTRLMODE_FD_NON_ISO)) { - if (can_is_canfd_skb(skb)) { - txdlc |= IFI_CANFD_TXFIFO_DLC_EDL; - if (cf->flags & CANFD_BRS) - txdlc |= IFI_CANFD_TXFIFO_DLC_BRS; - } + txdlc = can_len2dlc(cf->len); + if ((priv->can.ctrlmode & CAN_CTRLMODE_FD) && can_is_canfd_skb(skb)) { + txdlc |= IFI_CANFD_TXFIFO_DLC_EDL; + if (cf->flags & CANFD_BRS) + txdlc |= IFI_CANFD_TXFIFO_DLC_BRS; } if (cf->can_id & CAN_RTR_FLAG) From 223654355c4eb35f890233e6a52b0f8d79bc3b44 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 3 Mar 2016 20:45:57 +0100 Subject: [PATCH 3/5] can: ifi: Fix RX and TX ID mask The RX and TX ID mask for CAN2.0 is 11 bits wide. This patch fixes the incorrect mask, which caused the CAN IDs to miss the MSBit both on receive and transmit. Signed-off-by: Marek Vasut Cc: Marc Kleine-Budde Cc: Mark Rutland Cc: Oliver Hartkopp Cc: Wolfgang Grandegger Reviewed-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde --- drivers/net/can/ifi_canfd/ifi_canfd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/can/ifi_canfd/ifi_canfd.c b/drivers/net/can/ifi_canfd/ifi_canfd.c index fb93122a2bd3..aee43c0c631a 100644 --- a/drivers/net/can/ifi_canfd/ifi_canfd.c +++ b/drivers/net/can/ifi_canfd/ifi_canfd.c @@ -135,8 +135,8 @@ #define IFI_CANFD_RXFIFO_ID 0x6c #define IFI_CANFD_RXFIFO_ID_ID_OFFSET 0 -#define IFI_CANFD_RXFIFO_ID_ID_STD_MASK 0x3ff -#define IFI_CANFD_RXFIFO_ID_ID_XTD_MASK 0x1fffffff +#define IFI_CANFD_RXFIFO_ID_ID_STD_MASK CAN_SFF_MASK +#define IFI_CANFD_RXFIFO_ID_ID_XTD_MASK CAN_EFF_MASK #define IFI_CANFD_RXFIFO_ID_IDE BIT(29) #define IFI_CANFD_RXFIFO_DATA 0x70 /* 0x70..0xac */ @@ -156,8 +156,8 @@ #define IFI_CANFD_TXFIFO_ID 0xbc #define IFI_CANFD_TXFIFO_ID_ID_OFFSET 0 -#define IFI_CANFD_TXFIFO_ID_ID_STD_MASK 0x3ff -#define IFI_CANFD_TXFIFO_ID_ID_XTD_MASK 0x1fffffff +#define IFI_CANFD_TXFIFO_ID_ID_STD_MASK CAN_SFF_MASK +#define IFI_CANFD_TXFIFO_ID_ID_XTD_MASK CAN_EFF_MASK #define IFI_CANFD_TXFIFO_ID_IDE BIT(29) #define IFI_CANFD_TXFIFO_DATA 0xc0 /* 0xb0..0xfc */ From 6cc6426605b7edabde41c72add723979d1d509e7 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 3 Mar 2016 20:45:58 +0100 Subject: [PATCH 4/5] can: ifi: Add obscure bit swap for EFF frame IDs In case of CAN2.0 EFF frame, the controller handles frame IDs in a rather bizzare way. The ID is split into an extended part, IDX[28:11] and standard part, ID[10:0]. In the TX path, the core first sends the top 11 bits of the IDX, followed by ID and finally the rest of IDX. In the RX path, the core stores the ID the LSbit part of IDX field, followed by the LSbit parts of real IDX. The MSbit parts of IDX are stored in ID field of the register. This patch implements the necessary bit shuffling to mitigate this obscure behavior. In case two of these controllers are connected together, the RX and TX bit swapping nullifies itself and the issue does not manifest. The issue only manifests when talking to another different CAN controller. Signed-off-by: Marek Vasut Cc: Marc Kleine-Budde Cc: Mark Rutland Cc: Oliver Hartkopp Cc: Wolfgang Grandegger Reviewed-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde --- drivers/net/can/ifi_canfd/ifi_canfd.c | 31 +++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/ifi_canfd/ifi_canfd.c b/drivers/net/can/ifi_canfd/ifi_canfd.c index aee43c0c631a..a1bd54ffd31e 100644 --- a/drivers/net/can/ifi_canfd/ifi_canfd.c +++ b/drivers/net/can/ifi_canfd/ifi_canfd.c @@ -136,7 +136,11 @@ #define IFI_CANFD_RXFIFO_ID 0x6c #define IFI_CANFD_RXFIFO_ID_ID_OFFSET 0 #define IFI_CANFD_RXFIFO_ID_ID_STD_MASK CAN_SFF_MASK +#define IFI_CANFD_RXFIFO_ID_ID_STD_OFFSET 0 +#define IFI_CANFD_RXFIFO_ID_ID_STD_WIDTH 10 #define IFI_CANFD_RXFIFO_ID_ID_XTD_MASK CAN_EFF_MASK +#define IFI_CANFD_RXFIFO_ID_ID_XTD_OFFSET 11 +#define IFI_CANFD_RXFIFO_ID_ID_XTD_WIDTH 18 #define IFI_CANFD_RXFIFO_ID_IDE BIT(29) #define IFI_CANFD_RXFIFO_DATA 0x70 /* 0x70..0xac */ @@ -157,7 +161,11 @@ #define IFI_CANFD_TXFIFO_ID 0xbc #define IFI_CANFD_TXFIFO_ID_ID_OFFSET 0 #define IFI_CANFD_TXFIFO_ID_ID_STD_MASK CAN_SFF_MASK +#define IFI_CANFD_TXFIFO_ID_ID_STD_OFFSET 0 +#define IFI_CANFD_TXFIFO_ID_ID_STD_WIDTH 10 #define IFI_CANFD_TXFIFO_ID_ID_XTD_MASK CAN_EFF_MASK +#define IFI_CANFD_TXFIFO_ID_ID_XTD_OFFSET 11 +#define IFI_CANFD_TXFIFO_ID_ID_XTD_WIDTH 18 #define IFI_CANFD_TXFIFO_ID_IDE BIT(29) #define IFI_CANFD_TXFIFO_DATA 0xc0 /* 0xb0..0xfc */ @@ -229,10 +237,20 @@ static void ifi_canfd_read_fifo(struct net_device *ndev) rxid = readl(priv->base + IFI_CANFD_RXFIFO_ID); id = (rxid >> IFI_CANFD_RXFIFO_ID_ID_OFFSET); - if (id & IFI_CANFD_RXFIFO_ID_IDE) + if (id & IFI_CANFD_RXFIFO_ID_IDE) { id &= IFI_CANFD_RXFIFO_ID_ID_XTD_MASK; - else + /* + * In case the Extended ID frame is received, the standard + * and extended part of the ID are swapped in the register, + * so swap them back to obtain the correct ID. + */ + id = (id >> IFI_CANFD_RXFIFO_ID_ID_XTD_OFFSET) | + ((id & IFI_CANFD_RXFIFO_ID_ID_STD_MASK) << + IFI_CANFD_RXFIFO_ID_ID_XTD_WIDTH); + id |= CAN_EFF_FLAG; + } else { id &= IFI_CANFD_RXFIFO_ID_ID_STD_MASK; + } cf->can_id = id; if (rxdlc & IFI_CANFD_RXFIFO_DLC_ESI) { @@ -767,6 +785,15 @@ static netdev_tx_t ifi_canfd_start_xmit(struct sk_buff *skb, if (cf->can_id & CAN_EFF_FLAG) { txid = cf->can_id & CAN_EFF_MASK; + /* + * In case the Extended ID frame is transmitted, the + * standard and extended part of the ID are swapped + * in the register, so swap them back to send the + * correct ID. + */ + txid = (txid >> IFI_CANFD_TXFIFO_ID_ID_XTD_WIDTH) | + ((txid & IFI_CANFD_TXFIFO_ID_ID_XTD_MASK) << + IFI_CANFD_TXFIFO_ID_ID_XTD_OFFSET); txid |= IFI_CANFD_TXFIFO_ID_IDE; } else { txid = cf->can_id & CAN_SFF_MASK; From e481ab23c57b37c989fa27e0a6b3e941a908775a Mon Sep 17 00:00:00 2001 From: Ramesh Shanmugasundaram Date: Mon, 29 Feb 2016 12:37:25 +0000 Subject: [PATCH 5/5] can: rcar_can: Add r8a7795 support Added r8a7795 SoC support. Signed-off-by: Ramesh Shanmugasundaram Acked-by: Rob Herring Signed-off-by: Marc Kleine-Budde --- .../devicetree/bindings/net/can/rcar_can.txt | 11 +++++++++++ drivers/net/can/Kconfig | 2 +- drivers/net/can/rcar_can.c | 1 + 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/net/can/rcar_can.txt b/Documentation/devicetree/bindings/net/can/rcar_can.txt index 65edc055722f..8d40ab27bc8c 100644 --- a/Documentation/devicetree/bindings/net/can/rcar_can.txt +++ b/Documentation/devicetree/bindings/net/can/rcar_can.txt @@ -9,8 +9,10 @@ Required properties: "renesas,can-r8a7792" if CAN controller is a part of R8A7792 SoC. "renesas,can-r8a7793" if CAN controller is a part of R8A7793 SoC. "renesas,can-r8a7794" if CAN controller is a part of R8A7794 SoC. + "renesas,can-r8a7795" if CAN controller is a part of R8A7795 SoC. "renesas,rcar-gen1-can" for a generic R-Car Gen1 compatible device. "renesas,rcar-gen2-can" for a generic R-Car Gen2 compatible device. + "renesas,rcar-gen3-can" for a generic R-Car Gen3 compatible device. When compatible with the generic version, nodes must list the SoC-specific version corresponding to the platform first followed by the generic version. @@ -22,6 +24,15 @@ Required properties: - pinctrl-0: pin control group to be used for this controller. - pinctrl-names: must be "default". +Required properties for "renesas,can-r8a7795" compatible: +In R8A7795 SoC, "clkp2" can be CANFD clock. This is a div6 clock and can be +used by both CAN and CAN FD controller at the same time. It needs to be scaled +to maximum frequency if any of these controllers use it. This is done using +the below properties. + +- assigned-clocks: phandle of clkp2(CANFD) clock. +- assigned-clock-rates: maximum frequency of this clock. + Optional properties: - renesas,can-clock-select: R-Car CAN Clock Source Select. Valid values are: <0x0> (default) : Peripheral clock (clkp1) diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index 164ccdeca663..0d40aef928e2 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig @@ -106,7 +106,7 @@ config CAN_JANZ_ICAN3 config CAN_RCAR tristate "Renesas R-Car CAN controller" - depends on ARM + depends on ARCH_RENESAS || ARM ---help--- Say Y here if you want to use CAN controller found on Renesas R-Car SoCs. diff --git a/drivers/net/can/rcar_can.c b/drivers/net/can/rcar_can.c index ad3d2e0cb191..788459f6bf5c 100644 --- a/drivers/net/can/rcar_can.c +++ b/drivers/net/can/rcar_can.c @@ -906,6 +906,7 @@ static const struct of_device_id rcar_can_of_table[] __maybe_unused = { { .compatible = "renesas,can-r8a7791" }, { .compatible = "renesas,rcar-gen1-can" }, { .compatible = "renesas,rcar-gen2-can" }, + { .compatible = "renesas,rcar-gen3-can" }, { } }; MODULE_DEVICE_TABLE(of, rcar_can_of_table);