advice on using ddelinux

Korbinian Ederer <[email protected]>
Newsgroups gmane.comp.micro-kernel.l4.devel
Message-ID <[email protected]>
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 <[email protected]>
  *
  * Borrowed from C_CAN driver
  * Copyright (C) 2010 ST Microelectronics
  * - Bhupesh Sharma <[email protected]>
  *
  * Borrowed heavily from the C_CAN driver originally written by:
  * Copyright (C) 2007
  * - Sascha Hauer, Marc Kleine-Budde, Pengutronix <[email protected]>
  * - Simon Kallweit, intefo AG <[email protected]>
  *
  * 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 <[email protected]>");
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 <[email protected]>
  *
  * Borrowed from C_CAN driver
  * Copyright (C) 2010 ST Microelectronics
  * - Bhupesh Sharma <[email protected]>
  *
  * Borrowed heavily from the C_CAN driver originally written by:
  * Copyright (C) 2007
  * - Sascha Hauer, Marc Kleine-Budde, Pengutronix <[email protected]>
  * - Simon Kallweit, intefo AG <[email protected]>
  *
  * 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 <[email protected]>
  *
  * Borrowed from C_CAN driver
  * Copyright (C) 2010 ST Microelectronics
  * - Bhupesh Sharma <[email protected]>
  *
  * Borrowed heavily from the C_CAN driver originally written by:
  * Copyright (C) 2007
  * - Sascha Hauer, Marc Kleine-Budde, Pengutronix <[email protected]>
  * - Simon Kallweit, intefo AG <[email protected]>
  *
  * 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 <[email protected]>");
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/

_______________________________________________
l4-hackers mailing list
[email protected]
http://os.inf.tu-dresden.de/mailman/listinfo/l4-hackers
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.