From: Marc Kleine-Budde <mkl@pengutronix.de>
To: Marek Vasut <marex@denx.de>, netdev@vger.kernel.org
Cc: Oliver Hartkopp <socketcan@hartkopp.net>,
Mark Rutland <mark.rutland@arm.com>,
Wolfgang Grandegger <wg@grandegger.com>
Subject: Re: [PATCH V3 5/5] net: can: ifi: Add IFI CANFD IP support
Date: Wed, 20 Jan 2016 15:39:51 +0100 [thread overview]
Message-ID: <569F9C37.60007@pengutronix.de> (raw)
In-Reply-To: <1453300419-5716-1-git-send-email-marex@denx.de>
[-- Attachment #1: Type: text/plain, Size: 19868 bytes --]
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@denx.de>
> Cc: Marc Kleine-Budde <mkl@pengutronix.de>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: Oliver Hartkopp <socketcan@hartkopp.net>
> Cc: Wolfgang Grandegger <wg@grandegger.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@denx.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 |
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 455 bytes --]
next prev parent reply other threads:[~2016-01-20 14:40 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-01-11 18:47 [PATCH 1/5] net: can: Sort the Kconfig includes Marek Vasut
2016-01-11 18:48 ` [PATCH 2/5] net: can: Sort the Makefile Marek Vasut
2016-01-11 18:48 ` [PATCH 3/5] of: Add vendor prefix for I/F/I Marek Vasut
2016-01-11 18:48 ` [PATCH 4/5] net: can: ifi: Add DT bindings for ifi,canfd Marek Vasut
2016-01-11 18:48 ` [PATCH 5/5] net: can: ifi: Add IFI CANFD IP support Marek Vasut
2016-01-11 19:29 ` kbuild test robot
2016-01-11 19:33 ` Marek Vasut
2016-01-12 11:06 ` kbuild test robot
2016-01-12 23:59 ` [PATCH V2 " Marek Vasut
2016-01-20 10:39 ` Marc Kleine-Budde
2016-01-20 10:54 ` Marc Kleine-Budde
2016-01-20 12:58 ` Marek Vasut
2016-01-20 14:06 ` Marc Kleine-Budde
2016-01-20 14:25 ` Marek Vasut
2016-01-23 0:11 ` Rustad, Mark D
2016-01-20 14:33 ` [PATCH V3 " Marek Vasut
2016-01-20 14:39 ` Marc Kleine-Budde [this message]
2016-01-20 14:41 ` Marek Vasut
2016-01-20 14:46 ` Marc Kleine-Budde
2016-01-20 15:03 ` Marek Vasut
2016-01-20 15:09 ` Marc Kleine-Budde
2016-01-20 15:40 ` Marek Vasut
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=569F9C37.60007@pengutronix.de \
--to=mkl@pengutronix.de \
--cc=marex@denx.de \
--cc=mark.rutland@arm.com \
--cc=netdev@vger.kernel.org \
--cc=socketcan@hartkopp.net \
--cc=wg@grandegger.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.