advice on using ddelinux

Korbinian Ederer korbinian.ederer at in.tum.de
Tue Aug 26 13:54:37 CEST 2014


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 at ti.com>
  *
  * Borrowed from C_CAN driver
  * Copyright (C) 2010 ST Microelectronics
  * - Bhupesh Sharma <bhupesh.sharma at st.com>
  *
  * Borrowed heavily from the C_CAN driver originally written by:
  * Copyright (C) 2007
  * - Sascha Hauer, Marc Kleine-Budde, Pengutronix <s.hauer at pengutronix.de>
  * - Simon Kallweit, intefo AG <simon.kallweit at 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 at 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 at ti.com>
  *
  * Borrowed from C_CAN driver
  * Copyright (C) 2010 ST Microelectronics
  * - Bhupesh Sharma <bhupesh.sharma at st.com>
  *
  * Borrowed heavily from the C_CAN driver originally written by:
  * Copyright (C) 2007
  * - Sascha Hauer, Marc Kleine-Budde, Pengutronix <s.hauer at pengutronix.de>
  * - Simon Kallweit, intefo AG <simon.kallweit at 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 at ti.com>
  *
  * Borrowed from C_CAN driver
  * Copyright (C) 2010 ST Microelectronics
  * - Bhupesh Sharma <bhupesh.sharma at st.com>
  *
  * Borrowed heavily from the C_CAN driver originally written by:
  * Copyright (C) 2007
  * - Sascha Hauer, Marc Kleine-Budde, Pengutronix <s.hauer at pengutronix.de>
  * - Simon Kallweit, intefo AG <simon.kallweit at 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 at 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/
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://os.inf.tu-dresden.de/pipermail/l4-hackers/attachments/20140826/4bbbf59c/attachment-0001.html>


More information about the l4-hackers mailing list