Hello together,
I just started to play with ddelinux... My Goal is to build an d_can driver for l4re.
I tried to collect the important parts from the Makefiles of pkg/anghk and the ddelinux examples to write my own for d_can.

when i Try to build my "puzzle" ;) i get following error: fiasco/src/l4/pkg/d_can/d_can/d_can.c:42:27: fatal error: linux/can/dev.h: No such file or directory
this leads me to the fear that there's no can/dev.h in ddelinux...

My questions at this point are:
-Am I working in the right direction or did I misunderstand the concept of ddelinux?
-If not, what would be the right procedure?


Thanks

Korbinian Ederer


PS: Sorry for the large appendix, but I think it's important for the problem.



my pkg folder structure looks like this:

l4/pkg/d_can:
    -./Control
    -./Makefile
    -d_can/:
        -./d_can.c
        -./d_dcan.h
        -./d_can_platform.c
        -./Kconfig
        -./Makefile


The contents of the files:

l4/pkg/d_can/Control:

provides: d_can
requires: dde-linux26 dde-linux26_net







l4/pkg/d_can/Makefile:


PKGDIR ?= .
L4DIR  ?= $(PKGDIR)/../..

include $(L4DIR)/mk/Makeconf
-include $(PKGDIR_OBJ)/Makeconf

#ifeq ($(CONFIG_DDE26),y)
TARGET = d_can
#endif

include $(L4DIR)/mk/subdir.mk






l4/d_can/d_can/d_can.c:

/*
 * CAN bus driver for Bosch D_CAN controller
 *
 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
 * Anil Kumar Ch <anilkumar@ti.com>
 *
 * Borrowed from C_CAN driver
 * 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>
 *
 * Bosch D_CAN controller is compliant to CAN protocol version 2.0 part A and B.
 * Bosch D_CAN user manual can be obtained from:
 * http://www.semiconductors.bosch.de/media/en/pdf/ipmodules_1/can/
 * d_can_users_manual_111.pdf
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation version 2.
 *
 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
 * kind, whether express or implied; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#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/can.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>

#include "d_can.h"

/* TI D_CAN module registers */
#define D_CAN_CTL        0x0    /* CAN control register */
#define D_CAN_ES        0x4    /* Error and status */
#define D_CAN_PARITYERR_EOI    0x4    /* Parity error EOI */
#define D_CAN_ERRC        0x8    /* Error counter */
#define D_CAN_BTR        0xC    /* Bit timing */
#define D_CAN_INT        0x10    /* Interrupt register */
#define D_CAN_TEST        0x14    /* Test register */
#define D_CAN_PERR        0x1C    /* Parity Error Code */
#define D_CAN_ABOTR        0x80    /* Auto-Bus-On Time */
#define D_CAN_TXRQ_X        0x84    /* Transmission Request X */
#define D_CAN_TXRQ(n)        (0x88 + ((n) * 4)) /* Transmission request */
#define D_CAN_NWDAT_X        0x98    /* New data X register */
#define D_CAN_NWDAT(n)        (0x9C + ((n) * 4)) /* New data */
#define D_CAN_INTPND_X        0xAC    /* Interrupt Pending X */
#define D_CAN_INTPND(n)        (0xB0 + ((n) * 4)) /* Interrupt Pending */
#define D_CAN_MSGVAL_X        0xC0        /* Message Valid X */
#define D_CAN_MSGVAL(n)        (0xC4 + ((n) * 4)) /* Message Valid */
#define D_CAN_INTMUX(n)        (0xD8 + ((n) * 4)) /* Interrupt Multiplexer */
#define D_CAN_IFCMD(n)        (0x100 + ((n) * 0x20)) /* Command */
#define D_CAN_IFMSK(n)        (0x104 + ((n) * 0x20)) /* Mask */
#define D_CAN_IFARB(n)        (0x108 + ((n) * 0x20)) /* Arbitration */
#define D_CAN_IFMCTL(n)        (0x10c + ((n) * 0x20)) /* Message ctl */
#define D_CAN_IFDATA(n)        (0x110 + ((n) * 0x20)) /* DATA A */
#define D_CAN_IFDATB(n)        (0x114 + ((n) * 0x20)) /* DATA B */
#define D_CAN_IF3OBS        0x140    /* IF3 Observation */
#define D_CAN_IF3UPD(n)        (0x160 + ((n) * 4)) /* Update enable */
#define D_CAN_TIOC        0x1E0    /* CAN TX IO Control */
#define D_CAN_RIOC        0x1E4    /* CAN RX IO Control */

/* Control register Bit fields */
#define D_CAN_CTL_WUBA        BIT(26)    /* Automatic wake-up on bus activity */
#define D_CAN_CTL_PDR        BIT(24)    /* Request for local low power mode */
#define D_CAN_CTL_DE3        BIT(20)    /* Enable DMA request line for IF3 */
#define D_CAN_CTL_DE2        BIT(19)    /* Enable DMA request line for IF2 */
#define D_CAN_CTL_DE1        BIT(18)    /* Enable DMA request line for IF1 */
#define D_CAN_CTL_IE1        BIT(17)    /* Interrupt line 1 enable */
#define D_CAN_CTL_INITDBG    BIT(16)    /* Init state for debug access */
#define D_CAN_CTL_SWR        BIT(15)    /* S/W reset enable */
#define D_CAN_CTL_PMD        (0xF << 10)    /* Parity on/off */
#define D_CAN_CTL_ABO        BIT(9)    /* Auto bus on enable */
#define D_CAN_CTL_IDS        BIT(8)    /* Interruption debug support enable */
#define D_CAN_CTL_TEST        BIT(7)    /* Test mode enable */
#define D_CAN_CTL_CCE        BIT(6)    /* Configuration change enable */
#define D_CAN_CTL_DISABLE_AR    BIT(5)    /* Disable automatic retransmission */
#define D_CAN_CTL_ENABLE_AR    (0 << 5)
#define D_CAN_CTL_EIE        BIT(3)    /* Error interrupt enable */
#define D_CAN_CTL_SIE        BIT(2)    /* Status change int enable */
#define D_CAN_CTL_IE0        BIT(1)    /* Interrupt line 0 enable */
#define D_CAN_CTL_INIT        BIT(0)    /* D_CAN initialization mode */

/* D_CAN Error and Status and Parity Error EOI reg bit fields */
#define D_CAN_ES_PDA        BIT(10)    /* Local power-down ACK */
#define D_CAN_ES_WUP        BIT(9)    /* Wkae up pending */
#define D_CAN_ES_PER        BIT(8)    /* Parity error detected */
#define D_CAN_ES_BOFF        BIT(7)    /* Bus off state */
#define D_CAN_ES_EWARN        BIT(6)    /* Warning state */
#define D_CAN_ES_EPASS        BIT(5)    /* Error passive state */
#define D_CAN_ES_RXOK        BIT(4)    /* Received a msg successfully */
#define D_CAN_ES_TXOK        BIT(3)    /* Transmitted a msg successfully */
#define D_CAN_ES_LEC_MASK    0x7    /* Last error code */

/* Parity error reg bit fields */
#define D_CAN_PEEOI        BIT(8)    /* EOI indication for parity error */

/* Error counter reg bit fields */
#define D_CAN_ERRC_RP_SHIFT    15
#define D_CAN_ERRC_RP_MASK    BIT(15)        /* Receive error passive */
#define D_CAN_ERRC_REC_SHIFT    8
#define D_CAN_ERRC_REC_MASK    (0x7F << 8)    /* Receive err counter */
#define D_CAN_ERRC_TEC_SHIFT    0
#define D_CAN_ERRC_TEC_MASK    (0xFF << 0)    /* Transmit err counter */

/* Bit timing reg bit fields */
#define D_CAN_BTR_BRPE_SHIFT    16
#define D_CAN_BTR_BRPE_MASK    (0xF << 16)    /* Baud rate prescaler ext */
#define D_CAN_BTR_TSEG2_SHIFT    12
#define D_CAN_BTR_TSEG2_MASK    (0x7 << 12)    /* Time seg after smpl point */
#define D_CAN_BTR_TSEG1_SHIFT    8
#define D_CAN_BTR_TSEG1_MASK    (0xF << 8)    /* Time seg before smpl point */
#define D_CAN_BTR_SJW_SHIFT    6
#define D_CAN_BTR_SJW_MASK    (0x3 << 6)    /* Syncronization jump width */
#define D_CAN_BTR_BRP_SHIFT    0
#define D_CAN_BTR_BRP_MASK    (0x3F << 0)    /* Baud rate prescaler */

/* D_CAN Test register bit fields */
#define D_CAN_TEST_RDA        BIT(9)    /* RAM direct access enable */
#define D_CAN_TEST_EXL        BIT(8)    /* External loopback mode */
#define D_CAN_TEST_RX        BIT(7)    /* Monitors the reveive pin */
#define D_CAN_TEST_TX        (0x3 << 5)    /* Control of CAN_TX pin */
#define D_CAN_TEST_LBACK    BIT(4)    /* Loopback mode */
#define D_CAN_TEST_SILENT    BIT(3)    /* Silent mdoe */

/* D_CAN Parity error reg bit fields */
#define D_CAN_PERR_WN_MASK    (0x7 << 8)    /* Parity error word nuber */
#define D_CAN_PERR_MN_MASK    0xFF        /* Parity error msg object */

/* D_CAN X registers bit fields */
#define D_CAN_BIT_FIELD(n)    (0x3 << (2 * n)) /* X reg's bit field 1 mask */

/* D_CAN IF command reg bit fields */
#define D_CAN_IF_CMD_WR        BIT(23)    /* Write/read */
#define D_CAN_IF_CMD_MASK    BIT(22)    /* Access to mask bits */
#define D_CAN_IF_CMD_ARB    BIT(21)    /* Access to arbitration bits */
#define D_CAN_IF_CMD_CONTROL    BIT(20)    /* Acess to control bits */
#define D_CAN_IF_CMD_CIP    BIT(19)    /* Clear int pending */
#define D_CAN_IF_CMD_TXRQST    BIT(18)    /* Access transmission request */
#define D_CAN_IF_CMD_DATAA    BIT(17)    /* Access to Data Bytes 0-3 */
#define D_CAN_IF_CMD_DATAB    BIT(16)    /* Access to Data Bytes 4-7 */
#define D_CAN_IF_CMD_BUSY    BIT(15)    /* Busy flag */
#define D_CAN_IF_CMD_DAM    BIT(14)    /* Activation of DMA */
#define D_CAN_IF_CMD_MN_MASK    0xFF    /* No. of msg's used for DMA T/F */
#define D_CAN_IF_CMD_ALL    (D_CAN_IF_CMD_MASK | D_CAN_IF_CMD_ARB | \
                D_CAN_IF_CMD_CONTROL | D_CAN_IF_CMD_TXRQST | \
                D_CAN_IF_CMD_DATAA | D_CAN_IF_CMD_DATAB)

/* D_CAN IF mask reg bit fields */
#define D_CAN_IF_MASK_MX    BIT(31)    /* Mask Extended Identifier */
#define D_CAN_IF_MASK_MD    BIT(30)    /* Mask Message direction */

/* D_CAN IF Arbitration */
#define D_CAN_IF_ARB_MSGVAL    BIT(31)    /* Message Vaild */
#define D_CAN_IF_ARB_MSGXTD    BIT(30)    /* Extended Identifier 0-11 1-29 */
#define D_CAN_IF_ARB_DIR_XMIT    BIT(29) /* Message direction 0-R 1-T */

/* D_CAN IF Message control */
#define D_CAN_IF_MCTL_NEWDAT    BIT(15)    /* New data available */
#define D_CAN_IF_MCTL_MSGLST    BIT(14)    /* Message lost, only for receive */
#define D_CAN_IF_MCTL_CLR_MSGLST (0 << 14)
#define D_CAN_IF_MCTL_INTPND    BIT(13)    /* Interrupt pending */
#define D_CAN_IF_MCTL_UMASK    BIT(12)    /* Use acceptance mask */
#define D_CAN_IF_MCTL_TXIE    BIT(11)    /* Transmit int enable */
#define D_CAN_IF_MCTL_RXIE    BIT(10)    /* Receive int enable */
#define D_CAN_IF_MCTL_RMTEN    BIT(9)    /* Remote enable */
#define D_CAN_IF_MCTL_TXRQST    BIT(8)    /* Transmit request */
#define D_CAN_IF_MCTL_EOB    BIT(7)    /* Data frames */
#define D_CAN_IF_MCTL_DLC_MASK    0xF    /* Data length code */

/* D_CAN IF3 Observation reg bit fields */
#define D_CAN_IF3OBS_UP        BIT(15)    /* Update data status */
#define D_CAN_IF3OBS_SDB    BIT(12)    /* DataB read out status */
#define D_CAN_IF3OBS_SDA    BIT(11)    /* DataA read out status */
#define D_CAN_IF3OBS_SC        BIT(10)    /* Contol bits read out status */
#define D_CAN_IF3OBS_SA        BIT(9)    /* Arbitration read out status */
#define D_CAN_IF3OBS_SM        BIT(8)    /* Mask bits read out status */
#define D_CAN_IF3OBS_DB        BIT(4)    /* Data B read observation */
#define D_CAN_IF3OBS_DA        BIT(3)    /* Data A read observation */
#define D_CAN_IF3OBS_CTL    BIT(2)    /* Control read observation */
#define D_CAN_IF3OBS_ARB    BIT(1)    /* Arbitration data read observation */
#define D_CAN_IF3OBS_MASK    BIT(0)    /* Mask data read observation */

/* D_CAN TX I/O reg bit fields */
#define D_CAN_TIOC_PU        BIT(18)    /* CAN_TX pull up/down select */
#define D_CAN_TIOC_PD        BIT(17)    /* CAN_TX pull disable */
#define D_CAN_TIOC_OD        BIT(16)    /* CAN_TX open drain enable */
#define D_CAN_TIOC_FUNC        BIT(3)    /* CAN_TX function */
#define D_CAN_TIOC_DIR        BIT(2)    /* CAN_TX data direction */
#define D_CAN_TIOC_OUT        BIT(1)    /* CAN_TX data out write */
#define D_CAN_TIOC_IN        BIT(0)    /* CAN_TX data in */

/* D_CAN RX I/O reg bit fields */
#define D_CAN_RIOC_PU        BIT(18)    /* CAN_RX pull up/down select */
#define D_CAN_RIOC_PD        BIT(17)    /* CAN_RX pull disable */
#define D_CAN_RIOC_OD        BIT(16)    /* CAN_RX open drain enable */
#define D_CAN_RIOC_FUNC        BIT(3)    /* CAN_RX function */
#define D_CAN_RIOC_DIR        BIT(2)    /* CAN_RX data direction */
#define D_CAN_RIOC_OUT        BIT(1)    /* CAN_RX data out write */
#define D_CAN_RTIOC_IN        BIT(0)    /* CAN_RX data in */

#define D_CAN_SET_REG        0xFFFFFFFF

#define D_CAN_CANMID_IDE    BIT(31)    /* Extended frame format */
#define D_CAN_CANMID_AME    BIT(30)    /* Acceptance mask enable */
#define D_CAN_CANMID_AAM    BIT(29)    /* Auto answer mode */

/*
 * IF register masks:
 */
#define IFX_WRITE_IDR(x)        ((x) & 0x1FFFFFFF)

#define IFX_CMD_BITS(x)            ((x) & 0xFFFFFF00)
#define IFX_CMD_MSG_NUMBER(x)        ((x) & 0xFF)

/* Message objects split */
#define D_CAN_NUM_MSG_OBJECTS        64
#define D_CAN_NUM_RX_MSG_OBJECTS    32
#define D_CAN_NUM_TX_MSG_OBJECTS    32

#define D_CAN_MSG_OBJ_RX_FIRST        1
#define D_CAN_MSG_OBJ_RX_LAST        (D_CAN_MSG_OBJ_RX_FIRST + \
                    D_CAN_NUM_RX_MSG_OBJECTS - 1)

#define D_CAN_MSG_OBJ_TX_FIRST        (D_CAN_MSG_OBJ_RX_LAST + 1)
#define D_CAN_MSG_OBJ_TX_LAST        (D_CAN_MSG_OBJ_TX_FIRST + \
                    D_CAN_NUM_TX_MSG_OBJECTS - 1)

#define D_CAN_MSG_OBJ_RX_SPLIT        17
#define D_CAN_MSG_OBJ_RX_LOW_LAST    (D_CAN_MSG_OBJ_RX_SPLIT - 1)

#define D_CAN_NEXT_MSG_OBJ_MASK        (D_CAN_NUM_TX_MSG_OBJECTS - 1)

/* status interrupt */
#define STATUS_INTERRUPT        0x8000

/* global interrupt masks */
#define ENABLE_ALL_INTERRUPTS        1
#define DISABLE_ALL_INTERRUPTS        0

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

/* Wait for ~1 sec for INIT bit */
#define D_CAN_WAIT_COUNT        100

#define D_CAN_IF_RX_NUM            0
#define D_CAN_IF_TX_NUM            1

#define D_CAN_GET_XREG_NUM(priv, reg)    (__ffs(d_can_read(priv, reg))/4)

/* CAN Bittiming constants as per D_CAN specs */
static struct can_bittiming_const d_can_bittiming_const = {
    .name = D_CAN_DRV_NAME,
    .tseg1_min = 1,        /* 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,
};

/* d_can last error code (lec) values */
enum d_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,
};

/*
 * d_can error types:
 * Bus errors (BUS_OFF, ERROR_WARNING, ERROR_PASSIVE) are supported
 */
enum d_can_bus_error_types {
    D_CAN_NO_ERROR = 0,
    D_CAN_BUS_OFF,
    D_CAN_ERROR_WARNING,
    D_CAN_ERROR_PASSIVE,
};

static inline void d_can_write(struct d_can_priv *priv, u32 reg, u32 val)
{
    __raw_writel(val, priv->base + reg);
}

static inline u32 d_can_read(struct d_can_priv *priv, int reg)
{
    return __raw_readl(priv->base + reg);
}

static inline void d_can_set_bit(struct d_can_priv *priv, int reg,
    u32 bit_mask)
{
    d_can_write(priv, reg, d_can_read(priv, reg) | bit_mask);
}

static inline u32 d_can_get_bit(struct d_can_priv *priv, int reg,
    u32 bit_mask)
{
    return (d_can_read(priv, reg) & bit_mask) ? 1 : 0;
}

static inline void d_can_clear_bit(struct d_can_priv *priv, int reg,
    u32 bit_mask)
{
    d_can_write(priv, reg, d_can_read(priv, reg) & ~bit_mask);
}

static inline int get_tx_next_msg_obj(const struct d_can_priv *priv)
{
    return (priv->tx_next & D_CAN_NEXT_MSG_OBJ_MASK) +
            D_CAN_MSG_OBJ_TX_FIRST;
}

static inline int get_tx_echo_msg_obj(const struct d_can_priv *priv)
{
    return (priv->tx_echo & D_CAN_NEXT_MSG_OBJ_MASK) +
            D_CAN_MSG_OBJ_TX_FIRST;
}

/*
 * API for enabling and disabling the multiple interrupts
 * of the DCAN module like error interrupt, status interrupt
 * error enable/disable for instance zero and one and etc.
 */
static void d_can_interrupts(struct d_can_priv *priv, int enable)
{
    unsigned int cntrl_save = d_can_read(priv, D_CAN_CTL);

    if (enable)
        cntrl_save |= (D_CAN_CTL_IE1 | D_CAN_CTL_EIE |
                D_CAN_CTL_IE0);
    else
        cntrl_save &= ~(D_CAN_CTL_IE1 | D_CAN_CTL_SIE |
                D_CAN_CTL_EIE | D_CAN_CTL_IE0);

    d_can_write(priv, D_CAN_CTL, cntrl_save);
}

static inline int d_can_msg_obj_is_busy(struct d_can_priv *priv, int iface)
{
    int count = MIN_TIMEOUT_VALUE;

    while (count && (d_can_read(priv, D_CAN_IFCMD(iface)) &
                D_CAN_IF_CMD_BUSY)) {
        count--;
        udelay(1);
    }

    if (!count)
        return 1;

    return 0;
}

static inline void d_can_object_get(struct net_device *dev,
                    int iface, int objno, int mask)
{
    struct d_can_priv *priv = netdev_priv(dev);

    d_can_write(priv, D_CAN_IFCMD(iface), IFX_CMD_BITS(mask) |
                    IFX_CMD_MSG_NUMBER(objno));

    /*
     * As per specs, after writing the message object number in the
     * IF command register the transfer b/w interface register and
     * message RAM must be complete in 12 CAN-CLK period.
     */
    if (d_can_msg_obj_is_busy(priv, iface))
        netdev_err(dev, "timed out in object get\n");
}

static inline void d_can_object_put(struct net_device *dev,
                    int iface, int objno, int mask)
{
    struct d_can_priv *priv = netdev_priv(dev);

    d_can_write(priv, D_CAN_IFCMD(iface), D_CAN_IF_CMD_WR |
        IFX_CMD_BITS(mask) | IFX_CMD_MSG_NUMBER(objno));

    /*
     * As per specs, after writing the message object number in the
     * IF command register the transfer b/w interface register and
     * message RAM must be complete in 12 CAN-CLK period.
     */
    if (d_can_msg_obj_is_busy(priv, iface))
        netdev_err(dev, "timed out in object put\n");
}

static void d_can_write_msg_object(struct net_device *dev,
            int iface, struct can_frame *frame, int objno)
{
    int i;
    unsigned int id;
    u32 dataA = 0;
    u32 dataB = 0;
    u32 flags = 0;
    struct d_can_priv *priv = netdev_priv(dev);

    if (!(frame->can_id & CAN_RTR_FLAG))
        flags |= D_CAN_IF_ARB_DIR_XMIT;

    if (frame->can_id & CAN_EFF_FLAG) {
        id = frame->can_id & CAN_EFF_MASK;
        flags |= D_CAN_IF_ARB_MSGXTD;
    } else
        id = ((frame->can_id & CAN_SFF_MASK) << 18);

    flags |= D_CAN_IF_ARB_MSGVAL;
    d_can_write(priv, D_CAN_IFARB(iface), IFX_WRITE_IDR(id) | flags);

    for (i = 0; i < frame->can_dlc; i++) {
        if (frame->can_dlc <= 4)
            dataA |= (frame->data[i] << (8 * i));
        else {
            if (i < 4)
                dataA |= (frame->data[i] << (8 * i));
            else
                dataB |= (frame->data[i] << (8 * (i - 4)));
        }
    }

    /* DATA write to Message object registers DATAA and DATAB */
    if (frame->can_dlc <= 4)
        d_can_write(priv, D_CAN_IFDATA(iface), dataA);
    else {
        d_can_write(priv, D_CAN_IFDATB(iface), dataB);
        d_can_write(priv, D_CAN_IFDATA(iface), dataA);
    }

    /* enable TX interrupt for this message object */
    d_can_write(priv, D_CAN_IFMCTL(iface),
            D_CAN_IF_MCTL_TXIE | D_CAN_IF_MCTL_EOB |
            D_CAN_IF_MCTL_TXRQST | D_CAN_IF_MCTL_NEWDAT |
            frame->can_dlc);

    /* Put message data into message RAM */
    d_can_object_put(dev, iface, objno, D_CAN_IF_CMD_ALL);
}

/*
 * Mark that this particular message object is received and clearing
 * the interrupt pending register value.
 */
static inline void d_can_mark_rx_msg_obj(struct net_device *dev,
                int iface, int ctrl_mask, int obj)
{
    struct d_can_priv *priv = netdev_priv(dev);

    d_can_write(priv, D_CAN_IFMCTL(iface), ctrl_mask
        & ~(D_CAN_IF_MCTL_MSGLST | D_CAN_IF_MCTL_INTPND));

    d_can_object_put(dev, iface, obj, D_CAN_IF_CMD_CONTROL);
}

static inline void d_can_activate_all_lower_rx_msg_objs(struct net_device *dev,
                int iface, int ctrl_mask)
{
    int i;
    struct d_can_priv *priv = netdev_priv(dev);

    for (i = D_CAN_MSG_OBJ_RX_FIRST; i <= D_CAN_MSG_OBJ_RX_LOW_LAST; i++) {
        d_can_write(priv, D_CAN_IFMCTL(iface),
                ctrl_mask & ~(D_CAN_IF_MCTL_MSGLST |
                D_CAN_IF_MCTL_INTPND | D_CAN_IF_MCTL_NEWDAT));
        d_can_object_put(dev, iface, i, D_CAN_IF_CMD_CONTROL);
    }
}

static inline void d_can_activate_rx_msg_obj(struct net_device *dev,
                        int iface, int ctrl_mask,
                        int obj)
{
    struct d_can_priv *priv = netdev_priv(dev);

    d_can_write(priv, D_CAN_IFMCTL(iface),
            ctrl_mask & ~(D_CAN_IF_MCTL_MSGLST |
            D_CAN_IF_MCTL_INTPND | D_CAN_IF_MCTL_NEWDAT));
    d_can_object_put(dev, iface, obj, D_CAN_IF_CMD_CONTROL);
}

static void d_can_handle_lost_msg_obj(struct net_device *dev,
                    int iface, int objno)
{
    struct d_can_priv *priv = netdev_priv(dev);
    struct net_device_stats *stats = &dev->stats;
    struct sk_buff *skb;
    struct can_frame *frame;

    netdev_err(dev, "msg lost in buffer %d\n", objno);

    d_can_object_get(dev, iface, objno, D_CAN_IF_CMD_ALL &
                    ~D_CAN_IF_CMD_TXRQST);

    d_can_write(priv, D_CAN_IFMCTL(iface), D_CAN_IF_MCTL_CLR_MSGLST);

    d_can_object_put(dev, iface, objno, D_CAN_IF_CMD_CONTROL);

    /* create an error msg */
    skb = alloc_can_err_skb(dev, &frame);
    if (unlikely(!skb))
        return;

    frame->can_id |= CAN_ERR_CRTL;
    frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
    stats->rx_errors++;
    stats->rx_over_errors++;

    netif_receive_skb(skb);
}

static int d_can_read_msg_object(struct net_device *dev, int iface, int ctrl)
{
    int i;
    u32 dataA = 0;
    u32 dataB = 0;
    unsigned int arb_val;
    unsigned int mctl_val;
    struct d_can_priv *priv = netdev_priv(dev);
    struct net_device_stats *stats = &dev->stats;
    struct sk_buff *skb;
    struct can_frame *frame;

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

    frame->can_dlc = get_can_dlc(ctrl & 0x0F);

    arb_val = d_can_read(priv, D_CAN_IFARB(iface));
    mctl_val = d_can_read(priv, D_CAN_IFMCTL(iface));

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

    if (mctl_val & D_CAN_IF_MCTL_RMTEN)
        frame->can_id |= CAN_RTR_FLAG;
    else {
        dataA = d_can_read(priv, D_CAN_IFDATA(iface));
        dataB = d_can_read(priv, D_CAN_IFDATB(iface));
        for (i = 0; i < frame->can_dlc; i++) {
            /* Writing MO higher 4 data bytes to skb */
            if (frame->can_dlc <= 4)
                frame->data[i] = dataA >> (8 * i);
            else {
                if (i < 4)
                    frame->data[i] = dataA >> (8 * i);
                else
                    frame->data[i] = dataB >> (8 * (i-4));
            }
        }
    }

    netif_receive_skb(skb);

    stats->rx_packets++;
    stats->rx_bytes += frame->can_dlc;

    return 0;
}

static void d_can_setup_receive_object(struct net_device *dev, int iface,
                    int objno, unsigned int mask,
                    unsigned int id, unsigned int mcont)
{
    struct d_can_priv *priv = netdev_priv(dev);

    d_can_write(priv, D_CAN_IFMSK(iface), IFX_WRITE_IDR(mask));
    d_can_write(priv, D_CAN_IFARB(iface), IFX_WRITE_IDR(id) |
            D_CAN_IF_ARB_MSGVAL);
    d_can_write(priv, D_CAN_IFMCTL(iface), mcont);

    d_can_object_put(dev, iface, objno, D_CAN_IF_CMD_ALL &
                    ~D_CAN_IF_CMD_TXRQST);

    netdev_dbg(dev, "obj no:%d, msgval:0x%08x\n", objno, d_can_read(priv,
        D_CAN_MSGVAL(D_CAN_GET_XREG_NUM(priv, D_CAN_MSGVAL_X))));
}

static void d_can_inval_msg_object(struct net_device *dev, int iface, int objno)
{
    struct d_can_priv *priv = netdev_priv(dev);

    d_can_write(priv, D_CAN_IFARB(iface), 0);
    d_can_write(priv, D_CAN_IFMCTL(iface), 0);

    d_can_object_put(dev, iface, objno, D_CAN_IF_CMD_ARB |
                    D_CAN_IF_CMD_CONTROL);

    netdev_dbg(dev, "obj no:%d, msgval:0x%08x\n", objno, d_can_read(priv,
        D_CAN_MSGVAL(D_CAN_GET_XREG_NUM(priv, D_CAN_MSGVAL_X))));
}

static inline int d_can_is_next_tx_obj_busy(struct d_can_priv *priv, int objno)
{
    u32 txrq_x_reg_val = D_CAN_GET_XREG_NUM(priv, D_CAN_TXRQ_X);

    /*
     * as transmission request register's bit n-1 corresponds to
     * message object n, we need to handle the same properly.
     */
    if (d_can_read(priv, D_CAN_TXRQ(txrq_x_reg_val)) &
            (1 << (objno - D_CAN_MSG_OBJ_TX_FIRST)))
        return 1;

    return 0;
}

static netdev_tx_t d_can_start_xmit(struct sk_buff *skb,
                    struct net_device *dev)
{
    u32 msg_obj_no;
    struct d_can_priv *priv = netdev_priv(dev);
    struct can_frame *frame = (struct can_frame *)skb->data;

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

    msg_obj_no = get_tx_next_msg_obj(priv);

    /* prepare message object for transmission */
    d_can_write_msg_object(dev, D_CAN_IF_TX_NUM, frame, msg_obj_no);
    can_put_echo_skb(skb, dev, msg_obj_no - D_CAN_MSG_OBJ_TX_FIRST);

    /*
     * we have to stop the queue in case of a wrap around or
     * if the next TX message object is still in use
     */
    priv->tx_next++;
    if (d_can_is_next_tx_obj_busy(priv, get_tx_next_msg_obj(priv)) ||
        ((priv->tx_next & D_CAN_NEXT_MSG_OBJ_MASK) == 0))
        netif_stop_queue(dev);

    return NETDEV_TX_OK;
}

static int d_can_set_bittiming(struct net_device *dev)
{
    struct d_can_priv *priv = netdev_priv(dev);
    const struct can_bittiming *bt = &priv->can.bittiming;
    u32 can_btc;

    can_btc = ((bt->phase_seg2 - 1) & 0x7) << D_CAN_BTR_TSEG2_SHIFT;
    can_btc |= ((bt->phase_seg1 + bt->prop_seg - 1)
            & 0xF) << D_CAN_BTR_TSEG1_SHIFT;

    can_btc |= ((bt->sjw - 1) & 0x3) << D_CAN_BTR_SJW_SHIFT;

    /* Ten bits contains the BRP, 6 bits for BRP and upper 4 bits for brpe*/
    can_btc |= ((bt->brp - 1) & 0x3F) << D_CAN_BTR_BRP_SHIFT;
    can_btc |= ((((bt->brp - 1) >> 6) & 0xF) << D_CAN_BTR_BRPE_SHIFT);

    d_can_write(priv, D_CAN_BTR, can_btc);

    netdev_info(dev, "setting CAN BT = %#x\n", can_btc);

    return 0;
}

/*
 * Configure D_CAN message objects for Tx and Rx purposes:
 * D_CAN provides a total of 64 message objects that can be configured
 * either for Tx or Rx purposes. In this driver first 32 message objects
 * are used as a reception FIFO and the reception FIFO is signified by the
 * EoB bit being SET. The remaining 32 message objects are kept aside for
 * Tx purposes. See user guide document for further details on configuring
 * message objects.
 */
static void d_can_configure_msg_objects(struct net_device *dev)
{
    unsigned int i;

    /* first invalidate all message objects */
    for (i = D_CAN_MSG_OBJ_RX_FIRST; i <= D_CAN_NUM_MSG_OBJECTS; i++)
        d_can_inval_msg_object(dev, D_CAN_IF_RX_NUM, i);

    /* setup receive message objects */
    for (i = D_CAN_MSG_OBJ_RX_FIRST; i < D_CAN_MSG_OBJ_RX_LAST; i++)
        d_can_setup_receive_object(dev, D_CAN_IF_RX_NUM, i, 0, 0,
            (D_CAN_IF_MCTL_RXIE | D_CAN_IF_MCTL_UMASK) &
            ~D_CAN_IF_MCTL_EOB);

    /* Last object EoB bit should be 1 for terminate */
    d_can_setup_receive_object(dev, D_CAN_IF_RX_NUM, D_CAN_MSG_OBJ_RX_LAST,
            0, 0, D_CAN_IF_MCTL_RXIE | D_CAN_IF_MCTL_UMASK |
            D_CAN_IF_MCTL_EOB);
}

static void d_can_test_mode(struct net_device *dev)
{
    struct d_can_priv *priv = netdev_priv(dev);

    /* Test mode is enabled in this step & the specific TEST bits
     * are enabled accordingly */
    d_can_write(priv, D_CAN_CTL, D_CAN_CTL_EIE |
            D_CAN_CTL_IE1 |    D_CAN_CTL_IE0 | D_CAN_CTL_TEST);

    if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) {
        /* silent mode : bus-monitoring mode */
        d_can_write(priv, D_CAN_TEST, D_CAN_TEST_SILENT);
    } else if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
        /* loopback mode : useful for self-test function */
        d_can_write(priv, D_CAN_TEST, D_CAN_TEST_LBACK);
    } else {
        /* loopback + silent mode : useful for hot self-test */
        d_can_write(priv, D_CAN_TEST, D_CAN_TEST_LBACK |
                D_CAN_TEST_SILENT);
    }
}

/*
 * Configure D_CAN chip:
 * - enable/disable auto-retransmission
 * - set operating mode
 * - configure message objects
 */
static void d_can_init(struct net_device *dev)
{
    struct d_can_priv *priv = netdev_priv(dev);
    u32 cnt;

    netdev_dbg(dev, "resetting d_can ...\n");
    d_can_set_bit(priv, D_CAN_CTL, D_CAN_CTL_SWR);

    /* Enter initialization mode by setting the Init bit */
    d_can_set_bit(priv, D_CAN_CTL, D_CAN_CTL_INIT);

    /* enable automatic retransmission */
    d_can_set_bit(priv, D_CAN_CTL, D_CAN_CTL_ENABLE_AR);

    /* Set the Configure Change Enable ( CCE) bit */
    d_can_set_bit(priv, D_CAN_CTL, D_CAN_CTL_CCE);

    /* Wait for the Init bit to get set */
    cnt = D_CAN_WAIT_COUNT;
    while (!d_can_get_bit(priv, D_CAN_CTL, D_CAN_CTL_INIT) && cnt != 0) {
        --cnt;
        udelay(10);
    }

    /* set bittiming params */
    d_can_set_bittiming(dev);

    d_can_clear_bit(priv, D_CAN_CTL, D_CAN_CTL_INIT | D_CAN_CTL_CCE);

    /* Wait for the Init bit to get clear */
    cnt = D_CAN_WAIT_COUNT;
    while (d_can_get_bit(priv, D_CAN_CTL, D_CAN_CTL_INIT) && cnt != 0) {
        --cnt;
        udelay(10);
    }

    if (!priv->test_mode) {
        /* normal mode*/
        d_can_write(priv, D_CAN_CTL, D_CAN_CTL_EIE | D_CAN_CTL_IE1 |
                            D_CAN_CTL_IE0);
    } else
        d_can_test_mode(dev);

    /* Enable TX and RX I/O Control pins */
    d_can_write(priv, D_CAN_TIOC, D_CAN_TIOC_FUNC);
    d_can_write(priv, D_CAN_RIOC, D_CAN_RIOC_FUNC);

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

    /* set a LEC value so that we can check for updates later */
    d_can_write(priv, D_CAN_ES, LEC_UNUSED);
}

static void d_can_start(struct net_device *dev)
{
    struct d_can_priv *priv = netdev_priv(dev);

    /* basic d_can initialization */
    d_can_init(dev);

    priv->can.state = CAN_STATE_ERROR_ACTIVE;

    /* reset tx helper pointers */
    priv->tx_next = priv->tx_echo = 0;

    /* enable status change, error and module interrupts */
    d_can_interrupts(priv, ENABLE_ALL_INTERRUPTS);
}

static void d_can_stop(struct net_device *dev)
{
    struct d_can_priv *priv = netdev_priv(dev);

    /* disable all interrupts */
    d_can_interrupts(priv, DISABLE_ALL_INTERRUPTS);

    /* set the state as STOPPED */
    priv->can.state = CAN_STATE_STOPPED;
}

static int d_can_set_mode(struct net_device *dev, enum can_mode mode)
{
    switch (mode) {
    case CAN_MODE_START:
        d_can_start(dev);
        netif_wake_queue(dev);
        break;
    default:
        return -EOPNOTSUPP;
    }

    return 0;
}

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

    reg_err_counter = d_can_read(priv, D_CAN_ERRC);
    bec->rxerr = (reg_err_counter & D_CAN_ERRC_REC_MASK) >>
                D_CAN_ERRC_REC_SHIFT;
    bec->txerr = reg_err_counter & D_CAN_ERRC_TEC_MASK;

    return 0;
}

/*
 * theory of operation:
 *
 * priv->tx_echo holds the number of the oldest can_frame put for
 * transmission into the hardware, but not yet ACKed by the CAN tx
 * complete IRQ.
 *
 * We iterate from priv->tx_echo to priv->tx_next and check if the
 * packet has been transmitted, echo it back to the CAN framework.
 * If we discover a not yet transmitted package, stop looking for more.
 */
static void d_can_do_tx(struct net_device *dev)
{
    u32 msg_obj_no;
    struct d_can_priv *priv = netdev_priv(dev);
    struct net_device_stats *stats = &dev->stats;
    u32 txrq_x_reg_val;
    u32 txrq_reg_val;

    for (/* nix */; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) {
        msg_obj_no = get_tx_echo_msg_obj(priv);
        txrq_x_reg_val = D_CAN_GET_XREG_NUM(priv, D_CAN_TXRQ_X);
        txrq_reg_val = d_can_read(priv, D_CAN_TXRQ(txrq_x_reg_val));
        if (!(txrq_reg_val & (1 << (msg_obj_no -
                        D_CAN_MSG_OBJ_TX_FIRST)))) {
            can_get_echo_skb(dev,
                    msg_obj_no - D_CAN_MSG_OBJ_TX_FIRST);
            stats->tx_bytes += d_can_read(priv,
                    D_CAN_IFMCTL(D_CAN_IF_TX_NUM))
                    & D_CAN_IF_MCTL_DLC_MASK;
            stats->tx_packets++;
            d_can_inval_msg_object(dev, D_CAN_IF_TX_NUM,
                    msg_obj_no);
        } else
            break;
    }

    /* restart queue if wrap-up or if queue stalled on last pkt */
    if (((priv->tx_next & D_CAN_NEXT_MSG_OBJ_MASK) != 0)
        || ((priv->tx_echo & D_CAN_NEXT_MSG_OBJ_MASK) == 0))
        netif_wake_queue(dev);
}

/*
 * theory of operation:
 *
 * d_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. To work-around this issue, we keep two groups of message
 * objects whose partitioning is defined by D_CAN_MSG_OBJ_RX_SPLIT.
 *
 * To ensure in-order frame reception we use the following
 * approach while re-activating a message object to receive further
 * frames:
 * - if the current message object number is lower than
 *   D_CAN_MSG_RX_LOW_LAST, do not clear the NEWDAT bit while clearing
 *   the INTPND bit.
 * - if the current message object number is equal to
 *   D_CAN_MSG_RX_LOW_LAST then clear the NEWDAT bit of all lower
 *   receive message objects.
 * - if the current message object number is greater than
 *   D_CAN_MSG_RX_LOW_LAST then clear the NEWDAT bit of
 *   only this message object.
 */
static int d_can_do_rx_poll(struct net_device *dev, int quota)
{
    struct d_can_priv *priv = netdev_priv(dev);
    unsigned int msg_obj, mctrl_reg_val;
    u32 num_rx_pkts = 0;
    u32 intpnd_x_reg_val;
    u32 intpnd_reg_val;

    for (msg_obj = D_CAN_MSG_OBJ_RX_FIRST; msg_obj <= D_CAN_MSG_OBJ_RX_LAST
                && quota > 0; msg_obj++) {

        intpnd_x_reg_val = D_CAN_GET_XREG_NUM(priv, D_CAN_INTPND_X);
        intpnd_reg_val = d_can_read(priv,
                    D_CAN_INTPND(intpnd_x_reg_val));

        /*
         * as interrupt pending register's bit n-1 corresponds to
         * message object n, we need to handle the same properly.
         */
        if (intpnd_reg_val & (1 << (msg_obj - 1))) {

            d_can_object_get(dev, D_CAN_IF_RX_NUM, msg_obj,
                    D_CAN_IF_CMD_ALL &
                    ~D_CAN_IF_CMD_TXRQST);

            mctrl_reg_val = d_can_read(priv,
                    D_CAN_IFMCTL(D_CAN_IF_RX_NUM));

            if (!(mctrl_reg_val & D_CAN_IF_MCTL_NEWDAT))
                continue;

            /* read the data from the message object */
            d_can_read_msg_object(dev, D_CAN_IF_RX_NUM,
                        mctrl_reg_val);

            if (mctrl_reg_val & D_CAN_IF_MCTL_EOB)
                d_can_setup_receive_object(dev, D_CAN_IF_RX_NUM,
                    D_CAN_MSG_OBJ_RX_LAST, 0, 0,
                    D_CAN_IF_MCTL_RXIE | D_CAN_IF_MCTL_UMASK
                    | D_CAN_IF_MCTL_EOB);

            if (mctrl_reg_val & D_CAN_IF_MCTL_MSGLST) {
                d_can_handle_lost_msg_obj(dev, D_CAN_IF_RX_NUM,
                    msg_obj);
                num_rx_pkts++;
                quota--;
                continue;
            }

            if (msg_obj < D_CAN_MSG_OBJ_RX_LOW_LAST)
                d_can_mark_rx_msg_obj(dev, D_CAN_IF_RX_NUM,
                        mctrl_reg_val, msg_obj);
            else if (msg_obj > D_CAN_MSG_OBJ_RX_LOW_LAST)
                /* activate this msg obj */
                d_can_activate_rx_msg_obj(dev, D_CAN_IF_RX_NUM,
                        mctrl_reg_val, msg_obj);
            else if (msg_obj == D_CAN_MSG_OBJ_RX_LOW_LAST)
                /* activate all lower message objects */
                d_can_activate_all_lower_rx_msg_objs(dev,
                        D_CAN_IF_RX_NUM, mctrl_reg_val);

            num_rx_pkts++;
            quota--;
        }
    }

    return num_rx_pkts;
}

static inline int d_can_has_handle_berr(struct d_can_priv *priv)
{
    return (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) &&
        (priv->current_status & LEC_UNUSED);
}

static int d_can_handle_state_change(struct net_device *dev,
                enum d_can_bus_error_types error_type)
{
    unsigned int reg_err_counter;
    unsigned int rx_err_passive;
    struct d_can_priv *priv = netdev_priv(dev);
    struct net_device_stats *stats = &dev->stats;
    struct can_frame *cf;
    struct sk_buff *skb;
    struct can_berr_counter bec;

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

    d_can_get_berr_counter(dev, &bec);
    reg_err_counter = d_can_read(priv, D_CAN_ERRC);
    rx_err_passive = (reg_err_counter & D_CAN_ERRC_RP_MASK) >>
                D_CAN_ERRC_RP_SHIFT;

    switch (error_type) {
    case D_CAN_ERROR_WARNING:
        /* error warning state */
        priv->can.can_stats.error_warning++;
        priv->can.state = CAN_STATE_ERROR_WARNING;
        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 D_CAN_ERROR_PASSIVE:
        /* error passive state */
        priv->can.can_stats.error_passive++;
        priv->can.state = CAN_STATE_ERROR_PASSIVE;
        cf->can_id |= CAN_ERR_CRTL;
        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 D_CAN_BUS_OFF:
        /* bus-off state */
        priv->can.state = CAN_STATE_BUS_OFF;
        cf->can_id |= CAN_ERR_BUSOFF;
        /*
         * disable all interrupts in bus-off mode to ensure that
         * the CPU is not hogged down
         */
        d_can_interrupts(priv, DISABLE_ALL_INTERRUPTS);
        can_bus_off(dev);
        break;
    default:
        break;
    }

    netif_receive_skb(skb);
    stats->rx_packets++;
    stats->rx_bytes += cf->can_dlc;

    return 1;
}

static int d_can_handle_bus_err(struct net_device *dev,
                enum d_can_lec_type lec_type)
{
    struct d_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;

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

    /*
     * check for 'last error code' which tells us the
     * type of the last error to occur on the CAN bus
     */

    /* common for all type of bus errors */
    priv->can.can_stats.bus_error++;
    stats->rx_errors++;
    cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
    cf->data[2] |= CAN_ERR_PROT_UNSPEC;

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

    /* set a LEC value so that we can check for updates later */
    d_can_write(priv, D_CAN_ES, LEC_UNUSED);

    netif_receive_skb(skb);
    stats->rx_packets++;
    stats->rx_bytes += cf->can_dlc;

    return 1;
}

static int d_can_poll(struct napi_struct *napi, int quota)
{
    int lec_type = 0;
    int work_done = 0;
    struct net_device *dev = napi->dev;
    struct d_can_priv *priv = netdev_priv(dev);

    if (!priv->irqstatus)
        goto end;

    /* status events have the highest priority */
    if (priv->irqstatus == STATUS_INTERRUPT) {
        priv->current_status = d_can_read(priv, D_CAN_ES);

        /* handle Tx/Rx events */
        if (priv->current_status & D_CAN_ES_TXOK)
            d_can_write(priv, D_CAN_ES,
                    priv->current_status & ~D_CAN_ES_TXOK);

        if (priv->current_status & D_CAN_ES_RXOK)
            d_can_write(priv, D_CAN_ES,
                    priv->current_status & ~D_CAN_ES_RXOK);

        /* handle state changes */
        if ((priv->current_status & D_CAN_ES_EWARN) &&
                (!(priv->last_status & D_CAN_ES_EWARN))) {
            netdev_dbg(dev, "entered error warning state\n");
            work_done += d_can_handle_state_change(dev,
                        D_CAN_ERROR_WARNING);
        }
        if ((priv->current_status & D_CAN_ES_EPASS) &&
                (!(priv->last_status & D_CAN_ES_EPASS))) {
            netdev_dbg(dev, "entered error passive state\n");
            work_done += d_can_handle_state_change(dev,
                        D_CAN_ERROR_PASSIVE);
        }
        if ((priv->current_status & D_CAN_ES_BOFF) &&
                (!(priv->last_status & D_CAN_ES_BOFF))) {
            netdev_dbg(dev, "entered bus off state\n");
            work_done += d_can_handle_state_change(dev,
                        D_CAN_BUS_OFF);
        }

        /* handle bus recovery events */
        if ((!(priv->current_status & D_CAN_ES_BOFF)) &&
                (priv->last_status & D_CAN_ES_BOFF)) {
            netdev_dbg(dev, "left bus off state\n");
            priv->can.state = CAN_STATE_ERROR_ACTIVE;
        }
        if ((!(priv->current_status & D_CAN_ES_EPASS)) &&
                (priv->last_status & D_CAN_ES_EPASS)) {
            netdev_dbg(dev, "left error passive state\n");
            priv->can.state = CAN_STATE_ERROR_ACTIVE;
        }

        priv->last_status = priv->current_status;

        /* handle lec errors on the bus */
        lec_type = d_can_has_handle_berr(priv);
        if (lec_type)
            work_done += d_can_handle_bus_err(dev, lec_type);
    } else if ((priv->irqstatus >= D_CAN_MSG_OBJ_RX_FIRST) &&
            (priv->irqstatus <= D_CAN_MSG_OBJ_RX_LAST)) {
        /* handle events corresponding to receive message objects */
        work_done += d_can_do_rx_poll(dev, (quota - work_done));
    } else if ((priv->irqstatus >= D_CAN_MSG_OBJ_TX_FIRST) &&
            (priv->irqstatus <= D_CAN_MSG_OBJ_TX_LAST)) {
        /* handle events corresponding to transmit message objects */
        d_can_do_tx(dev);
    }

end:
    if (work_done < quota) {
        napi_complete(napi);
        /* enable all IRQs */
        d_can_interrupts(priv, ENABLE_ALL_INTERRUPTS);
    }

    return work_done;
}

static irqreturn_t d_can_isr(int irq, void *dev_id)
{
    struct net_device *dev = (struct net_device *)dev_id;
    struct d_can_priv *priv = netdev_priv(dev);

    priv->irqstatus = d_can_read(priv, D_CAN_INT);
    if (!priv->irqstatus)
        return IRQ_NONE;

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

    return IRQ_HANDLED;
}

static int d_can_open(struct net_device *ndev)
{
    int err;
    struct d_can_priv *priv = netdev_priv(ndev);

    /* Open common can device */
    err = open_candev(ndev);
    if (err) {
        netdev_err(ndev, "open_candev() failed %d\n", err);
        return err;
    }

    /* register interrupt handler for Message Object (MO)
     * and Error + status change (ES) */
    err = request_irq(ndev->irq, &d_can_isr, IRQF_SHARED, ndev->name,
                ndev);
    if (err) {
        netdev_err(ndev, "failed to request MO_ES interrupt\n");
        goto exit_close_candev;
    }

    /* register interrupt handler for only Message Object */
    err = request_irq(priv->irq_obj, &d_can_isr, IRQF_SHARED, ndev->name,
                ndev);
    if (err) {
        netdev_err(ndev, "failed to request MO interrupt\n");
        goto exit_free_irq;
    }

    /* start the d_can controller */
    d_can_start(ndev);

    napi_enable(&priv->napi);
    netif_start_queue(ndev);

    return 0;
exit_free_irq:
    free_irq(ndev->irq, ndev);
exit_close_candev:
    close_candev(ndev);
    return err;
}

static int d_can_close(struct net_device *ndev)
{
    struct d_can_priv *priv = netdev_priv(ndev);

    netif_stop_queue(ndev);
    napi_disable(&priv->napi);
    d_can_stop(ndev);
    free_irq(ndev->irq, ndev);
    free_irq(priv->irq_obj, ndev);
    close_candev(ndev);

    return 0;
}

struct net_device *alloc_d_can_dev(int num_objs)
{
    struct net_device *dev;
    struct d_can_priv *priv;

    dev = alloc_candev(sizeof(struct d_can_priv), num_objs/2);
    if (!dev)
        return NULL;

    priv = netdev_priv(dev);
    netif_napi_add(dev, &priv->napi, d_can_poll, num_objs/2);

    priv->dev = dev;
    priv->can.bittiming_const = &d_can_bittiming_const;
    priv->can.do_set_mode = d_can_set_mode;
    priv->can.do_get_berr_counter = d_can_get_berr_counter;
    priv->can.ctrlmode_supported = (CAN_CTRLMODE_LOOPBACK |
                    CAN_CTRLMODE_LISTENONLY |
                    CAN_CTRLMODE_BERR_REPORTING |
                    CAN_CTRLMODE_3_SAMPLES);

    return dev;
}
EXPORT_SYMBOL_GPL(alloc_d_can_dev);

void free_d_can_dev(struct net_device *dev)
{
    free_candev(dev);
}
EXPORT_SYMBOL_GPL(free_d_can_dev);

static const struct net_device_ops d_can_netdev_ops = {
    .ndo_open = d_can_open,
    .ndo_stop = d_can_close,
    .ndo_start_xmit = d_can_start_xmit,
};

int register_d_can_dev(struct net_device *dev)
{
    /* we support local echo */
    dev->flags |= IFF_ECHO;
    dev->netdev_ops = &d_can_netdev_ops;

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

void unregister_d_can_dev(struct net_device *dev)
{
    struct d_can_priv *priv = netdev_priv(dev);

    /* disable all interrupts */
    d_can_interrupts(priv, DISABLE_ALL_INTERRUPTS);

    unregister_candev(dev);
}
EXPORT_SYMBOL_GPL(unregister_d_can_dev);

MODULE_AUTHOR("Anil Kumar Ch <anilkumar@ti.com>");
MODULE_LICENSE("GPL v2");
MODULE_VERSION(D_CAN_VERSION);
MODULE_DESCRIPTION(D_CAN_DRV_DESC);







l4/pkg/d_can/d_can/d_can.h:

/*
 * CAN bus driver for Bosch D_CAN controller
 *
 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
 * Anil Kumar Ch <anilkumar@ti.com>
 *
 * Borrowed from C_CAN driver
 * 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>
 *
 * Bosch D_CAN controller is compliant to CAN protocol version 2.0 part A and B.
 * Bosch D_CAN user manual can be obtained from:
 * http://www.semiconductors.bosch.de/media/en/pdf/ipmodules_1/can/
 * d_can_users_manual_111.pdf
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation version 2.
 *
 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
 * kind, whether express or implied; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#ifndef D_CAN_H
#define D_CAN_H

#define D_CAN_DRV_NAME    "d_can"
#define D_CAN_VERSION    "1.0"
#define D_CAN_DRV_DESC    "CAN bus driver for Bosch D_CAN controller " \
            D_CAN_VERSION

/* d_can private data structure */
struct d_can_priv {
    struct can_priv can;    /* must be the first member */
    struct napi_struct napi;
    struct net_device *dev;
    int current_status;
    int last_status;
    unsigned int irqstatus;
    void __iomem *base;
    u32 napi_weight;
    struct clk *fck;
    struct clk *ick;
    bool test_mode;
    unsigned int irq;    /* device IRQ number, for all MO and ES    */
    unsigned int irq_obj;    /* device IRQ number for only Msg Object */
    unsigned int irq_parity; /* device IRQ number for parity error */
    unsigned long irq_flags; /* for request_irq() */
    unsigned int tx_next;
    unsigned int tx_echo;
    unsigned int rx_next;
    void *priv;        /* for board-specific data */
};

struct net_device *alloc_d_can_dev(int);
void free_d_can_dev(struct net_device *dev);
int register_d_can_dev(struct net_device *dev);
void unregister_d_can_dev(struct net_device *dev);

#endif /* D_CAN_H */






l4/pkg/d_can/d_can/d_can_platform.c:


/*
 * Platform CAN bus driver for Bosch D_CAN controller
 *
 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
 * Anil Kumar Ch <anilkumar@ti.com>
 *
 * Borrowed from C_CAN driver
 * 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>
 *
 * Bosch D_CAN controller is compliant to CAN protocol version 2.0 part A and B.
 * Bosch D_CAN user manual can be obtained from:
 * http://www.semiconductors.bosch.de/media/en/pdf/ipmodules_1/can/
 * d_can_users_manual_111.pdf
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation version 2.
 *
 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
 * kind, whether express or implied; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

/*
 * Your platform definitions should specify module ram offsets and interrupt
 * number to use as follows:
 *
 * static struct d_can_platform_data am33xx_evm_d_can_pdata = {
 *    .d_can_offset        = 0,
 *    .d_can_ram_offset    = 0x1000,
 *    .num_of_msg_objs    = 64,
 *    .dma_support        = true,
 *    .test_mode_enable    = false,
 *    .parity_check        = false,
 *    .version        = 0x1,
 *    .hw_raminit        = d_can_hw_raminit,
 * };
 *
 * Please see include/linux/can/platform/d_can.h for description of
 * above fields.
 *
 */

#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/platform_device.h>
#include <linux/can/platform/d_can.h>
#include <linux/clk.h>
#include <linux/slab.h>
#include <linux/can/dev.h>

#include "d_can.h"

static int __devinit d_can_plat_probe(struct platform_device *pdev)
{
    int ret = 0;
    void __iomem *addr;
    struct net_device *ndev;
    struct d_can_priv *priv;
    struct resource *mem;
    struct d_can_platform_data *pdata;

    pdata = pdev->dev.platform_data;
    if (!pdata) {
        dev_err(&pdev->dev, "No platform data\n");
        goto exit;
    }

    /* allocate the d_can device */
    ndev = alloc_d_can_dev(pdata->num_of_msg_objs);
    if (!ndev) {
        ret = -ENOMEM;
        dev_err(&pdev->dev, "alloc_d_can_dev failed\n");
        goto exit;
    }

    priv = netdev_priv(ndev);

    priv->fck = clk_get(&pdev->dev, pdata->fck_name);
    if (IS_ERR(priv->fck)) {
        dev_err(&pdev->dev, "%s is not found\n", pdata->fck_name);
        ret = -ENODEV;
        goto exit_free_ndev;
    }
    clk_enable(priv->fck);

    priv->ick = clk_get(&pdev->dev, pdata->ick_name);
    if (IS_ERR(priv->ick)) {
        dev_err(&pdev->dev, "%s is not found\n", pdata->ick_name);
        ret = -ENODEV;
        goto exit_free_fck;
    }
    clk_enable(priv->ick);

    /* get the platform data */
    mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    if (!mem) {
        ret = -ENODEV;
        dev_err(&pdev->dev, "No mem resource\n");
        goto exit_free_clks;
    }

    if (!request_mem_region(mem->start, resource_size(mem),
                D_CAN_DRV_NAME)) {
        dev_err(&pdev->dev, "resource unavailable\n");
        ret = -EBUSY;
        goto exit_free_clks;
    }

    addr = ioremap(mem->start, resource_size(mem));
    if (!addr) {
        dev_err(&pdev->dev, "ioremap failed\n");
        ret = -ENOMEM;
        goto exit_release_mem;
    }

    /* IRQ specific to Error and status & can be used for Message Object */
    ndev->irq = platform_get_irq_byname(pdev, "int0");
    if (!ndev->irq) {
        dev_err(&pdev->dev, "No irq0 resource\n");
        goto exit_iounmap;
    }

    /* IRQ specific for Message Object */
    priv->irq_obj = platform_get_irq_byname(pdev, "int1");
    if (!priv->irq_obj) {
        dev_err(&pdev->dev, "No irq1 resource\n");
        goto exit_iounmap;
    }

    priv->base = addr;
    priv->can.clock.freq = clk_get_rate(priv->fck);
    priv->test_mode = pdata->test_mode_enable;

    platform_set_drvdata(pdev, ndev);
    SET_NETDEV_DEV(ndev, &pdev->dev);

    ret = register_d_can_dev(ndev);
    if (ret) {
        dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
                D_CAN_DRV_NAME, ret);
        goto exit_free_device;
    }

    dev_info(&pdev->dev, "%s device registered (irq=%d, irq_obj=%d)\n",
                D_CAN_DRV_NAME, ndev->irq, priv->irq_obj);

    return 0;

exit_free_device:
    platform_set_drvdata(pdev, NULL);
exit_iounmap:
    iounmap(addr);
exit_release_mem:
    release_mem_region(mem->start, resource_size(mem));
exit_free_clks:
    clk_disable(priv->ick);
    clk_put(priv->ick);
exit_free_fck:
    clk_disable(priv->fck);
    clk_put(priv->fck);
exit_free_ndev:
    free_d_can_dev(ndev);
exit:
    dev_err(&pdev->dev, "probe failed\n");

    return ret;
}

static int __devexit d_can_plat_remove(struct platform_device *pdev)
{
    struct net_device *ndev = platform_get_drvdata(pdev);
    struct d_can_priv *priv = netdev_priv(ndev);
    struct resource *mem;

    unregister_d_can_dev(ndev);
    platform_set_drvdata(pdev, NULL);

    free_d_can_dev(ndev);
    iounmap(priv->base);

    mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    release_mem_region(mem->start, resource_size(mem));

    clk_disable(priv->ick);
    clk_disable(priv->fck);
    clk_put(priv->ick);
    clk_put(priv->fck);

    return 0;
}

static struct platform_driver d_can_plat_driver = {
    .driver = {
        .name    = D_CAN_DRV_NAME,
        .owner    = THIS_MODULE,
    },
    .probe    = d_can_plat_probe,
    .remove = __devexit_p(d_can_plat_remove),
};

static int __init d_can_plat_init(void)
{
    printk(KERN_INFO D_CAN_DRV_DESC "\n");
    return platform_driver_register(&d_can_plat_driver);
}
module_init(d_can_plat_init);

static void __exit d_can_plat_exit(void)
{
    printk(KERN_INFO D_CAN_DRV_DESC " unloaded\n");
    platform_driver_unregister(&d_can_plat_driver);
}
module_exit(d_can_plat_exit);

MODULE_AUTHOR("Anil Kumar Ch <anilkumar@ti.com>");
MODULE_LICENSE("GPL v2");
MODULE_VERSION(D_CAN_VERSION);
MODULE_DESCRIPTION(D_CAN_DRV_DESC);






l4/pkg/d_can/d_can/Makefile:


PKGDIR    ?= ..
L4DIR    ?= $(PKGDIR)/../..

DDE_SYSTEMS    = x86 arm

TARGET = d_can

SRC_C = d_can.c d_can_platform.c

REQUIRES_LIBS  = slab ddekit dde-linux26 dde-linux26_net libio l4util l4re_c-util

ifeq ($(ARCH), arm)
DEFINES += -D__LINUX_ARM_ARCH__=6
ARCH_DIR = arch/arm
endif


include $(PKGDIR)/../dde/linux26/Makeconf
#include $(PKGDIR_OBJ)/Makeconf
include $(L4DIR)/mk/prog.mk


#
#  Makefile for the Bosch D_CAN controller drivers.
#

obj-$(CONFIG_CAN_D_CAN) += d_can.o
obj-$(CONFIG_CAN_D_CAN_PLATFORM) += d_can_platform.o

ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG






l4/pkg/D-can/d_can/Kconfig:


menuconfig CAN_D_CAN
    tristate "Bosch D_CAN devices"
    depends on CAN_DEV && HAS_IOMEM

if CAN_D_CAN

config CAN_D_CAN_PLATFORM
    tristate "Generic Platform Bus based D_CAN driver"
    ---help---
      This driver adds support for the D_CAN chips connected to
      the "platform bus" (Linux abstraction for directly to the
      processor attached devices) which can be found on am335x
      and dm814x boards from TI (http://www.ti.com).
endif