Hi Wolfgang, this patch conflicts with my simple SJA header posted some days ago
http://lists.denx.de/pipermail/u-boot/2009-October/063097.html together with a fix for two of our boards - which has not much to do with CAN. WD asked me to use a C struct to access the SJA1000. http://lists.denx.de/pipermail/u-boot/2009-October/062902.html So where does this bring us? Either we want to use C structs for everything or decide it from patch to patch :-( Matthias On Sunday 01 November 2009 12:33, Wolfgang Grandegger wrote: > From: Wolfgang Grandegger <w...@denx.de> > > Signed-off-by: Wolfgang Grandegger <w...@denx.de> > --- > drivers/can/Makefile | 3 +- > drivers/can/sja1000.c | 223 > +++++++++++++++++++++++++++++++++++++++++++++++++ > include/sja1000.h | 159 +++++++++++++++++++++++++++++++++++ > 3 files changed, 384 insertions(+), 1 deletions(-) > create mode 100644 drivers/can/sja1000.c > create mode 100644 include/sja1000.h > > diff --git a/drivers/can/Makefile b/drivers/can/Makefile > index 74d2ff5..e2b6bd6 100644 > --- a/drivers/can/Makefile > +++ b/drivers/can/Makefile > @@ -25,7 +25,8 @@ include $(TOPDIR)/config.mk > > LIB := $(obj)libcan.a > > -COBJS-$(CONFIG_CAN) += can.o > +COBJS-$(CONFIG_CAN) += can.o > +COBJS-$(CONFIG_CAN_SJA1000) += sja1000.o > > COBJS := $(COBJS-y) > SRCS := $(COBJS:.o=.c) > diff --git a/drivers/can/sja1000.c b/drivers/can/sja1000.c > new file mode 100644 > index 0000000..b75f01c > --- /dev/null > +++ b/drivers/can/sja1000.c > @@ -0,0 +1,223 @@ > +/* > + * (C) Copyright 2007-2009, Wolfgang Grandegger <w...@denx.de> > + * > + * Derived from Xenomai's RT-Socket-CAN driver for SJA1000: > + * > + * Copyright (C) 2005,2006 Sebastian Smolorz > + * <sebastian.smol...@stud.uni-hannover.de> > + * > + * Copyright (C) 2005, Sascha Hauer, Pengutronix > + * > + * 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 <common.h> > +#include <asm/io.h> > + > +#include <can.h> > +#include <sja1000.h> > + > +#define SJA1000_OCR (SJA_OCR_MODE_NORMAL | SJA_OCR_TX0_PUSHPULL) > +#define SJA1000_CDR SJA_CDR_CAN_MODE > + > +/* > + * Basic functions to access registers > + */ > +#define sja1000_read_reg(dev, reg) \ > + in_8 ((volatile u8 *)((dev)->base + (reg))) > + > +#define sja1000_write_reg(dev, reg, value) \ > + out_8 ((volatile u8 *)((dev)->base + (reg)), value) > + > +/* > + * Baudrate table > + */ > + > +static u16 sja1000_btr0btr1[] = { > + 0x031c, /* 125K */ > + 0x011c, /* 250K */ > + 0x001c, /* 500K */ > +}; > + > +int sja1000_init (struct can_dev *dev, unsigned int ibaud) > +{ > + int i, wait = 1000; > + u16 btr0btr1; > + > + /* Disable the controller's interrupts */ > + sja1000_write_reg (dev, SJA_IER, 0x00); > + > + /* Set reset mode bit */ > + sja1000_write_reg (dev, SJA_MOD, SJA_MOD_RM); > + > + /* Read reset mode bit, multiple tests */ > + do { > + udelay (100); > + if (sja1000_read_reg (dev, SJA_MOD) & SJA_MOD_RM) > + break; > + } while (--wait); > + > + sja1000_write_reg (dev, SJA_CDR, SJA1000_CDR); > + sja1000_write_reg (dev, SJA_OCR, SJA1000_OCR); > + > + sja1000_write_reg (dev, SJA_AMR0, 0xFF); > + sja1000_write_reg (dev, SJA_AMR1, 0xFF); > + sja1000_write_reg (dev, SJA_AMR2, 0xFF); > + sja1000_write_reg (dev, SJA_AMR3, 0xFF); > + > + sja1000_write_reg (dev, SJA_RXERR, 0); > + sja1000_write_reg (dev, SJA_TXERR, 0); > + > + i = sizeof (sja1000_btr0btr1) / sizeof (u16); > + if (ibaud >= i) > + ibaud = i - 1; > + btr0btr1 = sja1000_btr0btr1[ibaud]; > + sja1000_write_reg (dev, SJA_BTR0, (btr0btr1 >> 8) & 0xff); > + sja1000_write_reg (dev, SJA_BTR1, (btr0btr1 & 0xff)); > + > + /* Clear error code capture (i.e. read it) */ > + sja1000_read_reg (dev, SJA_ECC); > + > + /* Clear reset mode bit in SJA1000 */ > + sja1000_write_reg (dev, SJA_MOD, 0); > + > + return 0; > +} > + > +int sja1000_xmit (struct can_dev *dev, struct can_msg *msg) > +{ > + int i; > + u8 fir; > + > + if (msg->dlc > 8) > + msg->dlc = 8; > + fir = msg->dlc; > + > + sja1000_write_reg (dev, SJA_ID1, msg->id >> 3); > + sja1000_write_reg (dev, SJA_ID2, msg->id << 5); > + for (i = 0; i < msg->dlc; i++) > + sja1000_write_reg (dev, SJA_DATA_SFF (i), msg->data[i]); > + > + /* Write frame information register */ > + sja1000_write_reg (dev, SJA_FIR, fir); > + > + /* Push the 'send' button */ > + sja1000_write_reg (dev, SJA_CMR, SJA_CMR_TR); > + > + /* Wait some time */ > + for (i = 0; i < CAN_XMIT_TIMEOUT_US; i += 10000) { > + if (sja1000_read_reg (dev, SJA_SR) & SJA_SR_TCS) > + return 0; > + if (ctrlc ()) > + break; > + udelay (10000); > + } > + > + return -1; > +} > + > +int sja1000_recv (struct can_dev *dev, struct can_msg *msg) > +{ > + int i; > + u8 fir; > + > + while (!(sja1000_read_reg (dev, SJA_SR) & SJA_SR_RBS)) { > + if (ctrlc ()) > + return -1; > + } > + > + /* Read out frame information register */ > + fir = sja1000_read_reg (dev, SJA_FIR); > + > + /* Extract data length code */ > + msg->dlc = fir & SJA_FIR_DLC_MASK; > + > + /* If DLC exceeds 8 bytes adjust it to 8 (for the payload size) */ > + if (msg->dlc > 8) > + msg->dlc = 8; > + > + if (fir & SJA_FIR_EFF) { > + printf ("Extended CAN messages not supported\n"); > + return -1; > + } else { > + msg->id = sja1000_read_reg (dev, SJA_ID1) << 3; > + msg->id |= sja1000_read_reg (dev, SJA_ID2) >> 5; > + > + if (!(fir & SJA_FIR_RTR)) { > + for (i = 0; i < msg->dlc; i++) > + msg->data[i] = > + sja1000_read_reg (dev, SJA_DATA_SFF (i)); > + } > + } > + if (fir & SJA_FIR_RTR) > + msg->id |= CAN_RTR_FLAG; > + > + /* Release Receive Buffer */ > + sja1000_write_reg (dev, SJA_CMR, SJA_CMR_RRB); > + > + return 0; > +} > + > +int sja1000_status (struct can_dev *dev, int level) > +{ > + printf ("SJA1000 at %#x", dev->base); > + if (level > 0) { > + int stat = sja1000_read_reg (dev, SJA_SR) & 0xff; > + printf (", status 0x%02x", stat); > + if (stat & SJA_SR_BS) > + puts (" busoff"); > + if (stat & SJA_SR_ES) > + puts (" error"); > + if (stat & SJA_SR_TS) > + puts (" txing"); > + if (stat & SJA_SR_RS) > + puts (" rxing"); > + if (stat & SJA_SR_TCS) > + puts (" txdone"); > + if (stat & SJA_SR_TBS) > + puts (" txfree"); > + if (stat & SJA_SR_DOS) > + puts (" overrun"); > + if (stat & SJA_SR_RBS) > + puts (" rxfull"); > + } > + puts ("\n"); > + if (level > 1) { > + int i; > + for (i = 0; i < SJA1000_SIZE; i++) { > + if ((i % 0x10) == 0) > + printf ("\n%02x:", i); > + printf (" %02x", sja1000_read_reg (dev, i)); > + } > + puts ("\n"); > + } > + return 0; > +} > + > +void sja1000_register (struct can_dev *dev, unsigned long base) > +{ > + dev->name = "sja1000"; > + dev->base = base; > + dev->init = sja1000_init; > + dev->xmit = sja1000_xmit; > + dev->recv = sja1000_recv; > + dev->status = sja1000_status; > + > + can_register (dev); > +} > diff --git a/include/sja1000.h b/include/sja1000.h > new file mode 100644 > index 0000000..56b43bf > --- /dev/null > +++ b/include/sja1000.h > @@ -0,0 +1,159 @@ > +/* > + * (C) Copyright 2007-2009, Wolfgang Grandegger <w...@denx.de> > + * > + * Derived from Xenomai's RT-Socket-CAN driver for SJA1000: > + * > + * Copyright (C) 2005,2006 Sebastian Smolorz > + * <sebastian.smol...@stud.uni-hannover.de> > + * > + * Copyright (C) 2005, Sascha Hauer, Pengutronix > + * > + * 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 > + */ > + > +#ifndef __SJA1000_H__ > +#define __SJA1000_H__ > + > +#include <can.h> > + > +/* PeliCAN mode address map */ > + > +/* reset and operating mode */ > +#define SJA_MOD 0 /* Mode register */ > +#define SJA_CMR 1 /* Command register */ > +#define SJA_SR 2 /* Status register */ > +#define SJA_IR 3 /* Interrupt register */ > +#define SJA_IER 4 /* Interrupt enable register */ > +#define SJA_BTR0 6 /* Bus timing register 0 */ > +#define SJA_BTR1 7 /* Bus timing register 1 */ > +#define SJA_OCR 8 /* Output control register */ > +#define SJA_ALC 11 /* Arbitration lost capture */ > +#define SJA_ECC 12 /* Error code capture register */ > +#define SJA_RXERR 14 /* Receive error counter */ > +#define SJA_TXERR 15 /* Transmit error counter */ > +#define SJA_CDR 31 /* Clock divider register */ > + > +/* reset mode */ > +#define SJA_ACR0 16 /* Acceptance code register 0 */ > +#define SJA_ACR1 17 /* Acceptance code register 1 */ > +#define SJA_ACR2 18 /* Acceptance code register 2 */ > +#define SJA_ACR3 19 /* Acceptance code register 3 */ > +#define SJA_AMR0 20 /* Acceptance mask register 0 */ > +#define SJA_AMR1 21 /* Acceptance mask register 1 */ > +#define SJA_AMR2 22 /* Acceptance mask register 2 */ > +#define SJA_AMR3 23 /* Acceptance mask register 3 */ > + > +/* operating mode */ > +#define SJA_FIR 16 /* Frame information register */ > +#define SJA_ID1 17 /* Identifier 1 */ > +#define SJA_ID2 18 /* Identifier 2 */ > +#define SJA_ID3 19 /* Identifier 3 (EFF only) */ > +#define SJA_ID4 20 /* Identifier 4 (EFF only) */ > + > +#define SJA_DATA_SFF(x) (19 + (x)) /* Data registers in case of standard > + * frame format; 0 <= x <= 7 */ > +#define SJA_DATA_EFF(x) (21 + (x)) /* Data registers in case of extended > + * frame format; 0 <= x <= 7 */ > +/* Mode register */ > +#define SJA_MOD_RM (1<<0) /* Reset Mode */ > +#define SJA_MOD_LOM (1<<1) /* Listen Only Mode */ > +#define SJA_MOD_STM (1<<2) /* Self Test Mode */ > +#define SJA_MOD_AFM (1<<3) /* Acceptance Filter Mode */ > +#define SJA_MOD_SM (1<<4) /* Sleep Mode */ > + > +/* Command register */ > +#define SJA_CMR_TR (1<<0) /* Transmission request */ > +#define SJA_CMR_AT (1<<1) /* Abort Transmission */ > +#define SJA_CMR_RRB (1<<2) /* Release Receive Buffer */ > +#define SJA_CMR_CDO (1<<3) /* Clear Data Overrun */ > +#define SJA_CMR_SRR (1<<4) /* Self reception request */ > + > +/* Status register */ > +#define SJA_SR_RBS (1<<0) /* Receive Buffer Status */ > +#define SJA_SR_DOS (1<<1) /* Data Overrun Status */ > +#define SJA_SR_TBS (1<<2) /* Transmit Buffer Status */ > +#define SJA_SR_TCS (1<<3) /* Transmission Complete Status */ > +#define SJA_SR_RS (1<<4) /* Receive Status */ > +#define SJA_SR_TS (1<<5) /* Transmit Status */ > +#define SJA_SR_ES (1<<6) /* Error Status */ > +#define SJA_SR_BS (1<<7) /* Bus Status */ > + > +/* Interrupt register */ > +#define SJA_IR_RI (1<<0) /* Receive Interrupt */ > +#define SJA_IR_TI (1<<1) /* Transmit Interrupt */ > +#define SJA_IR_EI (1<<2) /* Error Warning Interrupt */ > +#define SJA_IR_DOI (1<<3) /* Data Overrun Interrupt */ > +#define SJA_IR_WUI (1<<4) /* Wake-Up Interrupt */ > +#define SJA_IR_EPI (1<<5) /* Error Passive Interrupt */ > +#define SJA_IR_ALI (1<<6) /* Arbitration Lost Interrupt */ > +#define SJA_IR_BEI (1<<7) /* Bus Error Interrupt */ > + > +/* Interrupt enable register */ > +#define SJA_IER_RIE (1<<0) /* Receive Interrupt Enable */ > +#define SJA_IER_TIE (1<<1) /* Transmit Interrupt Enable */ > +#define SJA_IER_EIE (1<<2) /* Error Warning Interrupt Enable */ > +#define SJA_IER_DOIE (1<<3) /* Data Overrun Interrupt Enable */ > +#define SJA_IER_WUIE (1<<4) /* Wake-Up Interrupt Enable */ > +#define SJA_IER_EPIE (1<<5) /* Error Passive Interrupt Enable */ > +#define SJA_IER_ALIE (1<<6) /* Arbitration Lost Interrupt Enable */ > +#define SJA_IER_BEIE (1<<7) /* Bus Error Interrupt Enable */ > + > +/* Output control register */ > +#define SJA_OCR_MODE_BIPHASE 0 > +#define SJA_OCR_MODE_TEST 1 > +#define SJA_OCR_MODE_NORMAL 2 > +#define SJA_OCR_MODE_CLOCK 3 > +#define SJA_OCR_TX0_INVERT (1<<2) > +#define SJA_OCR_TX0_PULLDOWN (1<<3) > +#define SJA_OCR_TX0_PULLUP (2<<3) > +#define SJA_OCR_TX0_PUSHPULL (3<<3) > +#define SJA_OCR_TX1_INVERT (1<<5) > +#define SJA_OCR_TX1_PULLDOWN (1<<6) > +#define SJA_OCR_TX1_PULLUP (2<<6) > +#define SJA_OCR_TX1_PUSHPULL (3<<6) > + > +/* Error code capture register */ > + > +/* > + * The segmentation field gives information about the location of > + * errors on the bus > + */ > +#define SJA_ECC_SEG_MASK 31 /* Segmentation field mask */ > +#define SJA_ECC_DIR (1<<5) /* Transfer direction */ > +#define SJA_ECC_ERR_BIT (0<<6) > +#define SJA_ECC_ERR_FORM (1<<6) > +#define SJA_ECC_ERR_STUFF (2<<6) > +#define SJA_ECC_ERR_MASK (3<<6) /* Error code mask */ > + > +/* Frame information register */ > +#define SJA_FIR_DLC_MASK 15 /* Data length code mask */ > +#define SJA_FIR_RTR (1<<6) /* Remote transmission request */ > +#define SJA_FIR_EFF (1<<7) /* Extended frame format */ > + > +/* Clock divider register */ > +#define SJA_CDR_CLK_OFF (1<<3) /* Clock off (CLKOUT pin) */ > +#define SJA_CDR_CBP (1<<6) /* CAN input comparator bypass */ > +#define SJA_CDR_CAN_MODE (1<<7) /* CAN mode: 1 = PeliCAN */ > + > +#define SJA1000_SIZE 0x80 > + > +void sja1000_register (struct can_dev *dev, unsigned long base); > + > +#endif /* __SJA1000_H__ */ > + -- ------------------------------------------------------------------------- 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