
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 wg@denx.de
Signed-off-by: Wolfgang Grandegger wg@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 wg@denx.de
- Derived from Xenomai's RT-Socket-CAN driver for SJA1000:
- Copyright (C) 2005,2006 Sebastian Smolorz
<Sebastian.Smolorz@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 wg@denx.de
- Derived from Xenomai's RT-Socket-CAN driver for SJA1000:
- Copyright (C) 2005,2006 Sebastian Smolorz
<Sebastian.Smolorz@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__ */