Do we have boards that use this code? Matthias
On Saturday 24 October 2009 06:17, miaofng wrote: > >From 1f6aaba856fbf484c442eb33cf220774d57fba8d Mon Sep 17 00:00:00 2001 > From: miaofng <miao...@gmail.com> > Date: Fri, 23 Oct 2009 17:06:50 +0800 > Subject: [PATCH] [can] add u-boot sja1000/can support > > Signed-off-by: miaofng <miao...@gmail.com> > --- > Makefile | 1 + > drivers/can/Makefile | 46 ++++ > drivers/can/can_core.c | 266 ++++++++++++++++++++++ > drivers/can/sja1000.c | 584 > ++++++++++++++++++++++++++++++++++++++++++++++++ > drivers/can/sja1000.h | 160 +++++++++++++ > include/can.h | 216 ++++++++++++++++++ > include/can_error.h | 93 ++++++++ > include/candev.h | 46 ++++ > lib_arm/board.c | 2 + > 9 files changed, 1414 insertions(+), 0 deletions(-) > create mode 100755 drivers/can/Makefile > create mode 100755 drivers/can/can_core.c > create mode 100755 drivers/can/sja1000.c > create mode 100755 drivers/can/sja1000.h > create mode 100755 include/can.h > create mode 100755 include/can_error.h > create mode 100755 include/candev.h > mode change 100644 => 100755 lib_arm/board.c > > diff --git a/Makefile b/Makefile > index d6d6368..1ba59f8 100755 > --- a/Makefile > +++ b/Makefile > @@ -203,6 +203,7 @@ LIBS += net/libnet.a > LIBS += disk/libdisk.a > LIBS += drivers/bios_emulator/libatibiosemu.a > LIBS += drivers/block/libblock.a > +LIBS += drivers/can/libcan.a > LIBS += drivers/dma/libdma.a > LIBS += drivers/fpga/libfpga.a > LIBS += drivers/gpio/libgpio.a > diff --git a/drivers/can/Makefile b/drivers/can/Makefile > new file mode 100755 > index 0000000..d3d47bb > --- /dev/null > +++ b/drivers/can/Makefile > @@ -0,0 +1,46 @@ > +# > +# Copyright (C) 2009 miaofng<miao...@126.com> > +# > +# See file CREDITS for list of people who contributed to this > +# project. > +# > +# 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; either version 2 of > +# the License, or (at your option) any later version. > +# > +# This program is distributed in the hope that it will be useful, > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +# GNU General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with this program; if not, write to the Free Software > +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, > +# MA 02111-1307 USA > +# > + > +include $(TOPDIR)/config.mk > + > +LIB := $(obj)libcan.a > + > +COBJS-y += can_core.o > +COBJS-$(CONFIG_DRIVER_SJA1000) += sja1000.o > + > +COBJS := $(sort $(COBJS-y)) > +SRCS := $(COBJS:.o=.c) > +OBJS := $(addprefix $(obj),$(COBJS)) > + > +all: $(LIB) > + > +$(LIB): $(obj).depend $(OBJS) > + $(AR) $(ARFLAGS) $@ $(OBJS) > + > +######################################################################### > + > +# defines $(obj).depend target > +include $(SRCTREE)/rules.mk > + > +sinclude $(obj).depend > + > +######################################################################### > diff --git a/drivers/can/can_core.c b/drivers/can/can_core.c > new file mode 100755 > index 0000000..a723e8a > --- /dev/null > +++ b/drivers/can/can_core.c > @@ -0,0 +1,266 @@ > +/* > + * Copyright (C) 2009 miaofng<miao...@gmail.com> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the version 2 of the GNU General Public License > + * as published by the Free Software Foundation > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > + */ > + > +#include <common.h> > +#include <can.h> > +#include <malloc.h> > + > +#define can_debug printf > +#define can_error printf > + > +#ifdef CONFIG_CMD_CAN > +#ifndef CONFIG_CAN_DEV_MAX > +#define CONFIG_CAN_DEV_MAX 8 > +#endif > + > +static struct can_device *can_devs[CONFIG_CAN_DEV_MAX]; > +#endif > + > +static inline struct can_device* index_to_cdev(int index) > +{ > + return (index<CONFIG_CAN_DEV_MAX)? can_devs[index]:0; > +} > + > +static inline int cdev_to_index(struct can_device *dev) > +{ > + return (dev)?dev->index:-1; > +} > + > +static void canif_tx(struct can_device *dev) > +{ > + struct can_frame *cf; > + int len; > + > + len = buf_pop(&dev->tbuf, (char*)&cf, sizeof(cf)); > + if(len == sizeof(cf)) { > + dev->start_xmit(cf, dev); > + free(cf); > + } > +} > + > +void canif_rx(struct can_frame *cf, struct can_device *dev) > +{ > + int len; > + > + //error frame? > + if(cf->can_id&CAN_ERR_FLAG) > + { > + //error frame, drop it > + free(cf); > + return; > + } > + > + //soft id filter? > + > + //store to cirbuf > + if(dev->rbuf.size == dev->rbuf.totalsize) { > + can_debug("CAN: rx buffer is full\n"); > + dev->stats.rx_dropped ++; > + free(cf); > + return; > + } > + > + buf_push(&dev->rbuf, (char*)&cf, sizeof(cf)); > +} > + > +void canif_wake_queue(struct can_device *dev) > +{ > + canif_start_queue(dev); > + canif_tx(dev); > +} > + > +int can_init(void) > +{ > +#ifdef CONFIG_CMD_CAN > + int index; > + for(index = 0; index < CONFIG_CAN_DEV_MAX; index ++) can_devs[index] = > 0; > + board_can_init(); > +#endif > + return 0; > +} > + > +/* > + * Register the CAN network device > + */ > + #ifndef CONFIG_CAN_BUF_TX_SZ > + #define CONFIG_CAN_BUF_TX_SZ (8*sizeof(void*)) > + #endif > + > + #ifndef CONFIG_CAN_BUF_RX_SZ > + #define CONFIG_CAN_BUF_RX_SZ (8*sizeof(void*)) > + #endif > + > +int register_candev(struct can_device *dev) > +{ > + int ret; > + int index; > + > + //insert into the list > + dev->index = -1; > + for(index =0; index < CONFIG_CAN_DEV_MAX; index ++) > + { > + if(!can_devs[index]) { > + can_devs[index] = dev; > + dev->index = index; > + break; > + } > + } > + if( dev->index < 0) > + can_debug("CAN: too many can devices\n"); > + > + //allocate circbuf for tx and rx > + ret = buf_init(&dev->tbuf, CONFIG_CAN_BUF_TX_SZ); > + if(ret != 1) { > + can_debug("CAN: cann't init cirbuf of tx\n"); > + can_devs[index] = 0; > + return -1; > + } > + ret = buf_init(&dev->rbuf, CONFIG_CAN_BUF_RX_SZ); > + if(ret != 1) { > + can_debug("CAN: cann't init cirbuf of rx\n"); > + can_devs[index] = 0; > + buf_free(&dev->tbuf); > + return -1; > + } > + dev->qstatus = CAN_QUEUE_INIT; > + > + //success > + printf("CAN: %s @index %d\n", dev->name, dev->index); > + return 0; > +} > + > +/* > + * Unregister the CAN network device > + */ > +void unregister_candev(struct can_device *dev) > +{ > + int index = cdev_to_index(dev); > + > + if(index < 0) { > + can_debug("CAN: invalid para\n"); > + return; > + } > + > + //close the dev first > + can_close((int)dev); > + > + //release tx/rx buffer > + buf_free(&dev->tbuf); > + buf_free(&dev->rbuf); > + > + //remove from the list > + can_devs[index] = 0; > +} > + > +//api > +int can_setbrg(int brg, int index) > +{ > + struct can_device *dev = index_to_cdev(index); > + > + if(!dev) { > + can_debug("CAN: invalid para\n"); > + return -1; > + } > + > + if( dev->state != CAN_STATE_STOPPED) { > + can_debug("CAN: invalid dev status<%d>\n", dev->state); > + return -1; > + } > + > + if(dev->setbrg) > + return dev->setbrg(brg, dev); > + > + can_debug("CAN: op not supported by the dev\n"); > + return -1; > +} > + > +int can_open(int index) > +{ > + struct can_device *dev = index_to_cdev(index); > + > + if(!dev) { > + can_debug("CAN: invalid para\n"); > + return 0; > + } > + > + if(dev->state != CAN_STATE_STOPPED) { > + can_debug("CAN: invalid dev status<%d>\n", dev->state); > + return 0; > + } > + > + if(dev && dev->open) dev->open(dev); > + return (int)dev; > +} > + > +void can_close(int dev_id) > +{ > + struct can_device *dev = (struct can_device*) dev_id; > + struct can_frame *cf; > + > + if(!dev) { > + can_debug("CAN: invalid para\n"); > + return; > + } > + > + //can device close > + if(dev->close) dev->close(dev); > + > + //tbuf,rbuf dump > + while(buf_pop(&dev->tbuf, (char*)&cf, sizeof(cf)) ) free(cf); > + while(buf_pop(&dev->rbuf, (char*)&cf, sizeof(cf)) ) free(cf); > +} > + > +//non block write > +int can_send(struct can_frame *cf, int dev_id) > +{ > + struct can_device *dev = (struct can_device*) dev_id; > + > + if(!cf || !dev ) { > + can_debug("CAN: invalid para\n"); > + return -1; > + } > + > + if(dev->tbuf.size == dev->tbuf.totalsize){ //tbuf overflow > + can_debug("CAN: tx buffer is full\n"); > + return -1; > + } > + > + buf_push(&dev->tbuf, (char*)&cf, sizeof(cf)); > + > + //start queue? > + if( dev->qstatus == CAN_QUEUE_READY ) > + canif_tx(dev); > + > + return 0; > +} > + > +//non block read > +struct can_frame* can_recv(int dev_id) > +{ > + struct can_device *dev = (struct can_device*) dev_id; > + struct can_frame *cf; > + int len; > + > + if(!dev ) { > + can_debug("CAN: invalid para\n"); > + return 0; > + } > + > + len = buf_pop(&dev->rbuf, (char*)&cf, sizeof(cf)); > + if(len != sizeof(cf)) return (struct can_frame*)0; > + else return cf; > +} > diff --git a/drivers/can/sja1000.c b/drivers/can/sja1000.c > new file mode 100755 > index 0000000..07560bd > --- /dev/null > +++ b/drivers/can/sja1000.c > @@ -0,0 +1,584 @@ > +/* > + * sja1000.c - Philips SJA1000 network device driver > + * > + * Copyright (c) 2009 miaofng<miao...@gmail.com> > + * > + * Copyright (c) 2003 Matthias Brukner, Trajet Gmbh, Rebenring 33, > + * 38106 Braunschweig, GERMANY > + * > + * Copyright (c) 2002-2007 Volkswagen Group Electronic Research > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * 3. Neither the name of Volkswagen nor the names of its contributors > + * may be used to endorse or promote products derived from this software > + * without specific prior written permission. > + * > + * Alternatively, provided that this notice is retained in full, this > + * software may be distributed under the terms of the GNU General > + * Public License ("GPL") version 2, in which case the provisions of the > + * GPL apply INSTEAD OF those given above. > + * > + * The provided data structures and external interfaces from this code > + * are not restricted to be used by modules with a GPL compatible license. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS > + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT > + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR > + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT > + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT > + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE > + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH > + * DAMAGE. > + * > + * Send feedback to <socketcan-us...@lists.berlios.de> > + * > + */ > + > +#include <common.h> > +#include <asm/io.h> > +#include <can.h> > +#include <malloc.h> > +#include <linux/string.h> > + > +#include "sja1000.h" > + > +#define DRV_NAME "sja1000" > + > +//MODULE_AUTHOR("Oliver Hartkopp <oliver.hartk...@volkswagen.de>"); > +//MODULE_LICENSE("Dual BSD/GPL"); > +//MODULE_DESCRIPTION(DRV_NAME "CAN netdevice driver"); > + > +#define sja_debug printf > + > +/* > + * Flags for sja1000priv.flags > + */ > +#define SJA1000_CUSTOM_IRQ_HANDLER 0x1 > + > +/* > + * SJA1000 private data structure > + */ > +struct sja1000_priv { > + struct can_device can; /* must be the first member */ > + > + /* the lower-layer is responsible for appropriate locking */ > + void* reg_base; /* ioremap'ed address to registers */ > + > + u8 (*read_reg) (const struct sja1000_priv *priv, u8 reg); > + void (*write_reg) (const struct sja1000_priv *priv, u8 reg, u8 val); > +}; > + > +static int set_reset_mode(struct can_device *dev) > +{ > + struct sja1000_priv *priv = candev_priv(dev); > + unsigned char status = priv->read_reg(priv, REG_MOD); > + int i; > + > + /* disable interrupts */ > + priv->write_reg(priv, REG_IER, IRQ_OFF); > + > + for (i = 0; i < 100; i++) { > + /* check reset bit */ > + if (status & MOD_RM) { > + priv->can.state = CAN_STATE_STOPPED; > + return 0; > + } > + > + priv->write_reg(priv, REG_MOD, MOD_RM); /* reset chip */ > + udelay(10); > + status = priv->read_reg(priv, REG_MOD); > + } > + > + //sja_debug("SJA1000: setting into reset mode failed!\n"); > + return -1; > +} > + > +static void set_normal_mode(struct can_device *dev) > +{ > + struct sja1000_priv *priv = candev_priv(dev); > + unsigned char status = priv->read_reg(priv, REG_MOD); > + int i; > + > + for (i = 0; i < 100; i++) { > + /* check reset bit */ > + if ((status & MOD_RM) == 0) { > + priv->can.state = CAN_STATE_ERROR_ACTIVE; > + /* enable all interrupts */ > + priv->write_reg(priv, REG_IER, IRQ_ALL); > + return; > + } > + > + /* set chip to normal mode */ > + priv->write_reg(priv, REG_MOD, 0x00); > + udelay(10); > + status = priv->read_reg(priv, REG_MOD); > + } > + > + sja_debug("sja1...@%d: setting into normal mode failed!\n", dev->index); > +} > + > +static void sja1000_start(struct can_device *dev) > +{ > + struct sja1000_priv *priv = candev_priv(dev); > + > + /* leave reset mode */ > + if (priv->can.state != CAN_STATE_STOPPED) > + set_reset_mode(dev); > + > + /* Clear error counters and error code capture */ > + priv->write_reg(priv, REG_TXERR, 0x0); > + priv->write_reg(priv, REG_RXERR, 0x0); > + priv->read_reg(priv, REG_ECC); > + > + /* leave reset mode */ > + set_normal_mode(dev); > +} > + > +#ifndef CONFIG_SJA1000_CLK_HZ > +#define CONFIG_SJA1000_CLK_HZ 24000000 > +#endif > + > +static int sja1000_setbrg(int brg, struct can_device *dev) > +{ > + struct sja1000_priv *priv = candev_priv(dev); > + int fosc = CONFIG_SJA1000_CLK_HZ; > + int fscl, btr0, btr1; > + u8 sjw = 1; // 0~3 +1 > + u8 brp; // 0~63 +1 > + u8 sam = 1; // 0~1 > + u8 tseg2 = 5; // 0~7 +1 > + u8 tseg1 = 6; // 0~15 +1 > + > + //calculation > + fscl = (1+tseg1+tseg2)*brg; > + brp = (fosc>>1)/fscl; > + if(brg > 250000) sam = 0; > + > + //set register > + btr0 = ((sjw - 1) << 6) | (brp - 1); > + btr1 = (sam << 7) | ((tseg2 -1) << 4) | (tseg1 -1); > + > + sja_debug("sja1...@%d: setting BTR0=0x%02x BTR1=0x%02x\n", dev->index, > btr0, btr1); > + > + priv->write_reg(priv, REG_BTR0, btr0); > + priv->write_reg(priv, REG_BTR1, btr1); > + > + return 0; > +} > + > +/* > + * initialize SJA1000 chip: > + * - reset chip > + * - set output mode > + * - set baudrate > + * - enable interrupts > + * - start operating mode > + */ > +static void chipset_init(struct can_device *dev) > +{ > + struct sja1000_priv *priv = candev_priv(dev); > + > + /* set clock divider and output control register */ > + priv->write_reg(priv, REG_CDR, CDR_PELICAN|CDR_CBP|CDR_CLK_OFF); > + > + /* set acceptance filter (accept all) */ > + priv->write_reg(priv, REG_ACCC0, 0x00); > + priv->write_reg(priv, REG_ACCC1, 0x00); > + priv->write_reg(priv, REG_ACCC2, 0x00); > + priv->write_reg(priv, REG_ACCC3, 0x00); > + > + priv->write_reg(priv, REG_ACCM0, 0xFF); > + priv->write_reg(priv, REG_ACCM1, 0xFF); > + priv->write_reg(priv, REG_ACCM2, 0xFF); > + priv->write_reg(priv, REG_ACCM3, 0xFF); > + > + priv->write_reg(priv, REG_OCR, OCR_TX0_PUSHPULL|OCR_TX1_PUSHPULL| > OCR_MODE_NORMAL); > +} > + > +/* > + * transmit a CAN message > + */ > +static int sja1000_start_xmit(struct can_frame *cf, struct can_device *dev) > +{ > + struct sja1000_priv *priv = candev_priv(dev); > + struct can_device_stats *stats = &dev->stats; > + uint8_t fi; > + uint8_t dlc; > + canid_t id; > + uint8_t dreg; > + int i; > + > + canif_stop_queue(dev); > + > + fi = dlc = cf->can_dlc; > + id = cf->can_id; > + > + if (id & CAN_RTR_FLAG) > + fi |= FI_RTR; > + > + if (id & CAN_EFF_FLAG) { > + fi |= FI_FF; > + dreg = EFF_BUF; > + priv->write_reg(priv, REG_FI, fi); > + priv->write_reg(priv, REG_ID1, (id & 0x1fe00000) >> (5 + 16)); > + priv->write_reg(priv, REG_ID2, (id & 0x001fe000) >> (5 + 8)); > + priv->write_reg(priv, REG_ID3, (id & 0x00001fe0) >> 5); > + priv->write_reg(priv, REG_ID4, (id & 0x0000001f) << 3); > + } else { > + dreg = SFF_BUF; > + priv->write_reg(priv, REG_FI, fi); > + priv->write_reg(priv, REG_ID1, (id & 0x000007f8) >> 3); > + priv->write_reg(priv, REG_ID2, (id & 0x00000007) << 5); > + } > + > + for (i = 0; i < dlc; i++) > + priv->write_reg(priv, dreg++, cf->data[i]); > + priv->write_reg(priv, REG_CMR, CMD_TR); > + > + stats->tx_bytes += dlc; > + > + return 0; > +} > + > +static void sja1000_rx(struct can_device *dev) > +{ > + struct sja1000_priv *priv = candev_priv(dev); > + struct can_device_stats *stats = &dev->stats; > + struct can_frame *cf; > + uint8_t fi; > + uint8_t dreg; > + canid_t id; > + uint8_t dlc; > + int i; > + > + cf = malloc(sizeof(struct can_frame)); > + if (cf == NULL) { > + sja_debug("SJA1000%d: out of mem!\n",dev->index); > + return; > + } > + > + fi = priv->read_reg(priv, REG_FI); > + dlc = fi & 0x0F; > + > + if (fi & FI_FF) { > + /* extended frame format (EFF) */ > + dreg = EFF_BUF; > + id = (priv->read_reg(priv, REG_ID1) << (5 + 16)) > + | (priv->read_reg(priv, REG_ID2) << (5 + 8)) > + | (priv->read_reg(priv, REG_ID3) << 5) > + | (priv->read_reg(priv, REG_ID4) >> 3); > + id |= CAN_EFF_FLAG; > + } else { > + /* standard frame format (SFF) */ > + dreg = SFF_BUF; > + id = (priv->read_reg(priv, REG_ID1) << 3) > + | (priv->read_reg(priv, REG_ID2) >> 5); > + } > + > + if (fi & FI_RTR) > + id |= CAN_RTR_FLAG; > + > + memset(cf, 0, sizeof(struct can_frame)); > + cf->can_id = id; > + cf->can_dlc = dlc; > + for (i = 0; i < dlc; i++) > + cf->data[i] = priv->read_reg(priv, dreg++); > + > + while (i < 8) > + cf->data[i++] = 0; > + > + /* release receive buffer */ > + priv->write_reg(priv, REG_CMR, CMD_RRB); > + > + canif_rx(cf, dev); > + > + //dev->last_rx = jiffies; > + stats->rx_packets++; > + stats->rx_bytes += dlc; > +} > + > +static int sja1000_err(struct can_device *dev, uint8_t isrc, uint8_t status) > +{ > + struct sja1000_priv *priv = candev_priv(dev); > + struct can_device_stats *stats = &dev->stats; > + struct can_frame *cf; > + enum can_state state = priv->can.state; > + uint8_t ecc, alc; > + > + cf = malloc(sizeof(struct can_frame)); > + if (cf == NULL) > + { > + sja_debug("sja1...@%d: out of mem!\n", dev->index); > + return -1; > + } > + memset(cf, 0, sizeof(struct can_frame)); > + cf->can_id = CAN_ERR_FLAG; > + cf->can_dlc = CAN_ERR_DLC; > + > + if (isrc & IRQ_DOI) { > + /* data overrun interrupt */ > + sja_debug("sja1...@%d: data overrun interrupt\n", dev->index); > + cf->can_id |= CAN_ERR_CRTL; > + cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; > + //stats->rx_over_errors++; > + stats->rx_errors++; > + priv->write_reg(priv, REG_CMR, CMD_CDO); /* clear bit */ > + } > + > + if (isrc & IRQ_EI) { > + /* error warning interrupt */ > + sja_debug("sja1...@%d: error warning interrupt\n", dev->index); > + > + if (status & SR_BS) { > + state = CAN_STATE_BUS_OFF; > + cf->can_id |= CAN_ERR_BUSOFF; > + //can_bus_off(dev); > + } else if (status & SR_ES) { > + state = CAN_STATE_ERROR_WARNING; > + } else > + state = CAN_STATE_ERROR_ACTIVE; > + } > + if (isrc & IRQ_BEI) { > + /* bus error interrupt */ > + priv->can.stats.bus_error++; > + stats->rx_errors++; > + > + ecc = priv->read_reg(priv, REG_ECC); > + > + cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; > + > + switch (ecc & ECC_MASK) { > + case ECC_BIT: > + cf->data[2] |= CAN_ERR_PROT_BIT; > + break; > + case ECC_FORM: > + cf->data[2] |= CAN_ERR_PROT_FORM; > + break; > + case ECC_STUFF: > + cf->data[2] |= CAN_ERR_PROT_STUFF; > + break; > + default: > + cf->data[2] |= CAN_ERR_PROT_UNSPEC; > + cf->data[3] = ecc & ECC_SEG; > + break; > + } > + /* error occured during transmission? */ > + if ((ecc & ECC_DIR) == 0) > + cf->data[2] |= CAN_ERR_PROT_TX; > + } > + if (isrc & IRQ_EPI) { > + /* error passive interrupt */ > + sja_debug("sja1...@%d: error passive interrupt\n", dev->index); > + if (status & SR_ES) > + state = CAN_STATE_ERROR_PASSIVE; > + else > + state = CAN_STATE_ERROR_ACTIVE; > + } > + if (isrc & IRQ_ALI) { > + /* arbitration lost interrupt */ > + sja_debug("sja1...@%d: arbitration lost interrupt\n", > dev->index); > + alc = priv->read_reg(priv, REG_ALC); > + priv->can.stats.arbitration_lost++; > + stats->rx_errors++; > + cf->can_id |= CAN_ERR_LOSTARB; > + cf->data[0] = alc & 0x1f; > + } > + > + if (state != priv->can.state && (state == CAN_STATE_ERROR_WARNING || > + state == CAN_STATE_ERROR_PASSIVE)) { > + uint8_t rxerr = priv->read_reg(priv, REG_RXERR); > + uint8_t txerr = priv->read_reg(priv, REG_TXERR); > + cf->can_id |= CAN_ERR_CRTL; > + if (state == CAN_STATE_ERROR_WARNING) { > + priv->can.stats.error_warning++; > + cf->data[1] = (txerr > rxerr) ? > + CAN_ERR_CRTL_TX_WARNING : > + CAN_ERR_CRTL_RX_WARNING; > + } else { > + priv->can.stats.error_passive++; > + cf->data[1] = (txerr > rxerr) ? > + CAN_ERR_CRTL_TX_PASSIVE : > + CAN_ERR_CRTL_RX_PASSIVE; > + } > + } > + > + priv->can.state = state; > + > + canif_rx(cf,dev); > + > + return 0; > +} > + > +#define SJA1000_MAX_IRQ 20 /* max. number of interrupts handled in ISR */ > + > +int sja1000_interrupt(struct can_device *dev) > +{ > + struct sja1000_priv *priv = candev_priv(dev); > + struct can_device_stats *stats = &dev->stats; > + uint8_t isrc, status; > + int n = 0; > + > + /* Shared interrupts and IRQ off? */ > + if (priv->read_reg(priv, REG_IER) == IRQ_OFF) > + return -1; > + > + while ((isrc = priv->read_reg(priv, REG_IR)) && (n < SJA1000_MAX_IRQ)) { > + n++; > + status = priv->read_reg(priv, REG_SR); > + > + if (isrc & IRQ_WUI) > + sja_debug("sja1...@%d: wakeup interrupt\n", dev->index); > + > + if (isrc & IRQ_TI) { > + /* transmission complete interrupt */ > + stats->tx_packets++; > + > + //can_get_echo_skb(dev, 0); > + canif_wake_queue(dev); > + } > + if (isrc & IRQ_RI) { > + /* receive interrupt */ > + while (status & SR_RBS) { > + sja1000_rx(dev); > + status = priv->read_reg(priv, REG_SR); > + } > + } > + if (isrc & (IRQ_DOI | IRQ_EI | IRQ_BEI | IRQ_EPI | IRQ_ALI)) { > + /* error interrupt */ > + if (sja1000_err(dev, isrc, status)) > + break; > + } > + } > + > + if (n >= SJA1000_MAX_IRQ) > + sja_debug("sja1...@%d: %d messages handled in ISR", dev->index, > n); > + > + return (n) ? 0 : -1; > +} > + > +static int sja1000_open(struct can_device *dev) > +{ > + /* set chip into reset mode */ > + set_reset_mode(dev); > + > + /* register interrupt handler, if not done by the device driver */ > +#ifdef CONFIG_USBCAN > + extern int request_irq_usbcan(int (*isr)(struct can_device*), struct > can_device*); > + int err = request_irq_usbcan(&sja1000_interrupt, dev); > + if (err) { > + sja_debug("sja1...@%d: unable to request the irq\n", > dev->index); > + return -1; > + } > +#endif > + > + /* init and start chi */ > + sja1000_start(dev); > + > + //priv->open_time = jiffies; > + canif_start_queue(dev); > + > + return 0; > +} > + > +static int sja1000_close(struct can_device *dev) > +{ > + canif_stop_queue(dev); > + set_reset_mode(dev); > + > + //can_free_irq(dev->irq, (void *)dev); > + > + return 0; > +} > + > +static int sja1000_probe_chip(struct can_device *dev) > +{ > + struct sja1000_priv *priv = candev_priv(dev); > + int ret; > + > + ret = set_reset_mode(dev); > + if(ret) { > + sja_debug("%s: probing @0x%x failed\n", DRV_NAME, > (u32)(priv->reg_base)); > + return -1; > + } > + > + return 0; > +} > + > +int register_sja1000dev(struct can_device *dev) > +{ > + if (sja1000_probe_chip(dev)) > + return -1; > + > + strcpy(dev->name, DRV_NAME); > + dev->setbrg = sja1000_setbrg; > + dev->open = sja1000_open; > + dev->start_xmit = sja1000_start_xmit; > + dev->close = sja1000_close; > + > + set_reset_mode(dev); > + chipset_init(dev); > + > + return register_candev(dev); > +} > + > +void unregister_sja1000dev(struct can_device *dev) > +{ > + set_reset_mode(dev); > + unregister_candev(dev); > +} > + > + > +static u8 sja1000_read_reg(const struct sja1000_priv *priv, u8 reg) > +{ > +#if (CONFIG_USBCAN == 1) > + writeb(reg, priv->reg_base+4); //addr latch > + return readb(priv->reg_base); > +#else > + return writeb(priv->reg_base + reg); > +#endif > +} > + > +static void sja1000_write_reg(const struct sja1000_priv *priv, u8 reg, u8 > val) > +{ > +#if (CONFIG_USBCAN == 1) > + writeb(reg, priv->reg_base+4); //addr latch > + writeb(val, priv->reg_base); > +#else > + return readb(val, priv->reg_base + reg); > +#endif > +} > + > +int sja1000_init(u32 reg_base) > +{ > + struct sja1000_priv * priv = malloc(sizeof(struct sja1000_priv)); > + if(priv == NULL) { > + sja_debug("SJA1000: out of mem!!!\n"); > + return -1; > + } > + > + memset(priv, 0, sizeof(priv)); > + priv->reg_base = (void*)reg_base; > + priv->read_reg = sja1000_read_reg; > + priv->write_reg = sja1000_write_reg; > + > + if( register_sja1000dev(&priv->can) ) > + { > + free(priv); > + //sja_debug("SJA1000: register device fail!!!\n"); > + return -1; > + } > + > + return 0; > +} > diff --git a/drivers/can/sja1000.h b/drivers/can/sja1000.h > new file mode 100755 > index 0000000..6311f75 > --- /dev/null > +++ b/drivers/can/sja1000.h > @@ -0,0 +1,160 @@ > +/* > + * sja1000.h - Philips SJA1000 network device driver > + * > + * Copyright (C) 2009 miaofng<miao...@126.com> > + * Copyright (c) 2003 Matthias Brukner, Trajet Gmbh, Rebenring 33, > + * 38106 Braunschweig, GERMANY > + * > + * Copyright (c) 2002-2007 Volkswagen Group Electronic Research > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * 3. Neither the name of Volkswagen nor the names of its contributors > + * may be used to endorse or promote products derived from this software > + * without specific prior written permission. > + * > + * Alternatively, provided that this notice is retained in full, this > + * software may be distributed under the terms of the GNU General > + * Public License ("GPL") version 2, in which case the provisions of the > + * GPL apply INSTEAD OF those given above. > + * > + * The provided data structures and external interfaces from this code > + * are not restricted to be used by modules with a GPL compatible license. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS > + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT > + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR > + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT > + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT > + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE > + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH > + * DAMAGE. > + * > + * Send feedback to <socketcan-us...@lists.berlios.de> > + * > + */ > + > +#ifndef SJA1000_DEV_H > +#define SJA1000_DEV_H > + > +/* SJA1000 registers - manual section 6.4 (Pelican Mode) */ > +#define REG_MOD 0x00 > +#define REG_CMR 0x01 > +#define REG_SR 0x02 > +#define REG_IR 0x03 > +#define REG_IER 0x04 > +#define REG_ALC 0x0B > +#define REG_ECC 0x0C > +#define REG_EWL 0x0D > +#define REG_RXERR 0x0E > +#define REG_TXERR 0x0F > +#define REG_ACCC0 0x10 > +#define REG_ACCC1 0x11 > +#define REG_ACCC2 0x12 > +#define REG_ACCC3 0x13 > +#define REG_ACCM0 0x14 > +#define REG_ACCM1 0x15 > +#define REG_ACCM2 0x16 > +#define REG_ACCM3 0x17 > +#define REG_RMC 0x1D > +#define REG_RBSA 0x1E > + > +/* Common registers - manual section 6.5 */ > +#define REG_BTR0 0x06 > +#define REG_BTR1 0x07 > +#define REG_OCR 0x08 > +#define REG_CDR 0x1F > + > +#define REG_FI 0x10 > +#define SFF_BUF 0x13 > +#define EFF_BUF 0x15 > + > +#define FI_FF 0x80 > +#define FI_RTR 0x40 > + > +#define REG_ID1 0x11 > +#define REG_ID2 0x12 > +#define REG_ID3 0x13 > +#define REG_ID4 0x14 > + > +#define CAN_RAM 0x20 > + > +/* mode register */ > +#define MOD_RM 0x01 > +#define MOD_LOM 0x02 > +#define MOD_STM 0x04 > +#define MOD_AFM 0x08 > +#define MOD_SM 0x10 > + > +/* commands */ > +#define CMD_SRR 0x10 > +#define CMD_CDO 0x08 > +#define CMD_RRB 0x04 > +#define CMD_AT 0x02 > +#define CMD_TR 0x01 > + > +/* interrupt sources */ > +#define IRQ_BEI 0x80 > +#define IRQ_ALI 0x40 > +#define IRQ_EPI 0x20 > +#define IRQ_WUI 0x10 > +#define IRQ_DOI 0x08 > +#define IRQ_EI 0x04 > +#define IRQ_TI 0x02 > +#define IRQ_RI 0x01 > +#define IRQ_ALL 0xFF > +#define IRQ_OFF 0x00 > + > +/* status register content */ > +#define SR_BS 0x80 > +#define SR_ES 0x40 > +#define SR_TS 0x20 > +#define SR_RS 0x10 > +#define SR_TCS 0x08 > +#define SR_TBS 0x04 > +#define SR_DOS 0x02 > +#define SR_RBS 0x01 > + > +#define SR_CRIT (SR_BS|SR_ES) > + > +/* ECC register */ > +#define ECC_SEG 0x1F > +#define ECC_DIR 0x20 > +#define ECC_ERR 6 > +#define ECC_BIT 0x00 > +#define ECC_FORM 0x40 > +#define ECC_STUFF 0x80 > +#define ECC_MASK 0xc0 > + > +/* clock divider register */ > +#define CDR_CLKOUT_MASK 0x07 > +#define CDR_CLK_OFF 0x08 /* Clock off (CLKOUT pin) */ > +#define CDR_RXINPEN 0x20 /* TX1 output is RX irq output */ > +#define CDR_CBP 0x40 /* CAN input comparator bypass */ > +#define CDR_PELICAN 0x80 /* PeliCAN mode */ > + > +/* output control register */ > +#define OCR_MODE_BIPHASE 0x00 > +#define OCR_MODE_TEST 0x01 > +#define OCR_MODE_NORMAL 0x02 > +#define OCR_MODE_CLOCK 0x03 > +#define OCR_TX0_INVERT 0x04 > +#define OCR_TX0_PULLDOWN 0x08 > +#define OCR_TX0_PULLUP 0x10 > +#define OCR_TX0_PUSHPULL 0x18 > +#define OCR_TX1_INVERT 0x20 > +#define OCR_TX1_PULLDOWN 0x40 > +#define OCR_TX1_PULLUP 0x80 > +#define OCR_TX1_PUSHPULL 0xc0 > +#endif /* SJA1000_DEV_H */ > diff --git a/include/can.h b/include/can.h > new file mode 100755 > index 0000000..55e6643 > --- /dev/null > +++ b/include/can.h > @@ -0,0 +1,216 @@ > +/* > + * linux/can.h > + * > + * Definitions for CAN network layer (socket addr / CAN frame / CAN filter) > + * > + * Copyright (C) 2009 miaofng<miao...@gmail.com> > + * > + * Authors: Oliver Hartkopp <oliver.hartk...@volkswagen.de> > + * Urs Thuermann <urs.thuerm...@volkswagen.de> > + * Copyright (c) 2002-2007 Volkswagen Group Electronic Research > + * All rights reserved. > + * > + * Send feedback to <socketcan-us...@lists.berlios.de> > + * > + */ > + > +#ifndef CAN_H > +#define CAN_H > + > +#include <linux/types.h> > +#include <can_error.h> > +#include <circbuf.h> > +#include <candev.h> > + > +/* controller area network (CAN) kernel definitions */ > + > +/* special address description flags for the CAN_ID */ > +#define CAN_EFF_FLAG 0x80000000U /* EFF/SFF is set in the MSB */ > +#define CAN_RTR_FLAG 0x40000000U /* remote transmission request */ > +#define CAN_ERR_FLAG 0x20000000U /* error frame */ > + > +/* valid bits in CAN ID for frame formats */ > +#define CAN_SFF_MASK 0x000007FFU /* standard frame format (SFF) */ > +#define CAN_EFF_MASK 0x1FFFFFFFU /* extended frame format (EFF) */ > +#define CAN_ERR_MASK 0x1FFFFFFFU /* omit EFF, RTR, ERR flags */ > + > +/* > + * Controller Area Network Identifier structure > + * > + * bit 0-28 : CAN identifier (11/29 bit) > + * bit 29 : error frame flag (0 = data frame, 1 = error frame) > + * bit 30 : remote transmission request flag (1 = rtr frame) > + * bit 31 : frame format flag (0 = standard 11 bit, 1 = extended 29 bit) > + */ > +typedef __u32 canid_t; > + > +/** > + * struct can_frame - basic CAN frame structure > + * @can_id: the CAN ID of the frame and CAN_*_FLAG flags, see above. > + * @can_dlc: the data length field of the CAN frame > + * @data: the CAN frame payload. > + */ > +struct can_frame { > + canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */ > + __u8 can_dlc; /* data length code: 0 .. 8 */ > + __u8 data[8] __attribute__((aligned(8))); > +}; > + > +/** > + * struct can_filter - CAN ID based filter in can_register(). > + * @can_id: relevant bits of CAN ID which are not masked out. > + * @can_mask: CAN mask (see description) > + * > + * Description: > + * A filter matches, when > + * > + * <received_can_id> & mask == can_id & mask > + * > + * The filter can be inverted (CAN_INV_FILTER bit set in can_id) or it can > + * filter for error frames (CAN_ERR_FLAG bit set in mask). > + */ > +struct can_filter { > + canid_t can_id; > + canid_t can_mask; > + > + struct can_filter* next; > +}; > + > +#define CAN_INV_FILTER 0x20000000U /* to be set in can_filter.can_id */ > + > +//can_device.state > +enum can_state { > + CAN_STATE_ERROR_ACTIVE = 0, /* RX/TX error count < 96 */ > + CAN_STATE_ERROR_WARNING, /* RX/TX error count < 128 */ > + CAN_STATE_ERROR_PASSIVE, /* RX/TX error count < 256 */ > + CAN_STATE_BUS_OFF, /* RX/TX error count >= 256 */ > + CAN_STATE_STOPPED, /* Device is stopped */ > + CAN_STATE_SLEEPING, /* Device is sleeping */ > + CAN_STATE_MAX > +}; > + > +//can_device.stats, refer to net_device_stats > +struct can_device_stats > +{ > + unsigned long rx_packets; /* total packets received > */ > + unsigned long tx_packets; /* total packets transmitted > */ > + unsigned long rx_bytes; /* total bytes received > */ > + unsigned long tx_bytes; /* total bytes transmitted > */ > + unsigned long rx_errors; /* bad packets received > */ > + unsigned long tx_errors; /* packet transmit problems > */ > + unsigned long rx_dropped; /* no space in linux buffers > */ > + unsigned long tx_dropped; /* no space available in linux > */ > + unsigned long multicast; /* multicast packets received > */ > + unsigned long collisions; > + > + //can stats > + unsigned long error_passive; > + unsigned long error_warning; > + unsigned long arbitration_lost; > + unsigned long bus_error; > +}; > + > +/*queue status definition*/ > +#define CAN_QUEUE_INIT 0 > +#define CAN_QUEUE_READY 1 > +#define CAN_QUEUE_BUSY 2 > + > +#define NAMESIZE_CAN 8 > + > +struct can_device { > + //can core readonly > + char name[NAMESIZE_CAN]; > + enum can_state state; > + struct can_device_stats stats; > + > + //can dev methods > + int (*setbrg)(int, struct can_device*); > + int (*setfilter)(struct can_filter*, struct can_device*); > + int (*open) (struct can_device*); > + int (*start_xmit) (struct can_frame*, struct can_device*); > + int (*close)(struct can_device*); > + > + //can_core private > + int qstatus; //queue status > + circbuf_t tbuf; //tx buffer > + circbuf_t rbuf; //rx buffer > + //struct can_device *next; > + int index; > +}; > + > +//help routines > +static inline void *candev_priv(const struct can_device *dev) { return (void > *) dev; } > +int register_candev(struct can_device*); > +void unregister_candev(struct can_device*); > +void canif_rx(struct can_frame*, struct can_device*); > + > +/* * > + * these 3 functions are used to set the queue status > + * > + */ > +static inline void canif_stop_queue(struct can_device *dev) {dev->qstatus = > CAN_QUEUE_BUSY;} > +static inline void canif_start_queue(struct can_device *dev) {dev->qstatus = > CAN_QUEUE_READY;} > +void canif_wake_queue(struct can_device*); > + > +//note: these functions must be called before can_open() > +int can_init(void); > + > +/** > + * function can_setbrg - set the bus speed of can device > + * @brg bus speed to set, unit bps, such as: 250000,1000000 and > etc > + * @index device to set the speed, should be 0,1,2,.... > + * @return success->0, or fail->-1 > + * description: > + * please set the speed when the device in reset mode. > + */ > +int can_setbrg(int brg, int index); > + > +/** > + * function can_setfilter - set the can id filter > + * @filter filter list to be set > + * @index device to do the operation, such as 0,1,2 ... > + * @return success->0, or fail->-1 > + * description: > + * please set the filter when the device in reset mode. > + */ > +int can_setfilter(struct can_filter *filter, int index); > + > +/** > + * function can_open - open a specified can device(or channel) for read/write > + * @index index of the can channel to open, value as 0,1,2 ... > + * @return device id, for can_send/can_recv ... , in case of fail, return 0 > + * description: > + * can device will leave the reset mode by this operation. > + */ > +int can_open(int index); > + > +/** > + * function can_send - send a can frame > + * @cf frame to be sent > + * @dev_id device to do 'send' operation > + * @return success->0, or fail->-1 > + * description: > + * this is non block operation. can_core will store the frame pointer to > the tx cirbuf. > + */ > +int can_send(struct can_frame *cf, int dev_id); > + > +/** > + * function can_recv - get a can frame from the specified can device(or > channel) > + * @dev_id can device to read > + * @return success-> the pointer to a can frame, fail->0 > + * description: > + * this is non block operation. can_core will get a frame pointer from the > rx cirbuf of the device. > + * the memory of the frame should be released by caller. > + */ > +struct can_frame* can_recv(int dev_id); > + > +/** > + * function can_close - close a specified can device(or channel) > + * @dev_id can device to close > + * description: > + * can_close will do following operation: > + * 1) dump the device's tx/rx buffer > + * 2) set device into reset mode > + */ > +void can_close(int dev_id); > +#endif /* CAN_H */ > diff --git a/include/can_error.h b/include/can_error.h > new file mode 100755 > index 0000000..d4127fd > --- /dev/null > +++ b/include/can_error.h > @@ -0,0 +1,93 @@ > +/* > + * linux/can/error.h > + * > + * Definitions of the CAN error frame to be filtered and passed to the user. > + * > + * Author: Oliver Hartkopp <oliver.hartk...@volkswagen.de> > + * Copyright (c) 2002-2007 Volkswagen Group Electronic Research > + * All rights reserved. > + * > + * Send feedback to <socketcan-us...@lists.berlios.de> > + * > + */ > + > +#ifndef CAN_ERROR_H > +#define CAN_ERROR_H > + > +#define CAN_ERR_DLC 8 /* dlc for error frames */ > + > +/* error class (mask) in can_id */ > +#define CAN_ERR_TX_TIMEOUT 0x00000001U /* TX timeout (by netdevice driver) > */ > +#define CAN_ERR_LOSTARB 0x00000002U /* lost arbitration / data[0] > */ > +#define CAN_ERR_CRTL 0x00000004U /* controller problems / data[1] > */ > +#define CAN_ERR_PROT 0x00000008U /* protocol violations / data[2..3] > */ > +#define CAN_ERR_TRX 0x00000010U /* transceiver status / data[4] > */ > +#define CAN_ERR_ACK 0x00000020U /* received no ACK on transmission > */ > +#define CAN_ERR_BUSOFF 0x00000040U /* bus off */ > +#define CAN_ERR_BUSERROR 0x00000080U /* bus error (may flood!) */ > +#define CAN_ERR_RESTARTED 0x00000100U /* controller restarted */ > + > +/* arbitration lost in bit ... / data[0] */ > +#define CAN_ERR_LOSTARB_UNSPEC 0x00 /* unspecified */ > + /* else bit number in bitstream */ > + > +/* error status of CAN-controller / data[1] */ > +#define CAN_ERR_CRTL_UNSPEC 0x00 /* unspecified */ > +#define CAN_ERR_CRTL_RX_OVERFLOW 0x01 /* RX buffer overflow */ > +#define CAN_ERR_CRTL_TX_OVERFLOW 0x02 /* TX buffer overflow */ > +#define CAN_ERR_CRTL_RX_WARNING 0x04 /* reached warning level for RX errors > */ > +#define CAN_ERR_CRTL_TX_WARNING 0x08 /* reached warning level for TX errors > */ > +#define CAN_ERR_CRTL_RX_PASSIVE 0x10 /* reached error passive status RX */ > +#define CAN_ERR_CRTL_TX_PASSIVE 0x20 /* reached error passive status TX */ > + /* (at least one error counter exceeds */ > + /* the protocol-defined level of 127) */ > + > +/* error in CAN protocol (type) / data[2] */ > +#define CAN_ERR_PROT_UNSPEC 0x00 /* unspecified */ > +#define CAN_ERR_PROT_BIT 0x01 /* single bit error */ > +#define CAN_ERR_PROT_FORM 0x02 /* frame format error */ > +#define CAN_ERR_PROT_STUFF 0x04 /* bit stuffing error */ > +#define CAN_ERR_PROT_BIT0 0x08 /* unable to send dominant bit */ > +#define CAN_ERR_PROT_BIT1 0x10 /* unable to send recessive bit */ > +#define CAN_ERR_PROT_OVERLOAD 0x20 /* bus overload */ > +#define CAN_ERR_PROT_ACTIVE 0x40 /* active error announcement */ > +#define CAN_ERR_PROT_TX 0x80 /* error occured on transmission */ > + > +/* error in CAN protocol (location) / data[3] */ > +#define CAN_ERR_PROT_LOC_UNSPEC 0x00 /* unspecified */ > +#define CAN_ERR_PROT_LOC_SOF 0x03 /* start of frame */ > +#define CAN_ERR_PROT_LOC_ID28_21 0x02 /* ID bits 28 - 21 (SFF: 10 - 3) */ > +#define CAN_ERR_PROT_LOC_ID20_18 0x06 /* ID bits 20 - 18 (SFF: 2 - 0 )*/ > +#define CAN_ERR_PROT_LOC_SRTR 0x04 /* substitute RTR (SFF: RTR) */ > +#define CAN_ERR_PROT_LOC_IDE 0x05 /* identifier extension */ > +#define CAN_ERR_PROT_LOC_ID17_13 0x07 /* ID bits 17-13 */ > +#define CAN_ERR_PROT_LOC_ID12_05 0x0F /* ID bits 12-5 */ > +#define CAN_ERR_PROT_LOC_ID04_00 0x0E /* ID bits 4-0 */ > +#define CAN_ERR_PROT_LOC_RTR 0x0C /* RTR */ > +#define CAN_ERR_PROT_LOC_RES1 0x0D /* reserved bit 1 */ > +#define CAN_ERR_PROT_LOC_RES0 0x09 /* reserved bit 0 */ > +#define CAN_ERR_PROT_LOC_DLC 0x0B /* data length code */ > +#define CAN_ERR_PROT_LOC_DATA 0x0A /* data section */ > +#define CAN_ERR_PROT_LOC_CRC_SEQ 0x08 /* CRC sequence */ > +#define CAN_ERR_PROT_LOC_CRC_DEL 0x18 /* CRC delimiter */ > +#define CAN_ERR_PROT_LOC_ACK 0x19 /* ACK slot */ > +#define CAN_ERR_PROT_LOC_ACK_DEL 0x1B /* ACK delimiter */ > +#define CAN_ERR_PROT_LOC_EOF 0x1A /* end of frame */ > +#define CAN_ERR_PROT_LOC_INTERM 0x12 /* intermission */ > + > +/* error status of CAN-transceiver / data[4] */ > +/* CANH CANL */ > +#define CAN_ERR_TRX_UNSPEC 0x00 /* 0000 0000 */ > +#define CAN_ERR_TRX_CANH_NO_WIRE 0x04 /* 0000 0100 */ > +#define CAN_ERR_TRX_CANH_SHORT_TO_BAT 0x05 /* 0000 0101 */ > +#define CAN_ERR_TRX_CANH_SHORT_TO_VCC 0x06 /* 0000 0110 */ > +#define CAN_ERR_TRX_CANH_SHORT_TO_GND 0x07 /* 0000 0111 */ > +#define CAN_ERR_TRX_CANL_NO_WIRE 0x40 /* 0100 0000 */ > +#define CAN_ERR_TRX_CANL_SHORT_TO_BAT 0x50 /* 0101 0000 */ > +#define CAN_ERR_TRX_CANL_SHORT_TO_VCC 0x60 /* 0110 0000 */ > +#define CAN_ERR_TRX_CANL_SHORT_TO_GND 0x70 /* 0111 0000 */ > +#define CAN_ERR_TRX_CANL_SHORT_TO_CANH 0x80 /* 1000 0000 */ > + > +/* controller specific additional information / data[5..7] */ > + > +#endif /* CAN_ERROR_H */ > diff --git a/include/candev.h b/include/candev.h > new file mode 100755 > index 0000000..0e0dee7 > --- /dev/null > +++ b/include/candev.h > @@ -0,0 +1,46 @@ > +/* > + * (C) Copyright 2009 miaofng<miao...@gmail.com> > + * > + * > + * See file CREDITS for list of people who contributed to this > + * project. > + * > + * 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; either version 2 of > + * the License, or (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, > + * MA 02111-1307 USA > + */ > + > +/* > + * netdev.h - definitions an prototypes for network devices > + */ > + > +#ifndef _CANDEV_H_ > +#define _CANDEV_H_ > + > +/* > + * Board and CPU-specific initialization functions > + * board_eth_init() has highest priority. cpu_eth_init() only > + * gets called if board_eth_init() isn't instantiated or fails. > + * Return values: > + * 0: success > + * -1: failure > + */ > + > +int board_can_init(void); > +void board_can_update(void); > + > +/* Driver initialization prototypes */ > +int sja1000_init(u32 reg_base); > + > +#endif /* _CANDEV_H_ */ > diff --git a/lib_arm/board.c b/lib_arm/board.c > old mode 100644 > new mode 100755 > index 5e3d7f6..aa11dd3 > --- a/lib_arm/board.c > +++ b/lib_arm/board.c > @@ -356,6 +356,8 @@ void start_armboot (void) > serial_initialize(); > #endif > > + can_init(); > + > /* IP Address */ > gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr"); > -- ------------------------------------------------------------------------- Dipl.-Ing. Matthias Fuchs Head of System Design esd electronic system design gmbh Vahrenwalder Str. 207 - 30165 Hannover - GERMANY Phone: +49-511-37298-0 - Fax: +49-511-37298-68 Please visit our homepage http://www.esd.eu Quality Products - Made in Germany ------------------------------------------------------------------------- Geschäftsführer: Klaus Detering, Dr. Werner Schulze Amtsgericht Hannover HRB 51373 - VAT-ID DE 115672832 ------------------------------------------------------------------------- _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot