root/drivers/net/can/c_can/c_can_main.c
/*
 * CAN bus driver for Bosch C_CAN controller
 *
 * Copyright (C) 2010 ST Microelectronics
 * Bhupesh Sharma <bhupesh.sharma@st.com>
 *
 * Borrowed heavily from the C_CAN driver originally written by:
 * Copyright (C) 2007
 * - Sascha Hauer, Marc Kleine-Budde, Pengutronix <s.hauer@pengutronix.de>
 * - Simon Kallweit, intefo AG <simon.kallweit@intefo.ch>
 *
 * TX and RX NAPI implementation has been borrowed from at91 CAN driver
 * written by:
 * Copyright
 * (C) 2007 by Hans J. Koch <hjk@hansjkoch.de>
 * (C) 2008, 2009 by Marc Kleine-Budde <kernel@pengutronix.de>
 *
 * Bosch C_CAN controller is compliant to CAN protocol version 2.0 part A and B.
 * Bosch C_CAN user manual can be obtained from:
 * http://www.semiconductors.bosch.de/media/en/pdf/ipmodules_1/c_can/
 * users_manual_c_can.pdf
 *
 * 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/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/list.h>
#include <linux/io.h>
#include <linux/pm_runtime.h>
#include <linux/pinctrl/consumer.h>

#include <linux/can.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>

#include "c_can.h"

/* Number of interface registers */
#define IF_ENUM_REG_LEN         11
#define C_CAN_IFACE(reg, iface) (C_CAN_IF1_##reg + (iface) * IF_ENUM_REG_LEN)

/* control extension register D_CAN specific */
#define CONTROL_EX_PDR          BIT(8)

/* control register */
#define CONTROL_SWR             BIT(15)
#define CONTROL_TEST            BIT(7)
#define CONTROL_CCE             BIT(6)
#define CONTROL_DISABLE_AR      BIT(5)
#define CONTROL_ENABLE_AR       (0 << 5)
#define CONTROL_EIE             BIT(3)
#define CONTROL_SIE             BIT(2)
#define CONTROL_IE              BIT(1)
#define CONTROL_INIT            BIT(0)

#define CONTROL_IRQMSK          (CONTROL_EIE | CONTROL_IE | CONTROL_SIE)

/* test register */
#define TEST_RX                 BIT(7)
#define TEST_TX1                BIT(6)
#define TEST_TX2                BIT(5)
#define TEST_LBACK              BIT(4)
#define TEST_SILENT             BIT(3)
#define TEST_BASIC              BIT(2)

/* status register */
#define STATUS_PDA              BIT(10)
#define STATUS_BOFF             BIT(7)
#define STATUS_EWARN            BIT(6)
#define STATUS_EPASS            BIT(5)
#define STATUS_RXOK             BIT(4)
#define STATUS_TXOK             BIT(3)

/* error counter register */
#define ERR_CNT_TEC_MASK        0xff
#define ERR_CNT_TEC_SHIFT       0
#define ERR_CNT_REC_SHIFT       8
#define ERR_CNT_REC_MASK        (0x7f << ERR_CNT_REC_SHIFT)
#define ERR_CNT_RP_SHIFT        15
#define ERR_CNT_RP_MASK         (0x1 << ERR_CNT_RP_SHIFT)

/* bit-timing register */
#define BTR_BRP_MASK            0x3f
#define BTR_BRP_SHIFT           0
#define BTR_SJW_SHIFT           6
#define BTR_SJW_MASK            (0x3 << BTR_SJW_SHIFT)
#define BTR_TSEG1_SHIFT         8
#define BTR_TSEG1_MASK          (0xf << BTR_TSEG1_SHIFT)
#define BTR_TSEG2_SHIFT         12
#define BTR_TSEG2_MASK          (0x7 << BTR_TSEG2_SHIFT)

/* interrupt register */
#define INT_STS_PENDING         0x8000

/* brp extension register */
#define BRP_EXT_BRPE_MASK       0x0f
#define BRP_EXT_BRPE_SHIFT      0

/* IFx command request */
#define IF_COMR_BUSY            BIT(15)

/* IFx command mask */
#define IF_COMM_WR              BIT(7)
#define IF_COMM_MASK            BIT(6)
#define IF_COMM_ARB             BIT(5)
#define IF_COMM_CONTROL         BIT(4)
#define IF_COMM_CLR_INT_PND     BIT(3)
#define IF_COMM_TXRQST          BIT(2)
#define IF_COMM_CLR_NEWDAT      IF_COMM_TXRQST
#define IF_COMM_DATAA           BIT(1)
#define IF_COMM_DATAB           BIT(0)

/* TX buffer setup */
#define IF_COMM_TX              (IF_COMM_ARB | IF_COMM_CONTROL | \
                                 IF_COMM_TXRQST |                \
                                 IF_COMM_DATAA | IF_COMM_DATAB)

/* For the low buffers we clear the interrupt bit, but keep newdat */
#define IF_COMM_RCV_LOW         (IF_COMM_MASK | IF_COMM_ARB | \
                                 IF_COMM_CONTROL | IF_COMM_CLR_INT_PND | \
                                 IF_COMM_DATAA | IF_COMM_DATAB)

/* For the high buffers we clear the interrupt bit and newdat */
#define IF_COMM_RCV_HIGH        (IF_COMM_RCV_LOW | IF_COMM_CLR_NEWDAT)

/* Receive setup of message objects */
#define IF_COMM_RCV_SETUP       (IF_COMM_MASK | IF_COMM_ARB | IF_COMM_CONTROL)

/* Invalidation of message objects */
#define IF_COMM_INVAL           (IF_COMM_ARB | IF_COMM_CONTROL)

/* IFx arbitration */
#define IF_ARB_MSGVAL           BIT(31)
#define IF_ARB_MSGXTD           BIT(30)
#define IF_ARB_TRANSMIT         BIT(29)

/* IFx message control */
#define IF_MCONT_NEWDAT         BIT(15)
#define IF_MCONT_MSGLST         BIT(14)
#define IF_MCONT_INTPND         BIT(13)
#define IF_MCONT_UMASK          BIT(12)
#define IF_MCONT_TXIE           BIT(11)
#define IF_MCONT_RXIE           BIT(10)
#define IF_MCONT_RMTEN          BIT(9)
#define IF_MCONT_TXRQST         BIT(8)
#define IF_MCONT_EOB            BIT(7)
#define IF_MCONT_DLC_MASK       0xf

#define IF_MCONT_RCV            (IF_MCONT_RXIE | IF_MCONT_UMASK)
#define IF_MCONT_RCV_EOB        (IF_MCONT_RCV | IF_MCONT_EOB)

#define IF_MCONT_TX             (IF_MCONT_TXIE | IF_MCONT_EOB)

/* Use IF1 in NAPI path and IF2 in TX path */
#define IF_NAPI                 0
#define IF_TX                   1

/* minimum timeout for checking BUSY status */
#define MIN_TIMEOUT_VALUE       6

/* Wait for ~1 sec for INIT bit */
#define INIT_WAIT_MS            1000

/* c_can lec values */
enum c_can_lec_type {
        LEC_NO_ERROR = 0,
        LEC_STUFF_ERROR,
        LEC_FORM_ERROR,
        LEC_ACK_ERROR,
        LEC_BIT1_ERROR,
        LEC_BIT0_ERROR,
        LEC_CRC_ERROR,
        LEC_UNUSED,
        LEC_MASK = LEC_UNUSED,
};

/* c_can error types:
 * Bus errors (BUS_OFF, ERROR_WARNING, ERROR_PASSIVE) are supported
 */
enum c_can_bus_error_types {
        C_CAN_NO_ERROR = 0,
        C_CAN_BUS_OFF,
        C_CAN_ERROR_WARNING,
        C_CAN_ERROR_PASSIVE,
};

static const struct can_bittiming_const c_can_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 = 1024,        /* 6-bit BRP field + 4-bit BRPE field*/
        .brp_inc = 1,
};

static inline void c_can_pm_runtime_get_sync(const struct c_can_priv *priv)
{
        if (priv->device)
                pm_runtime_get_sync(priv->device);
}

static inline void c_can_pm_runtime_put_sync(const struct c_can_priv *priv)
{
        if (priv->device)
                pm_runtime_put_sync(priv->device);
}

static inline void c_can_reset_ram(const struct c_can_priv *priv, bool enable)
{
        if (priv->raminit)
                priv->raminit(priv, enable);
}

static void c_can_irq_control(struct c_can_priv *priv, bool enable)
{
        u32 ctrl = priv->read_reg(priv, C_CAN_CTRL_REG) & ~CONTROL_IRQMSK;

        if (enable)
                ctrl |= CONTROL_IRQMSK;

        priv->write_reg(priv, C_CAN_CTRL_REG, ctrl);
}

static void c_can_obj_update(struct net_device *dev, int iface, u32 cmd, u32 obj)
{
        struct c_can_priv *priv = netdev_priv(dev);
        int cnt, reg = C_CAN_IFACE(COMREQ_REG, iface);

        priv->write_reg32(priv, reg, (cmd << 16) | obj);

        for (cnt = MIN_TIMEOUT_VALUE; cnt; cnt--) {
                if (!(priv->read_reg(priv, reg) & IF_COMR_BUSY))
                        return;
                udelay(1);
        }
        netdev_err(dev, "Updating object timed out\n");
}

static inline void c_can_object_get(struct net_device *dev, int iface,
                                    u32 obj, u32 cmd)
{
        c_can_obj_update(dev, iface, cmd, obj);
}

static inline void c_can_object_put(struct net_device *dev, int iface,
                                    u32 obj, u32 cmd)
{
        c_can_obj_update(dev, iface, cmd | IF_COMM_WR, obj);
}

/* Note: According to documentation clearing TXIE while MSGVAL is set
 * is not allowed, but works nicely on C/DCAN. And that lowers the I/O
 * load significantly.
 */
static void c_can_inval_tx_object(struct net_device *dev, int iface, int obj)
{
        struct c_can_priv *priv = netdev_priv(dev);

        priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), 0);
        c_can_object_put(dev, iface, obj, IF_COMM_INVAL);
}

static void c_can_inval_msg_object(struct net_device *dev, int iface, int obj)
{
        struct c_can_priv *priv = netdev_priv(dev);

        priv->write_reg32(priv, C_CAN_IFACE(ARB1_REG, iface), 0);
        c_can_inval_tx_object(dev, iface, obj);
}

static void c_can_setup_tx_object(struct net_device *dev, int iface,
                                  struct can_frame *frame, int idx)
{
        struct c_can_priv *priv = netdev_priv(dev);
        u16 ctrl = IF_MCONT_TX | frame->len;
        bool rtr = frame->can_id & CAN_RTR_FLAG;
        u32 arb = IF_ARB_MSGVAL;
        int i;

        if (frame->can_id & CAN_EFF_FLAG) {
                arb |= frame->can_id & CAN_EFF_MASK;
                arb |= IF_ARB_MSGXTD;
        } else {
                arb |= (frame->can_id & CAN_SFF_MASK) << 18;
        }

        if (!rtr)
                arb |= IF_ARB_TRANSMIT;

        /* If we change the DIR bit, we need to invalidate the buffer
         * first, i.e. clear the MSGVAL flag in the arbiter.
         */
        if (rtr != (bool)test_bit(idx, &priv->tx_dir)) {
                u32 obj = idx + priv->msg_obj_tx_first;

                c_can_inval_msg_object(dev, iface, obj);
                change_bit(idx, &priv->tx_dir);
        }

        priv->write_reg32(priv, C_CAN_IFACE(ARB1_REG, iface), arb);

        priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl);

        if (priv->type == BOSCH_D_CAN) {
                u32 data = 0, dreg = C_CAN_IFACE(DATA1_REG, iface);

                for (i = 0; i < frame->len; i += 4, dreg += 2) {
                        data = (u32)frame->data[i];
                        data |= (u32)frame->data[i + 1] << 8;
                        data |= (u32)frame->data[i + 2] << 16;
                        data |= (u32)frame->data[i + 3] << 24;
                        priv->write_reg32(priv, dreg, data);
                }
        } else {
                for (i = 0; i < frame->len; i += 2) {
                        priv->write_reg(priv,
                                        C_CAN_IFACE(DATA1_REG, iface) + i / 2,
                                        frame->data[i] |
                                        (frame->data[i + 1] << 8));
                }
        }
}

static int c_can_handle_lost_msg_obj(struct net_device *dev,
                                     int iface, int objno, u32 ctrl)
{
        struct net_device_stats *stats = &dev->stats;
        struct c_can_priv *priv = netdev_priv(dev);
        struct can_frame *frame;
        struct sk_buff *skb;

        ctrl &= ~(IF_MCONT_MSGLST | IF_MCONT_INTPND | IF_MCONT_NEWDAT);
        priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl);
        c_can_object_put(dev, iface, objno, IF_COMM_CONTROL);

        stats->rx_errors++;
        stats->rx_over_errors++;

        /* create an error msg */
        skb = alloc_can_err_skb(dev, &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 c_can_read_msg_object(struct net_device *dev, int iface, u32 ctrl)
{
        struct net_device_stats *stats = &dev->stats;
        struct c_can_priv *priv = netdev_priv(dev);
        struct can_frame *frame;
        struct sk_buff *skb;
        u32 arb, data;

        skb = alloc_can_skb(dev, &frame);
        if (!skb) {
                stats->rx_dropped++;
                return -ENOMEM;
        }

        frame->len = can_cc_dlc2len(ctrl & 0x0F);

        arb = priv->read_reg32(priv, C_CAN_IFACE(ARB1_REG, iface));

        if (arb & IF_ARB_MSGXTD)
                frame->can_id = (arb & CAN_EFF_MASK) | CAN_EFF_FLAG;
        else
                frame->can_id = (arb >> 18) & CAN_SFF_MASK;

        if (arb & IF_ARB_TRANSMIT) {
                frame->can_id |= CAN_RTR_FLAG;
        } else {
                int i, dreg = C_CAN_IFACE(DATA1_REG, iface);

                if (priv->type == BOSCH_D_CAN) {
                        for (i = 0; i < frame->len; i += 4, dreg += 2) {
                                data = priv->read_reg32(priv, dreg);
                                frame->data[i] = data;
                                frame->data[i + 1] = data >> 8;
                                frame->data[i + 2] = data >> 16;
                                frame->data[i + 3] = data >> 24;
                        }
                } else {
                        for (i = 0; i < frame->len; i += 2, dreg++) {
                                data = priv->read_reg(priv, dreg);
                                frame->data[i] = data;
                                frame->data[i + 1] = data >> 8;
                        }
                }

                stats->rx_bytes += frame->len;
        }
        stats->rx_packets++;

        netif_receive_skb(skb);
        return 0;
}

static void c_can_setup_receive_object(struct net_device *dev, int iface,
                                       u32 obj, u32 mask, u32 id, u32 mcont)
{
        struct c_can_priv *priv = netdev_priv(dev);

        mask |= BIT(29);
        priv->write_reg32(priv, C_CAN_IFACE(MASK1_REG, iface), mask);

        id |= IF_ARB_MSGVAL;
        priv->write_reg32(priv, C_CAN_IFACE(ARB1_REG, iface), id);

        priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), mcont);
        c_can_object_put(dev, iface, obj, IF_COMM_RCV_SETUP);
}

static bool c_can_tx_busy(const struct c_can_priv *priv,
                          const struct c_can_tx_ring *tx_ring)
{
        if (c_can_get_tx_free(priv, tx_ring) > 0)
                return false;

        netif_stop_queue(priv->dev);

        /* Memory barrier before checking tx_free (head and tail) */
        smp_mb();

        if (c_can_get_tx_free(priv, tx_ring) == 0) {
                netdev_dbg(priv->dev,
                           "Stopping tx-queue (tx_head=0x%08x, tx_tail=0x%08x, len=%d).\n",
                           tx_ring->head, tx_ring->tail,
                           tx_ring->head - tx_ring->tail);
                return true;
        }

        netif_start_queue(priv->dev);
        return false;
}

static netdev_tx_t c_can_start_xmit(struct sk_buff *skb,
                                    struct net_device *dev)
{
        struct can_frame *frame = (struct can_frame *)skb->data;
        struct c_can_priv *priv = netdev_priv(dev);
        struct c_can_tx_ring *tx_ring = &priv->tx;
        u32 idx, obj, cmd = IF_COMM_TX;

        if (can_dev_dropped_skb(dev, skb))
                return NETDEV_TX_OK;

        if (c_can_tx_busy(priv, tx_ring))
                return NETDEV_TX_BUSY;

        idx = c_can_get_tx_head(tx_ring);
        tx_ring->head++;
        if (c_can_get_tx_free(priv, tx_ring) == 0)
                netif_stop_queue(dev);

        if (idx < c_can_get_tx_tail(tx_ring))
                cmd &= ~IF_COMM_TXRQST; /* Cache the message */

        /* Store the message in the interface so we can call
         * can_put_echo_skb(). We must do this before we enable
         * transmit as we might race against do_tx().
         */
        c_can_setup_tx_object(dev, IF_TX, frame, idx);
        can_put_echo_skb(skb, dev, idx, 0);
        obj = idx + priv->msg_obj_tx_first;
        c_can_object_put(dev, IF_TX, obj, cmd);

        return NETDEV_TX_OK;
}

static int c_can_wait_for_ctrl_init(struct net_device *dev,
                                    struct c_can_priv *priv, u32 init)
{
        int retry = 0;

        while (init != (priv->read_reg(priv, C_CAN_CTRL_REG) & CONTROL_INIT)) {
                udelay(10);
                if (retry++ > 1000) {
                        netdev_err(dev, "CCTRL: set CONTROL_INIT failed\n");
                        return -EIO;
                }
        }
        return 0;
}

static int c_can_set_bittiming(struct net_device *dev)
{
        unsigned int reg_btr, reg_brpe, ctrl_save;
        u8 brp, brpe, sjw, tseg1, tseg2;
        u32 ten_bit_brp;
        struct c_can_priv *priv = netdev_priv(dev);
        const struct can_bittiming *bt = &priv->can.bittiming;
        int res;

        /* c_can provides a 6-bit brp and 4-bit brpe fields */
        ten_bit_brp = bt->brp - 1;
        brp = ten_bit_brp & BTR_BRP_MASK;
        brpe = ten_bit_brp >> 6;

        sjw = bt->sjw - 1;
        tseg1 = bt->prop_seg + bt->phase_seg1 - 1;
        tseg2 = bt->phase_seg2 - 1;
        reg_btr = brp | (sjw << BTR_SJW_SHIFT) | (tseg1 << BTR_TSEG1_SHIFT) |
                        (tseg2 << BTR_TSEG2_SHIFT);
        reg_brpe = brpe & BRP_EXT_BRPE_MASK;

        netdev_info(dev,
                    "setting BTR=%04x BRPE=%04x\n", reg_btr, reg_brpe);

        ctrl_save = priv->read_reg(priv, C_CAN_CTRL_REG);
        ctrl_save &= ~CONTROL_INIT;
        priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_CCE | CONTROL_INIT);
        res = c_can_wait_for_ctrl_init(dev, priv, CONTROL_INIT);
        if (res)
                return res;

        priv->write_reg(priv, C_CAN_BTR_REG, reg_btr);
        priv->write_reg(priv, C_CAN_BRPEXT_REG, reg_brpe);
        priv->write_reg(priv, C_CAN_CTRL_REG, ctrl_save);

        return c_can_wait_for_ctrl_init(dev, priv, 0);
}

/* Configure C_CAN message objects for Tx and Rx purposes:
 * C_CAN provides a total of 32 message objects that can be configured
 * either for Tx or Rx purposes. Here the first 16 message objects are used as
 * a reception FIFO. The end of reception FIFO is signified by the EoB bit
 * being SET. The remaining 16 message objects are kept aside for Tx purposes.
 * See user guide document for further details on configuring message
 * objects.
 */
static void c_can_configure_msg_objects(struct net_device *dev)
{
        struct c_can_priv *priv = netdev_priv(dev);
        int i;

        /* first invalidate all message objects */
        for (i = priv->msg_obj_rx_first; i <= priv->msg_obj_num; i++)
                c_can_inval_msg_object(dev, IF_NAPI, i);

        /* setup receive message objects */
        for (i = priv->msg_obj_rx_first; i < priv->msg_obj_rx_last; i++)
                c_can_setup_receive_object(dev, IF_NAPI, i, 0, 0, IF_MCONT_RCV);

        c_can_setup_receive_object(dev, IF_NAPI, priv->msg_obj_rx_last, 0, 0,
                                   IF_MCONT_RCV_EOB);
}

static int c_can_software_reset(struct net_device *dev)
{
        struct c_can_priv *priv = netdev_priv(dev);
        int retry = 0;

        if (priv->type != BOSCH_D_CAN)
                return 0;

        priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_SWR | CONTROL_INIT);
        while (priv->read_reg(priv, C_CAN_CTRL_REG) & CONTROL_SWR) {
                msleep(20);
                if (retry++ > 100) {
                        netdev_err(dev, "CCTRL: software reset failed\n");
                        return -EIO;
                }
        }

        return 0;
}

/* Configure C_CAN chip:
 * - enable/disable auto-retransmission
 * - set operating mode
 * - configure message objects
 */
static int c_can_chip_config(struct net_device *dev)
{
        struct c_can_priv *priv = netdev_priv(dev);
        struct c_can_tx_ring *tx_ring = &priv->tx;
        int err;

        err = c_can_software_reset(dev);
        if (err)
                return err;

        /* enable automatic retransmission */
        priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_ENABLE_AR);

        if ((priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) &&
            (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)) {
                /* loopback + silent mode : useful for hot self-test */
                priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST);
                priv->write_reg(priv, C_CAN_TEST_REG, TEST_LBACK | TEST_SILENT);
        } else if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
                /* loopback mode : useful for self-test function */
                priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST);
                priv->write_reg(priv, C_CAN_TEST_REG, TEST_LBACK);
        } else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) {
                /* silent mode : bus-monitoring mode */
                priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST);
                priv->write_reg(priv, C_CAN_TEST_REG, TEST_SILENT);
        }

        /* configure message objects */
        c_can_configure_msg_objects(dev);

        /* set a `lec` value so that we can check for updates later */
        priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED);

        /* Clear all internal status */
        tx_ring->head = 0;
        tx_ring->tail = 0;
        priv->tx_dir = 0;

        /* set bittiming params */
        return c_can_set_bittiming(dev);
}

static int c_can_start(struct net_device *dev)
{
        struct c_can_priv *priv = netdev_priv(dev);
        int err;
        struct pinctrl *p;

        /* basic c_can configuration */
        err = c_can_chip_config(dev);
        if (err)
                return err;

        /* Setup the command for new messages */
        priv->comm_rcv_high = priv->type != BOSCH_D_CAN ?
                IF_COMM_RCV_LOW : IF_COMM_RCV_HIGH;

        priv->can.state = CAN_STATE_ERROR_ACTIVE;

        /* Attempt to use "active" if available else use "default" */
        p = pinctrl_get_select(priv->device, "active");
        if (!IS_ERR(p))
                pinctrl_put(p);
        else
                pinctrl_pm_select_default_state(priv->device);

        return 0;
}

static void c_can_stop(struct net_device *dev)
{
        struct c_can_priv *priv = netdev_priv(dev);

        c_can_irq_control(priv, false);

        /* put ctrl to init on stop to end ongoing transmission */
        priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_INIT);

        /* deactivate pins */
        pinctrl_pm_select_sleep_state(dev->dev.parent);
        priv->can.state = CAN_STATE_STOPPED;
}

static int c_can_set_mode(struct net_device *dev, enum can_mode mode)
{
        struct c_can_priv *priv = netdev_priv(dev);
        int err;

        switch (mode) {
        case CAN_MODE_START:
                err = c_can_start(dev);
                if (err)
                        return err;
                netif_wake_queue(dev);
                c_can_irq_control(priv, true);
                break;
        default:
                return -EOPNOTSUPP;
        }

        return 0;
}

static int __c_can_get_berr_counter(const struct net_device *dev,
                                    struct can_berr_counter *bec)
{
        unsigned int reg_err_counter;
        struct c_can_priv *priv = netdev_priv(dev);

        reg_err_counter = priv->read_reg(priv, C_CAN_ERR_CNT_REG);
        bec->rxerr = (reg_err_counter & ERR_CNT_REC_MASK) >>
                                ERR_CNT_REC_SHIFT;
        bec->txerr = reg_err_counter & ERR_CNT_TEC_MASK;

        return 0;
}

static int c_can_get_berr_counter(const struct net_device *dev,
                                  struct can_berr_counter *bec)
{
        struct c_can_priv *priv = netdev_priv(dev);
        int err;

        c_can_pm_runtime_get_sync(priv);
        err = __c_can_get_berr_counter(dev, bec);
        c_can_pm_runtime_put_sync(priv);

        return err;
}

static void c_can_do_tx(struct net_device *dev)
{
        struct c_can_priv *priv = netdev_priv(dev);
        struct c_can_tx_ring *tx_ring = &priv->tx;
        struct net_device_stats *stats = &dev->stats;
        u32 idx, obj, pkts = 0, bytes = 0, pend;
        u8 tail;

        if (priv->msg_obj_tx_last > 32)
                pend = priv->read_reg32(priv, C_CAN_INTPND3_REG);
        else
                pend = priv->read_reg(priv, C_CAN_INTPND2_REG);

        while ((idx = ffs(pend))) {
                idx--;
                pend &= ~BIT(idx);
                obj = idx + priv->msg_obj_tx_first;

                /* We use IF_NAPI interface instead of IF_TX because we
                 * are called from c_can_poll(), which runs inside
                 * NAPI. We are not transmitting.
                 */
                c_can_inval_tx_object(dev, IF_NAPI, obj);
                bytes += can_get_echo_skb(dev, idx, NULL);
                pkts++;
        }

        if (!pkts)
                return;

        tx_ring->tail += pkts;
        if (c_can_get_tx_free(priv, tx_ring)) {
                /* Make sure that anybody stopping the queue after
                 * this sees the new tx_ring->tail.
                 */
                smp_mb();
                netif_wake_queue(priv->dev);
        }

        stats->tx_bytes += bytes;
        stats->tx_packets += pkts;

        tail = c_can_get_tx_tail(tx_ring);
        if (priv->type == BOSCH_D_CAN && tail == 0) {
                u8 head = c_can_get_tx_head(tx_ring);

                /* Start transmission for all cached messages */
                for (idx = tail; idx < head; idx++) {
                        obj = idx + priv->msg_obj_tx_first;
                        c_can_object_put(dev, IF_NAPI, obj, IF_COMM_TXRQST);
                }
        }
}

/* If we have a gap in the pending bits, that means we either
 * raced with the hardware or failed to readout all upper
 * objects in the last run due to quota limit.
 */
static u32 c_can_adjust_pending(u32 pend, u32 rx_mask)
{
        u32 weight, lasts;

        if (pend == rx_mask)
                return pend;

        /* If the last set bit is larger than the number of pending
         * bits we have a gap.
         */
        weight = hweight32(pend);
        lasts = fls(pend);

        /* If the bits are linear, nothing to do */
        if (lasts == weight)
                return pend;

        /* Find the first set bit after the gap. We walk backwards
         * from the last set bit.
         */
        for (lasts--; pend & BIT(lasts - 1); lasts--)
                ;

        return pend & ~GENMASK(lasts - 1, 0);
}

static inline void c_can_rx_object_get(struct net_device *dev,
                                       struct c_can_priv *priv, u32 obj)
{
        c_can_object_get(dev, IF_NAPI, obj, priv->comm_rcv_high);
}

static inline void c_can_rx_finalize(struct net_device *dev,
                                     struct c_can_priv *priv, u32 obj)
{
        if (priv->type != BOSCH_D_CAN)
                c_can_object_get(dev, IF_NAPI, obj, IF_COMM_CLR_NEWDAT);
}

static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv,
                              u32 pend, int quota)
{
        u32 pkts = 0, ctrl, obj;

        while ((obj = ffs(pend)) && quota > 0) {
                pend &= ~BIT(obj - 1);

                c_can_rx_object_get(dev, priv, obj);
                ctrl = priv->read_reg(priv, C_CAN_IFACE(MSGCTRL_REG, IF_NAPI));

                if (ctrl & IF_MCONT_MSGLST) {
                        int n;

                        n = c_can_handle_lost_msg_obj(dev, IF_NAPI, obj, ctrl);

                        pkts += n;
                        quota -= n;
                        continue;
                }

                /* This really should not happen, but this covers some
                 * odd HW behaviour. Do not remove that unless you
                 * want to brick your machine.
                 */
                if (!(ctrl & IF_MCONT_NEWDAT))
                        continue;

                /* read the data from the message object */
                c_can_read_msg_object(dev, IF_NAPI, ctrl);

                c_can_rx_finalize(dev, priv, obj);

                pkts++;
                quota--;
        }

        return pkts;
}

static inline u32 c_can_get_pending(struct c_can_priv *priv)
{
        u32 pend;

        if (priv->msg_obj_rx_last > 16)
                pend = priv->read_reg32(priv, C_CAN_NEWDAT1_REG);
        else
                pend = priv->read_reg(priv, C_CAN_NEWDAT1_REG);

        return pend;
}

/* theory of operation:
 *
 * c_can core saves a received CAN message into the first free message
 * object it finds free (starting with the lowest). Bits NEWDAT and
 * INTPND are set for this message object indicating that a new message
 * has arrived.
 *
 * We clear the newdat bit right away.
 *
 * This can result in packet reordering when the readout is slow.
 */
static int c_can_do_rx_poll(struct net_device *dev, int quota)
{
        struct c_can_priv *priv = netdev_priv(dev);
        u32 pkts = 0, pend = 0, toread, n;

        while (quota > 0) {
                if (!pend) {
                        pend = c_can_get_pending(priv);
                        if (!pend)
                                break;
                        /* If the pending field has a gap, handle the
                         * bits above the gap first.
                         */
                        toread = c_can_adjust_pending(pend,
                                                      priv->msg_obj_rx_mask);
                } else {
                        toread = pend;
                }
                /* Remove the bits from pend */
                pend &= ~toread;
                /* Read the objects */
                n = c_can_read_objects(dev, priv, toread, quota);
                pkts += n;
                quota -= n;
        }

        return pkts;
}

static int c_can_handle_state_change(struct net_device *dev,
                                     enum c_can_bus_error_types error_type)
{
        unsigned int reg_err_counter;
        unsigned int rx_err_passive;
        struct c_can_priv *priv = netdev_priv(dev);
        struct can_frame *cf;
        struct sk_buff *skb;
        struct can_berr_counter bec;

        switch (error_type) {
        case C_CAN_NO_ERROR:
                priv->can.state = CAN_STATE_ERROR_ACTIVE;
                break;
        case C_CAN_ERROR_WARNING:
                /* error warning state */
                priv->can.can_stats.error_warning++;
                priv->can.state = CAN_STATE_ERROR_WARNING;
                break;
        case C_CAN_ERROR_PASSIVE:
                /* error passive state */
                priv->can.can_stats.error_passive++;
                priv->can.state = CAN_STATE_ERROR_PASSIVE;
                break;
        case C_CAN_BUS_OFF:
                /* bus-off state */
                priv->can.state = CAN_STATE_BUS_OFF;
                priv->can.can_stats.bus_off++;
                break;
        default:
                break;
        }

        /* propagate the error condition to the CAN stack */
        skb = alloc_can_err_skb(dev, &cf);
        if (unlikely(!skb))
                return 0;

        __c_can_get_berr_counter(dev, &bec);
        reg_err_counter = priv->read_reg(priv, C_CAN_ERR_CNT_REG);
        rx_err_passive = (reg_err_counter & ERR_CNT_RP_MASK) >>
                                ERR_CNT_RP_SHIFT;

        switch (error_type) {
        case C_CAN_NO_ERROR:
                cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT;
                cf->data[1] = CAN_ERR_CRTL_ACTIVE;
                cf->data[6] = bec.txerr;
                cf->data[7] = bec.rxerr;
                break;
        case C_CAN_ERROR_WARNING:
                /* error warning state */
                cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT;
                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 C_CAN_ERROR_PASSIVE:
                /* error passive state */
                cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT;
                if (rx_err_passive)
                        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 C_CAN_BUS_OFF:
                /* bus-off state */
                cf->can_id |= CAN_ERR_BUSOFF;
                can_bus_off(dev);
                break;
        default:
                break;
        }

        netif_receive_skb(skb);

        return 1;
}

static int c_can_handle_bus_err(struct net_device *dev,
                                enum c_can_lec_type lec_type)
{
        struct c_can_priv *priv = netdev_priv(dev);
        struct net_device_stats *stats = &dev->stats;
        struct can_frame *cf;
        struct sk_buff *skb;

        /* early exit if no lec update or no error.
         * no lec update means that no CAN bus event has been detected
         * since CPU wrote 0x7 value to status reg.
         */
        if (lec_type == LEC_UNUSED || lec_type == LEC_NO_ERROR)
                return 0;

        if (!(priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING))
                return 0;

        /* common for all type of bus errors */
        priv->can.can_stats.bus_error++;

        /* propagate the error condition to the CAN stack */
        skb = alloc_can_err_skb(dev, &cf);

        /* check for 'last error code' which tells us the
         * type of the last error to occur on the CAN bus
         */
        if (likely(skb))
                cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;

        switch (lec_type) {
        case LEC_STUFF_ERROR:
                netdev_dbg(dev, "stuff error\n");
                if (likely(skb))
                        cf->data[2] |= CAN_ERR_PROT_STUFF;
                stats->rx_errors++;
                break;
        case LEC_FORM_ERROR:
                netdev_dbg(dev, "form error\n");
                if (likely(skb))
                        cf->data[2] |= CAN_ERR_PROT_FORM;
                stats->rx_errors++;
                break;
        case LEC_ACK_ERROR:
                netdev_dbg(dev, "ack error\n");
                if (likely(skb))
                        cf->data[3] = CAN_ERR_PROT_LOC_ACK;
                stats->tx_errors++;
                break;
        case LEC_BIT1_ERROR:
                netdev_dbg(dev, "bit1 error\n");
                if (likely(skb))
                        cf->data[2] |= CAN_ERR_PROT_BIT1;
                stats->tx_errors++;
                break;
        case LEC_BIT0_ERROR:
                netdev_dbg(dev, "bit0 error\n");
                if (likely(skb))
                        cf->data[2] |= CAN_ERR_PROT_BIT0;
                stats->tx_errors++;
                break;
        case LEC_CRC_ERROR:
                netdev_dbg(dev, "CRC error\n");
                if (likely(skb))
                        cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
                stats->rx_errors++;
                break;
        default:
                break;
        }

        if (unlikely(!skb))
                return 0;

        netif_receive_skb(skb);
        return 1;
}

static int c_can_poll(struct napi_struct *napi, int quota)
{
        struct net_device *dev = napi->dev;
        struct c_can_priv *priv = netdev_priv(dev);
        u16 curr, last = priv->last_status;
        int work_done = 0;

        /* Only read the status register if a status interrupt was pending */
        if (atomic_xchg(&priv->sie_pending, 0)) {
                priv->last_status = priv->read_reg(priv, C_CAN_STS_REG);
                curr = priv->last_status;
                /* Ack status on C_CAN. D_CAN is self clearing */
                if (priv->type != BOSCH_D_CAN)
                        priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED);
        } else {
                /* no change detected ... */
                curr = last;
        }

        /* handle state changes */
        if ((curr & STATUS_EWARN) && (!(last & STATUS_EWARN))) {
                netdev_dbg(dev, "entered error warning state\n");
                work_done += c_can_handle_state_change(dev, C_CAN_ERROR_WARNING);
        }

        if ((curr & STATUS_EPASS) && (!(last & STATUS_EPASS))) {
                netdev_dbg(dev, "entered error passive state\n");
                work_done += c_can_handle_state_change(dev, C_CAN_ERROR_PASSIVE);
        }

        if ((curr & STATUS_BOFF) && (!(last & STATUS_BOFF))) {
                netdev_dbg(dev, "entered bus off state\n");
                work_done += c_can_handle_state_change(dev, C_CAN_BUS_OFF);
                goto end;
        }

        /* handle bus recovery events */
        if ((!(curr & STATUS_BOFF)) && (last & STATUS_BOFF)) {
                netdev_dbg(dev, "left bus off state\n");
                work_done += c_can_handle_state_change(dev, C_CAN_ERROR_PASSIVE);
        }

        if ((!(curr & STATUS_EPASS)) && (last & STATUS_EPASS)) {
                netdev_dbg(dev, "left error passive state\n");
                work_done += c_can_handle_state_change(dev, C_CAN_ERROR_WARNING);
        }

        if ((!(curr & STATUS_EWARN)) && (last & STATUS_EWARN)) {
                netdev_dbg(dev, "left error warning state\n");
                work_done += c_can_handle_state_change(dev, C_CAN_NO_ERROR);
        }

        /* handle lec errors on the bus */
        work_done += c_can_handle_bus_err(dev, curr & LEC_MASK);

        /* Handle Tx/Rx events. We do this unconditionally */
        work_done += c_can_do_rx_poll(dev, (quota - work_done));
        c_can_do_tx(dev);

end:
        if (work_done < quota) {
                napi_complete_done(napi, work_done);
                /* enable all IRQs if we are not in bus off state */
                if (priv->can.state != CAN_STATE_BUS_OFF)
                        c_can_irq_control(priv, true);
        }

        return work_done;
}

static irqreturn_t c_can_isr(int irq, void *dev_id)
{
        struct net_device *dev = (struct net_device *)dev_id;
        struct c_can_priv *priv = netdev_priv(dev);
        int reg_int;

        reg_int = priv->read_reg(priv, C_CAN_INT_REG);
        if (!reg_int)
                return IRQ_NONE;

        /* save for later use */
        if (reg_int & INT_STS_PENDING)
                atomic_set(&priv->sie_pending, 1);

        /* disable all interrupts and schedule the NAPI */
        c_can_irq_control(priv, false);
        napi_schedule(&priv->napi);

        return IRQ_HANDLED;
}

static int c_can_open(struct net_device *dev)
{
        int err;
        struct c_can_priv *priv = netdev_priv(dev);

        c_can_pm_runtime_get_sync(priv);
        c_can_reset_ram(priv, true);

        /* open the can device */
        err = open_candev(dev);
        if (err) {
                netdev_err(dev, "failed to open can device\n");
                goto exit_open_fail;
        }

        /* register interrupt handler */
        err = request_irq(dev->irq, &c_can_isr, IRQF_SHARED, dev->name,
                          dev);
        if (err < 0) {
                netdev_err(dev, "failed to request interrupt\n");
                goto exit_irq_fail;
        }

        /* start the c_can controller */
        err = c_can_start(dev);
        if (err)
                goto exit_start_fail;

        napi_enable(&priv->napi);
        /* enable status change, error and module interrupts */
        c_can_irq_control(priv, true);
        netif_start_queue(dev);

        return 0;

exit_start_fail:
        free_irq(dev->irq, dev);
exit_irq_fail:
        close_candev(dev);
exit_open_fail:
        c_can_reset_ram(priv, false);
        c_can_pm_runtime_put_sync(priv);
        return err;
}

static int c_can_close(struct net_device *dev)
{
        struct c_can_priv *priv = netdev_priv(dev);

        netif_stop_queue(dev);
        napi_disable(&priv->napi);
        c_can_stop(dev);
        free_irq(dev->irq, dev);
        close_candev(dev);

        c_can_reset_ram(priv, false);
        c_can_pm_runtime_put_sync(priv);

        return 0;
}

struct net_device *alloc_c_can_dev(int msg_obj_num)
{
        struct net_device *dev;
        struct c_can_priv *priv;
        int msg_obj_tx_num = msg_obj_num / 2;

        dev = alloc_candev(sizeof(*priv), msg_obj_tx_num);
        if (!dev)
                return NULL;

        priv = netdev_priv(dev);
        priv->msg_obj_num = msg_obj_num;
        priv->msg_obj_rx_num = msg_obj_num - msg_obj_tx_num;
        priv->msg_obj_rx_first = 1;
        priv->msg_obj_rx_last =
                priv->msg_obj_rx_first + priv->msg_obj_rx_num - 1;
        priv->msg_obj_rx_mask = GENMASK(priv->msg_obj_rx_num - 1, 0);

        priv->msg_obj_tx_num = msg_obj_tx_num;
        priv->msg_obj_tx_first = priv->msg_obj_rx_last + 1;
        priv->msg_obj_tx_last =
                priv->msg_obj_tx_first + priv->msg_obj_tx_num - 1;

        priv->tx.head = 0;
        priv->tx.tail = 0;
        priv->tx.obj_num = msg_obj_tx_num;

        netif_napi_add_weight(dev, &priv->napi, c_can_poll,
                              priv->msg_obj_rx_num);

        priv->dev = dev;
        priv->can.bittiming_const = &c_can_bittiming_const;
        priv->can.do_set_mode = c_can_set_mode;
        priv->can.do_get_berr_counter = c_can_get_berr_counter;
        priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
                                        CAN_CTRLMODE_LISTENONLY |
                                        CAN_CTRLMODE_BERR_REPORTING;

        return dev;
}
EXPORT_SYMBOL_GPL(alloc_c_can_dev);

#ifdef CONFIG_PM
int c_can_power_down(struct net_device *dev)
{
        u32 val;
        unsigned long time_out;
        struct c_can_priv *priv = netdev_priv(dev);

        if (!(dev->flags & IFF_UP))
                return 0;

        WARN_ON(priv->type != BOSCH_D_CAN);

        /* set PDR value so the device goes to power down mode */
        val = priv->read_reg(priv, C_CAN_CTRL_EX_REG);
        val |= CONTROL_EX_PDR;
        priv->write_reg(priv, C_CAN_CTRL_EX_REG, val);

        /* Wait for the PDA bit to get set */
        time_out = jiffies + msecs_to_jiffies(INIT_WAIT_MS);
        while (!(priv->read_reg(priv, C_CAN_STS_REG) & STATUS_PDA) &&
               time_after(time_out, jiffies))
                cpu_relax();

        if (time_after(jiffies, time_out))
                return -ETIMEDOUT;

        c_can_stop(dev);

        c_can_reset_ram(priv, false);
        c_can_pm_runtime_put_sync(priv);

        return 0;
}
EXPORT_SYMBOL_GPL(c_can_power_down);

int c_can_power_up(struct net_device *dev)
{
        u32 val;
        unsigned long time_out;
        struct c_can_priv *priv = netdev_priv(dev);
        int ret;

        if (!(dev->flags & IFF_UP))
                return 0;

        WARN_ON(priv->type != BOSCH_D_CAN);

        c_can_pm_runtime_get_sync(priv);
        c_can_reset_ram(priv, true);

        /* Clear PDR and INIT bits */
        val = priv->read_reg(priv, C_CAN_CTRL_EX_REG);
        val &= ~CONTROL_EX_PDR;
        priv->write_reg(priv, C_CAN_CTRL_EX_REG, val);
        val = priv->read_reg(priv, C_CAN_CTRL_REG);
        val &= ~CONTROL_INIT;
        priv->write_reg(priv, C_CAN_CTRL_REG, val);

        /* Wait for the PDA bit to get clear */
        time_out = jiffies + msecs_to_jiffies(INIT_WAIT_MS);
        while ((priv->read_reg(priv, C_CAN_STS_REG) & STATUS_PDA) &&
               time_after(time_out, jiffies))
                cpu_relax();

        if (time_after(jiffies, time_out)) {
                ret = -ETIMEDOUT;
                goto err_out;
        }

        ret = c_can_start(dev);
        if (ret)
                goto err_out;

        c_can_irq_control(priv, true);

        return 0;

err_out:
        c_can_reset_ram(priv, false);
        c_can_pm_runtime_put_sync(priv);

        return ret;
}
EXPORT_SYMBOL_GPL(c_can_power_up);
#endif

void free_c_can_dev(struct net_device *dev)
{
        struct c_can_priv *priv = netdev_priv(dev);

        netif_napi_del(&priv->napi);
        free_candev(dev);
}
EXPORT_SYMBOL_GPL(free_c_can_dev);

static const struct net_device_ops c_can_netdev_ops = {
        .ndo_open = c_can_open,
        .ndo_stop = c_can_close,
        .ndo_start_xmit = c_can_start_xmit,
};

int register_c_can_dev(struct net_device *dev)
{
        /* Deactivate pins to prevent DRA7 DCAN IP from being
         * stuck in transition when module is disabled.
         * Pins are activated in c_can_start() and deactivated
         * in c_can_stop()
         */
        pinctrl_pm_select_sleep_state(dev->dev.parent);

        dev->flags |= IFF_ECHO; /* we support local echo */
        dev->netdev_ops = &c_can_netdev_ops;
        dev->ethtool_ops = &c_can_ethtool_ops;

        return register_candev(dev);
}
EXPORT_SYMBOL_GPL(register_c_can_dev);

void unregister_c_can_dev(struct net_device *dev)
{
        unregister_candev(dev);
}
EXPORT_SYMBOL_GPL(unregister_c_can_dev);

MODULE_AUTHOR("Bhupesh Sharma <bhupesh.sharma@st.com>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("CAN bus driver for Bosch C_CAN controller");