[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <569F9C37.60007@pengutronix.de>
Date: Wed, 20 Jan 2016 15:39:51 +0100
From: Marc Kleine-Budde <mkl@...gutronix.de>
To: Marek Vasut <marex@...x.de>, netdev@...r.kernel.org
Cc: Oliver Hartkopp <socketcan@...tkopp.net>,
Mark Rutland <mark.rutland@....com>,
Wolfgang Grandegger <wg@...ndegger.com>
Subject: Re: [PATCH V3 5/5] net: can: ifi: Add IFI CANFD IP support
On 01/20/2016 03:33 PM, Marek Vasut wrote:
> The patch adds support for IFI CAN/FD controller [1]. This driver
> currently supports sending and receiving both standard CAN and new
> CAN/FD frames. Both ISO and BOSCH variant of CAN/FD is supported.
>
> [1] http://www.ifi-pld.de/IP/CANFD/canfd.html
>
> Signed-off-by: Marek Vasut <marex@...x.de>
> Cc: Marc Kleine-Budde <mkl@...gutronix.de>
> Cc: Mark Rutland <mark.rutland@....com>
> Cc: Oliver Hartkopp <socketcan@...tkopp.net>
> Cc: Wolfgang Grandegger <wg@...ndegger.com>
> ---
> V2: - Move request_irq()/free_irq() into ifi_canfd_open()/ifi_canfd_close()
> just like other drivers do it to prevent crash when reloading module.
> - Fix Woverflow complains on x86_64 and itanium, exactly the same way
> as in commit dec23dca5a9ca4b9eb2fb66926f567889028b904 .
>
> V3: - Hopefully fix all problems with BIT(31) by adding more u32 casts.
> - Drop struct device from struct ifi_canfd_priv .
>
> NOTE: The driver is surprisingly similar to m_can, but the register
> layout of the IFI core is completely different, so it's clear
> that those are two different IP cores.
> ---
> drivers/net/can/Kconfig | 2 +
> drivers/net/can/Makefile | 1 +
> drivers/net/can/ifi_canfd/Kconfig | 8 +
> drivers/net/can/ifi_canfd/Makefile | 5 +
> drivers/net/can/ifi_canfd/ifi_canfd.c | 917 ++++++++++++++++++++++++++++++++++
> 5 files changed, 933 insertions(+)
> create mode 100644 drivers/net/can/ifi_canfd/Kconfig
> create mode 100644 drivers/net/can/ifi_canfd/Makefile
> create mode 100644 drivers/net/can/ifi_canfd/ifi_canfd.c
>
> diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
> index ca49d15..20be638 100644
> --- a/drivers/net/can/Kconfig
> +++ b/drivers/net/can/Kconfig
> @@ -151,6 +151,8 @@ source "drivers/net/can/c_can/Kconfig"
>
> source "drivers/net/can/cc770/Kconfig"
>
> +source "drivers/net/can/ifi_canfd/Kconfig"
> +
> source "drivers/net/can/m_can/Kconfig"
>
> source "drivers/net/can/mscan/Kconfig"
> diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
> index 4f85c2b..e3db0c8 100644
> --- a/drivers/net/can/Makefile
> +++ b/drivers/net/can/Makefile
> @@ -20,6 +20,7 @@ obj-$(CONFIG_CAN_CC770) += cc770/
> obj-$(CONFIG_CAN_C_CAN) += c_can/
> obj-$(CONFIG_CAN_FLEXCAN) += flexcan.o
> obj-$(CONFIG_CAN_GRCAN) += grcan.o
> +obj-$(CONFIG_CAN_IFI_CANFD) += ifi_canfd/
> obj-$(CONFIG_CAN_JANZ_ICAN3) += janz-ican3.o
> obj-$(CONFIG_CAN_MSCAN) += mscan/
> obj-$(CONFIG_CAN_M_CAN) += m_can/
> diff --git a/drivers/net/can/ifi_canfd/Kconfig b/drivers/net/can/ifi_canfd/Kconfig
> new file mode 100644
> index 0000000..9e8934f
> --- /dev/null
> +++ b/drivers/net/can/ifi_canfd/Kconfig
> @@ -0,0 +1,8 @@
> +config CAN_IFI_CANFD
> + depends on HAS_IOMEM
> + tristate "IFI CAN_FD IP"
> + ---help---
> + This driver adds support for the I/F/I CAN_FD soft IP block
> + connected to the "platform bus" (Linux abstraction for directly
> + to the processor attached devices). The CAN_FD is most often
> + synthesised into an FPGA or CPLD.
> diff --git a/drivers/net/can/ifi_canfd/Makefile b/drivers/net/can/ifi_canfd/Makefile
> new file mode 100644
> index 0000000..b229960
> --- /dev/null
> +++ b/drivers/net/can/ifi_canfd/Makefile
> @@ -0,0 +1,5 @@
> +#
> +# Makefile for the IFI CANFD controller driver.
> +#
> +
> +obj-$(CONFIG_CAN_IFI_CANFD) += ifi_canfd.o
> diff --git a/drivers/net/can/ifi_canfd/ifi_canfd.c b/drivers/net/can/ifi_canfd/ifi_canfd.c
> new file mode 100644
> index 0000000..639868b
> --- /dev/null
> +++ b/drivers/net/can/ifi_canfd/ifi_canfd.c
> @@ -0,0 +1,917 @@
> +/*
> + * CAN bus driver for IFI CANFD controller
> + *
> + * Copyright (C) 2016 Marek Vasut <marex@...x.de>
> + *
> + * Details about this controller can be found at
> + * http://www.ifi-pld.de/IP/CANFD/canfd.html
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/kernel.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/can/dev.h>
> +
> +#define IFI_CANFD_STCMD 0x0
> +#define IFI_CANFD_STCMD_HARDRESET 0xDEADCAFD
> +#define IFI_CANFD_STCMD_ENABLE BIT(0)
> +#define IFI_CANFD_STCMD_ERROR_ACTIVE BIT(2)
> +#define IFI_CANFD_STCMD_ERROR_PASSIVE BIT(3)
> +#define IFI_CANFD_STCMD_BUSOFF BIT(4)
> +#define IFI_CANFD_STCMD_BUSMONITOR BIT(16)
> +#define IFI_CANFD_STCMD_LOOPBACK BIT(18)
> +#define IFI_CANFD_STCMD_DISABLE_CANFD BIT(24)
> +#define IFI_CANFD_STCMD_ENABLE_ISO BIT(25)
> +#define IFI_CANFD_STCMD_NORMAL_MODE ((u32)BIT(31))
> +
> +#define IFI_CANFD_RXSTCMD 0x4
> +#define IFI_CANFD_RXSTCMD_REMOVE_MSG BIT(0)
> +#define IFI_CANFD_RXSTCMD_RESET BIT(7)
> +#define IFI_CANFD_RXSTCMD_EMPTY BIT(8)
> +#define IFI_CANFD_RXSTCMD_OVERFLOW BIT(13)
> +
> +#define IFI_CANFD_TXSTCMD 0x8
> +#define IFI_CANFD_TXSTCMD_ADD_MSG BIT(0)
> +#define IFI_CANFD_TXSTCMD_HIGH_PRIO BIT(1)
> +#define IFI_CANFD_TXSTCMD_RESET BIT(7)
> +#define IFI_CANFD_TXSTCMD_EMPTY BIT(8)
> +#define IFI_CANFD_TXSTCMD_FULL BIT(12)
> +#define IFI_CANFD_TXSTCMD_OVERFLOW BIT(13)
> +
> +#define IFI_CANFD_INTERRUPT 0xc
> +#define IFI_CANFD_INTERRUPT_ERROR_WARNING BIT(1)
> +#define IFI_CANFD_INTERRUPT_TXFIFO_EMPTY BIT(16)
> +#define IFI_CANFD_INTERRUPT_TXFIFO_REMOVE BIT(22)
> +#define IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY BIT(24)
> +#define IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY_PER BIT(25)
> +#define IFI_CANFD_INTERRUPT_SET_IRQ ((u32)BIT(31))
> +
> +#define IFI_CANFD_IRQMASK 0x10
> +#define IFI_CANFD_IRQMASK_SET_ERR BIT(7)
> +#define IFI_CANFD_IRQMASK_SET_TS BIT(15)
> +#define IFI_CANFD_IRQMASK_TXFIFO_EMPTY BIT(16)
> +#define IFI_CANFD_IRQMASK_SET_TX BIT(23)
> +#define IFI_CANFD_IRQMASK_RXFIFO_NEMPTY BIT(24)
> +#define IFI_CANFD_IRQMASK_SET_RX ((u32)BIT(31))
> +
> +#define IFI_CANFD_TIME 0x14
> +#define IFI_CANFD_FTIME 0x18
> +#define IFI_CANFD_TIME_TIMEB_OFF 0
> +#define IFI_CANFD_TIME_TIMEA_OFF 8
> +#define IFI_CANFD_TIME_PRESCALE_OFF 16
> +#define IFI_CANFD_TIME_SJW_OFF_ISO 25
> +#define IFI_CANFD_TIME_SJW_OFF_BOSCH 28
> +#define IFI_CANFD_TIME_SET_SJW_BOSCH BIT(6)
> +#define IFI_CANFD_TIME_SET_TIMEB_BOSCH BIT(7)
> +#define IFI_CANFD_TIME_SET_PRESC_BOSCH BIT(14)
> +#define IFI_CANFD_TIME_SET_TIMEA_BOSCH BIT(15)
> +
> +#define IFI_CANFD_TDELAY 0x1c
> +
> +#define IFI_CANFD_ERROR 0x20
> +#define IFI_CANFD_ERROR_TX_OFFSET 0
> +#define IFI_CANFD_ERROR_TX_MASK 0xff
> +#define IFI_CANFD_ERROR_RX_OFFSET 16
> +#define IFI_CANFD_ERROR_RX_MASK 0xff
> +
> +#define IFI_CANFD_ERRCNT 0x24
> +
> +#define IFI_CANFD_SUSPEND 0x28
> +
> +#define IFI_CANFD_REPEAT 0x2c
> +
> +#define IFI_CANFD_TRAFFIC 0x30
> +
> +#define IFI_CANFD_TSCONTROL 0x34
> +
> +#define IFI_CANFD_TSC 0x38
> +
> +#define IFI_CANFD_TST 0x3c
> +
> +#define IFI_CANFD_RES1 0x40
> +
> +#define IFI_CANFD_RES2 0x44
> +
> +#define IFI_CANFD_PAR 0x48
> +
> +#define IFI_CANFD_CANCLOCK 0x4c
> +
> +#define IFI_CANFD_SYSCLOCK 0x50
> +
> +#define IFI_CANFD_VER 0x54
> +
> +#define IFI_CANFD_IP_ID 0x58
> +#define IFI_CANFD_IP_ID_VALUE 0xD073CAFD
> +
> +#define IFI_CANFD_TEST 0x5c
> +
> +#define IFI_CANFD_RXFIFO_TS_63_32 0x60
> +
> +#define IFI_CANFD_RXFIFO_TS_31_0 0x64
> +
> +#define IFI_CANFD_RXFIFO_DLC 0x68
> +#define IFI_CANFD_RXFIFO_DLC_DLC_OFFSET 0
> +#define IFI_CANFD_RXFIFO_DLC_DLC_MASK 0xf
> +#define IFI_CANFD_RXFIFO_DLC_RTR BIT(4)
> +#define IFI_CANFD_RXFIFO_DLC_EDL BIT(5)
> +#define IFI_CANFD_RXFIFO_DLC_BRS BIT(6)
> +#define IFI_CANFD_RXFIFO_DLC_ESI BIT(7)
> +#define IFI_CANFD_RXFIFO_DLC_OBJ_OFFSET 8
> +#define IFI_CANFD_RXFIFO_DLC_OBJ_MASK 0x1ff
> +#define IFI_CANFD_RXFIFO_DLC_FNR_OFFSET 24
> +#define IFI_CANFD_RXFIFO_DLC_FNR_MASK 0xff
> +
> +#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_IDE BIT(29)
> +
> +#define IFI_CANFD_RXFIFO_DATA 0x70 /* 0x70..0xac */
> +
> +#define IFI_CANFD_TXFIFO_SUSPEND_US 0xb0
> +
> +#define IFI_CANFD_TXFIFO_REPEATCOUNT 0xb4
> +
> +#define IFI_CANFD_TXFIFO_DLC 0xb8
> +#define IFI_CANFD_TXFIFO_DLC_DLC_OFFSET 0
> +#define IFI_CANFD_TXFIFO_DLC_DLC_MASK 0xf
> +#define IFI_CANFD_TXFIFO_DLC_RTR BIT(4)
> +#define IFI_CANFD_TXFIFO_DLC_EDL BIT(5)
> +#define IFI_CANFD_TXFIFO_DLC_BRS BIT(6)
> +#define IFI_CANFD_TXFIFO_DLC_FNR_OFFSET 24
> +#define IFI_CANFD_TXFIFO_DLC_FNR_MASK 0xff
> +
> +#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_IDE BIT(29)
> +
> +#define IFI_CANFD_TXFIFO_DATA 0xc0 /* 0xb0..0xfc */
> +
> +#define IFI_CANFD_FILTER_MASK(n) (0x800 + ((n) * 8) + 0)
> +#define IFI_CANFD_FILTER_MASK_EXT BIT(29)
> +#define IFI_CANFD_FILTER_MASK_EDL BIT(30)
> +#define IFI_CANFD_FILTER_MASK_VALID ((u32)BIT(31))
> +
> +#define IFI_CANFD_FILTER_IDENT(n) (0x800 + ((n) * 8) + 4)
> +#define IFI_CANFD_FILTER_IDENT_IDE BIT(29)
> +#define IFI_CANFD_FILTER_IDENT_CANFD BIT(30)
> +#define IFI_CANFD_FILTER_IDENT_VALID ((u32)BIT(31))
> +
> +/* IFI CANFD private data structure */
> +struct ifi_canfd_priv {
> + struct can_priv can; /* must be the first member */
> + struct napi_struct napi;
> + struct net_device *ndev;
> + void __iomem *base;
> +};
> +
> +static void ifi_canfd_irq_enable(struct net_device *ndev, bool enable)
> +{
> + struct ifi_canfd_priv *priv = netdev_priv(ndev);
> + u32 enirq = 0;
> +
> + if (enable) {
> + enirq = IFI_CANFD_IRQMASK_TXFIFO_EMPTY |
> + IFI_CANFD_IRQMASK_RXFIFO_NEMPTY;
> + }
> +
> + writel(IFI_CANFD_IRQMASK_SET_ERR |
> + IFI_CANFD_IRQMASK_SET_TS |
> + IFI_CANFD_IRQMASK_SET_TX |
> + IFI_CANFD_IRQMASK_SET_RX | enirq,
> + priv->base + IFI_CANFD_IRQMASK);
> +}
> +
> +static void ifi_canfd_read_fifo(struct net_device *ndev)
> +{
> + struct net_device_stats *stats = &ndev->stats;
> + struct ifi_canfd_priv *priv = netdev_priv(ndev);
> + struct canfd_frame *cf;
> + struct sk_buff *skb;
> + const u32 rx_irq_mask = IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY |
> + IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY_PER;
> + u32 rxdlc, rxid;
> + u32 dlc, id;
> + int i;
> +
> + rxdlc = readl(priv->base + IFI_CANFD_RXFIFO_DLC);
> + if (rxdlc & IFI_CANFD_RXFIFO_DLC_EDL)
> + skb = alloc_canfd_skb(ndev, &cf);
> + else
> + skb = alloc_can_skb(ndev, (struct can_frame **)&cf);
> +
> + if (!skb) {
> + stats->rx_dropped++;
> + return;
> + }
> +
> + dlc = (rxdlc >> IFI_CANFD_RXFIFO_DLC_DLC_OFFSET) &
> + IFI_CANFD_RXFIFO_DLC_DLC_MASK;
> + if (rxdlc & IFI_CANFD_RXFIFO_DLC_EDL)
> + cf->len = can_dlc2len(dlc);
> + else
> + cf->len = get_can_dlc(dlc);
> +
> + rxid = readl(priv->base + IFI_CANFD_RXFIFO_ID);
> + id = (rxid >> IFI_CANFD_RXFIFO_ID_ID_OFFSET);
> + if (id & IFI_CANFD_RXFIFO_ID_IDE)
> + id &= IFI_CANFD_RXFIFO_ID_ID_XTD_MASK;
> + else
> + id &= IFI_CANFD_RXFIFO_ID_ID_STD_MASK;
> + cf->can_id = id;
> +
> + if (rxdlc & IFI_CANFD_RXFIFO_DLC_ESI) {
> + cf->flags |= CANFD_ESI;
> + netdev_dbg(ndev, "ESI Error\n");
> + }
> +
> + if (!(rxdlc & IFI_CANFD_RXFIFO_DLC_EDL) &&
> + (rxdlc & IFI_CANFD_RXFIFO_DLC_RTR)) {
> + cf->can_id |= CAN_RTR_FLAG;
> + } else {
> + if (rxdlc & IFI_CANFD_RXFIFO_DLC_BRS)
> + cf->flags |= CANFD_BRS;
> +
> + for (i = 0; i < cf->len; i += 4) {
> + *(u32 *)(cf->data + i) =
> + readl(priv->base + IFI_CANFD_RXFIFO_DATA + i);
> + }
> + }
> +
> + /* Remove the packet from FIFO */
> + writel(IFI_CANFD_RXSTCMD_REMOVE_MSG, priv->base + IFI_CANFD_RXSTCMD);
> + writel(rx_irq_mask, priv->base + IFI_CANFD_INTERRUPT);
> +
> + stats->rx_packets++;
> + stats->rx_bytes += cf->len;
> +
> + netif_receive_skb(skb);
> +}
> +
> +static int ifi_canfd_do_rx_poll(struct net_device *ndev, int quota)
> +{
> + struct ifi_canfd_priv *priv = netdev_priv(ndev);
> + u32 pkts = 0;
> + u32 rxst;
> +
> + rxst = readl(priv->base + IFI_CANFD_RXSTCMD);
> + if (rxst & IFI_CANFD_RXSTCMD_EMPTY) {
> + netdev_dbg(ndev, "No messages in RX FIFO\n");
> + return 0;
> + }
> +
> + for (;;) {
> + if (rxst & IFI_CANFD_RXSTCMD_EMPTY)
> + break;
> + if (quota <= 0)
> + break;
> +
> + ifi_canfd_read_fifo(ndev);
> + quota--;
> + pkts++;
> + rxst = readl(priv->base + IFI_CANFD_RXSTCMD);
> + }
> +
> + if (pkts)
> + can_led_event(ndev, CAN_LED_EVENT_RX);
> +
> + return pkts;
> +}
> +
> +static int ifi_canfd_handle_lost_msg(struct net_device *ndev)
> +{
> + struct net_device_stats *stats = &ndev->stats;
> + struct sk_buff *skb;
> + struct can_frame *frame;
> +
> + netdev_err(ndev, "RX FIFO overflow, message(s) lost.\n");
> +
> + stats->rx_errors++;
> + stats->rx_over_errors++;
> +
> + skb = alloc_can_err_skb(ndev, &frame);
> + if (unlikely(!skb))
> + return 0;
> +
> + frame->can_id |= CAN_ERR_CRTL;
> + frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
> +
> + netif_receive_skb(skb);
> +
> + return 1;
> +}
> +
> +static int ifi_canfd_get_berr_counter(const struct net_device *ndev,
> + struct can_berr_counter *bec)
> +{
> + struct ifi_canfd_priv *priv = netdev_priv(ndev);
> + u32 err;
> +
> + err = readl(priv->base + IFI_CANFD_ERROR);
> + bec->rxerr = (err >> IFI_CANFD_ERROR_RX_OFFSET) &
> + IFI_CANFD_ERROR_RX_MASK;
> + bec->txerr = (err >> IFI_CANFD_ERROR_TX_OFFSET) &
> + IFI_CANFD_ERROR_TX_MASK;
> +
> + return 0;
> +}
> +
> +static int ifi_canfd_handle_state_change(struct net_device *ndev,
> + enum can_state new_state)
> +{
> + struct ifi_canfd_priv *priv = netdev_priv(ndev);
> + struct net_device_stats *stats = &ndev->stats;
> + struct can_frame *cf;
> + struct sk_buff *skb;
> + struct can_berr_counter bec;
> +
> + switch (new_state) {
> + case CAN_STATE_ERROR_ACTIVE:
> + /* error warning state */
> + priv->can.can_stats.error_warning++;
> + priv->can.state = CAN_STATE_ERROR_WARNING;
> + break;
> + case CAN_STATE_ERROR_PASSIVE:
> + /* error passive state */
> + priv->can.can_stats.error_passive++;
> + priv->can.state = CAN_STATE_ERROR_PASSIVE;
> + break;
> + case CAN_STATE_BUS_OFF:
> + /* bus-off state */
> + priv->can.state = CAN_STATE_BUS_OFF;
> + ifi_canfd_irq_enable(ndev, 0);
> + priv->can.can_stats.bus_off++;
> + can_bus_off(ndev);
> + break;
> + default:
> + break;
> + }
> +
> + /* propagate the error condition to the CAN stack */
> + skb = alloc_can_err_skb(ndev, &cf);
> + if (unlikely(!skb))
> + return 0;
> +
> + ifi_canfd_get_berr_counter(ndev, &bec);
> +
> + switch (new_state) {
> + case CAN_STATE_ERROR_ACTIVE:
> + /* error warning state */
> + cf->can_id |= CAN_ERR_CRTL;
> + cf->data[1] = (bec.txerr > bec.rxerr) ?
> + CAN_ERR_CRTL_TX_WARNING :
> + CAN_ERR_CRTL_RX_WARNING;
> + cf->data[6] = bec.txerr;
> + cf->data[7] = bec.rxerr;
> + break;
> + case CAN_STATE_ERROR_PASSIVE:
> + /* error passive state */
> + cf->can_id |= CAN_ERR_CRTL;
> + cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
> + if (bec.txerr > 127)
> + cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE;
> + cf->data[6] = bec.txerr;
> + cf->data[7] = bec.rxerr;
> + break;
> + case CAN_STATE_BUS_OFF:
> + /* bus-off state */
> + cf->can_id |= CAN_ERR_BUSOFF;
> + break;
> + default:
> + break;
> + }
> +
> + stats->rx_packets++;
> + stats->rx_bytes += cf->can_dlc;
> + netif_receive_skb(skb);
> +
> + return 1;
> +}
> +
> +static int ifi_canfd_handle_state_errors(struct net_device *ndev, u32 stcmd)
> +{
> + struct ifi_canfd_priv *priv = netdev_priv(ndev);
> + int work_done = 0;
> + u32 isr;
> +
> + /*
> + * The ErrWarn condition is a little special, since the bit is
> + * located in the INTERRUPT register instead of STCMD register.
> + */
> + isr = readl(priv->base + IFI_CANFD_INTERRUPT);
> + if ((isr & IFI_CANFD_INTERRUPT_ERROR_WARNING) &&
> + (priv->can.state != CAN_STATE_ERROR_WARNING)) {
> + /* Clear the interrupt */
> + writel(IFI_CANFD_INTERRUPT_ERROR_WARNING,
> + priv->base + IFI_CANFD_INTERRUPT);
> + netdev_dbg(ndev, "Error, entered warning state\n");
> + work_done += ifi_canfd_handle_state_change(ndev,
> + CAN_STATE_ERROR_WARNING);
> + }
> +
> + if ((stcmd & IFI_CANFD_STCMD_ERROR_PASSIVE) &&
> + (priv->can.state != CAN_STATE_ERROR_PASSIVE)) {
> + netdev_dbg(ndev, "Error, entered passive state\n");
> + work_done += ifi_canfd_handle_state_change(ndev,
> + CAN_STATE_ERROR_PASSIVE);
> + }
> +
> + if ((stcmd & IFI_CANFD_STCMD_BUSOFF) &&
> + (priv->can.state != CAN_STATE_BUS_OFF)) {
> + netdev_dbg(ndev, "Error, entered bus-off state\n");
> + work_done += ifi_canfd_handle_state_change(ndev,
> + CAN_STATE_BUS_OFF);
> + }
> +
> + return work_done;
> +}
> +
> +static int ifi_canfd_poll(struct napi_struct *napi, int quota)
> +{
> + struct net_device *ndev = napi->dev;
> + struct ifi_canfd_priv *priv = netdev_priv(ndev);
> + const u32 stcmd_state_mask = IFI_CANFD_STCMD_ERROR_PASSIVE |
> + IFI_CANFD_STCMD_BUSOFF;
> + int work_done = 0;
> +
> + u32 stcmd = readl(priv->base + IFI_CANFD_STCMD);
> + u32 rxstcmd = readl(priv->base + IFI_CANFD_STCMD);
> +
> + /* Handle bus state changes */
> + if ((stcmd & stcmd_state_mask) ||
> + ((stcmd & IFI_CANFD_STCMD_ERROR_ACTIVE) == 0))
> + work_done += ifi_canfd_handle_state_errors(ndev, stcmd);
> +
> + /* Handle lost messages on RX */
> + if (rxstcmd & IFI_CANFD_RXSTCMD_OVERFLOW)
> + work_done += ifi_canfd_handle_lost_msg(ndev);
> +
> + /* Handle normal messages on RX */
> + if (!(rxstcmd & IFI_CANFD_RXSTCMD_EMPTY))
> + work_done += ifi_canfd_do_rx_poll(ndev, quota - work_done);
> +
> + if (work_done < quota) {
> + napi_complete(napi);
> + ifi_canfd_irq_enable(ndev, 1);
> + }
> +
> + return work_done;
> +}
> +
> +static irqreturn_t ifi_canfd_isr(int irq, void *dev_id)
> +{
> + struct net_device *ndev = (struct net_device *)dev_id;
> + struct ifi_canfd_priv *priv = netdev_priv(ndev);
> + struct net_device_stats *stats = &ndev->stats;
> + const u32 rx_irq_mask = IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY |
> + IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY_PER;
> + const u32 tx_irq_mask = IFI_CANFD_INTERRUPT_TXFIFO_EMPTY |
> + IFI_CANFD_INTERRUPT_TXFIFO_REMOVE;
> + const u32 clr_irq_mask = (u32)(~(IFI_CANFD_INTERRUPT_SET_IRQ |
> + IFI_CANFD_INTERRUPT_ERROR_WARNING));
I've squashed:
>> - const u32 clr_irq_mask = (u32)(~(IFI_CANFD_INTERRUPT_SET_IRQ |
>> - IFI_CANFD_INTERRUPT_ERROR_WARNING));
>> + const u32 clr_irq_mask = ~(IFI_CANFD_INTERRUPT_SET_IRQ |
>> + IFI_CANFD_INTERRUPT_ERROR_WARNING);
and the driver compiles without warnings.
Applied to can-next.
thanks,
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
Download attachment "signature.asc" of type "application/pgp-signature" (456 bytes)
Powered by blists - more mailing lists