linux-can.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* sja1000 BasicCAN mode
@ 2011-11-14 17:08 Yuriy Kiselev
  0 siblings, 0 replies; 3+ messages in thread
From: Yuriy Kiselev @ 2011-11-14 17:08 UTC (permalink / raw)
  To: socketcan-users-0fE9KPoRgkgATYTw5x5z8w; +Cc: linux-can-u79uwXL29TY76Z2rM5mHXA


[-- Attachment #1.1: Type: text/plain, Size: 277 bytes --]

Hello!
Implementation of BasicCAN mode for SJA1000 is in attachment.
Now SJA1000_PELICAN_MODE macros in sja1000.h is used for definition PeliCAN
or BasicCAN mode. It would be nice to create some menuconfig-wrapper, I
think.
I use this code for a few weeks and it looks stable.

[-- Attachment #1.2: Type: text/html, Size: 325 bytes --]

[-- Attachment #2: socketcan_sja1000_basicmod_impl.patch --]
[-- Type: application/octet-stream, Size: 11279 bytes --]

diff -ru trunk.orig/kernel/2.6/drivers/net/can/sja1000/sja1000.c trunk/kernel/2.6/drivers/net/can/sja1000/sja1000.c
--- trunk.orig/kernel/2.6/drivers/net/can/sja1000/sja1000.c	2011-11-14 20:46:35.074737955 +0400
+++ trunk/kernel/2.6/drivers/net/can/sja1000/sja1000.c	2011-11-14 20:56:00.083183431 +0400
@@ -117,22 +117,43 @@
 static void set_reset_mode(struct net_device *dev)
 {
 	struct sja1000_priv *priv = netdev_priv(dev);
+#ifdef SJA1000_PELICAN_MODE
 	unsigned char status = priv->read_reg(priv, REG_MOD);
+#else
+	unsigned char status = priv->read_reg(priv, REG_CR);
+#endif
 	int i;
 
 	/* disable interrupts */
+#ifdef SJA1000_PELICAN_MODE
 	priv->write_reg(priv, REG_IER, IRQ_OFF);
+#else
+	priv->write_reg(priv, REG_CR, status & IRQ_OFF);
+#endif
 
 	for (i = 0; i < 100; i++) {
-		/* check reset bit */
+		// check reset bit
+#ifdef SJA1000_PELICAN_MODE
 		if (status & MOD_RM) {
+#else
+		if (status & CR_RRQ) {
+#endif
 			priv->can.state = CAN_STATE_STOPPED;
 			return;
 		}
 
-		priv->write_reg(priv, REG_MOD, MOD_RM);	/* reset chip */
+    	/* reset chip */
+#ifdef SJA1000_PELICAN_MODE
+		priv->write_reg(priv, REG_MOD, MOD_RM);
+#else
+		priv->write_reg(priv, REG_CR, CR_RRQ);
+#endif
 		udelay(10);
+#ifdef SJA1000_PELICAN_MODE
 		status = priv->read_reg(priv, REG_MOD);
+#else
+		status = priv->read_reg(priv, REG_CR);
+#endif
 	}
 
 	dev_err(ND2D(dev), "setting SJA1000 into reset mode failed!\n");
@@ -141,26 +162,50 @@
 static void set_normal_mode(struct net_device *dev)
 {
 	struct sja1000_priv *priv = netdev_priv(dev);
+#ifdef SJA1000_PELICAN_MODE
 	unsigned char status = priv->read_reg(priv, REG_MOD);
+#else
+	unsigned char status = priv->read_reg(priv, REG_CR);
+#endif
 	int i;
 
 	for (i = 0; i < 100; i++) {
 		/* check reset bit */
+#ifdef SJA1000_PELICAN_MODE
 		if ((status & MOD_RM) == 0) {
+#else
+		if ((status & CR_RRQ) == 0) {
+#endif
 			priv->can.state = CAN_STATE_ERROR_ACTIVE;
 			/* enable interrupts */
+#ifdef SJA1000_PELICAN_MODE
 			if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
 				priv->write_reg(priv, REG_IER, IRQ_ALL);
+
 			else
 				priv->write_reg(priv, REG_IER,
 						IRQ_ALL & ~IRQ_BEI);
 			return;
+#else
+			priv->write_reg(priv, REG_CR, status | IRQ_ALL);
+			return;
+#endif
 		}
 
+
 		/* set chip to normal mode */
+#ifdef SJA1000_PELICAN_MODE
 		priv->write_reg(priv, REG_MOD, 0x00);
+#else
+		//status = priv->read_reg(priv, REG_CR);
+		priv->write_reg(priv, REG_CR, status & ~CR_RRQ);
+#endif
 		udelay(10);
+#ifdef SJA1000_PELICAN_MODE
 		status = priv->read_reg(priv, REG_MOD);
+#else
+		status = priv->read_reg(priv, REG_CR);
+#endif
 	}
 
 	dev_err(ND2D(dev), "setting SJA1000 into normal mode failed!\n");
@@ -175,9 +220,11 @@
 		set_reset_mode(dev);
 
 	/* Clear error counters and error code capture */
+#ifdef SJA1000_PELICAN_MODE
 	priv->write_reg(priv, REG_TXERR, 0x0);
 	priv->write_reg(priv, REG_RXERR, 0x0);
 	priv->read_reg(priv, REG_ECC);
+#endif
 
 	/* leave reset mode */
 	set_normal_mode(dev);
@@ -230,8 +277,13 @@
 {
 	struct sja1000_priv *priv = netdev_priv(dev);
 
+#ifdef SJA1000_PELICAN_MODE
 	bec->txerr = priv->read_reg(priv, REG_TXERR);
 	bec->rxerr = priv->read_reg(priv, REG_RXERR);
+#else
+	bec->txerr = 0;
+	bec->rxerr = 0;
+#endif
 
 	return 0;
 }
@@ -247,11 +299,17 @@
 static void chipset_init(struct net_device *dev)
 {
 	struct sja1000_priv *priv = netdev_priv(dev);
+	struct can_bittiming bt;
 
 	/* set clock divider and output control register */
+#ifdef SJA1000_PELICAN_MODE
 	priv->write_reg(priv, REG_CDR, priv->cdr | CDR_PELICAN);
+#else
+	priv->write_reg(priv, REG_CDR, priv->cdr);
+#endif
 
 	/* set acceptance filter (accept all) */
+#ifdef SJA1000_PELICAN_MODE
 	priv->write_reg(priv, REG_ACCC0, 0x00);
 	priv->write_reg(priv, REG_ACCC1, 0x00);
 	priv->write_reg(priv, REG_ACCC2, 0x00);
@@ -261,6 +319,11 @@
 	priv->write_reg(priv, REG_ACCM1, 0xFF);
 	priv->write_reg(priv, REG_ACCM2, 0xFF);
 	priv->write_reg(priv, REG_ACCM3, 0xFF);
+#else
+	priv->write_reg(priv, REG_AC, 0x00);
+	priv->write_reg(priv, REG_AM, 0xFF);
+	
+#endif
 
 	priv->write_reg(priv, REG_OCR, priv->ocr | OCR_MODE_NORMAL);
 }
@@ -298,6 +361,8 @@
 		fi |= FI_RTR;
 
 	if (id & CAN_EFF_FLAG) {
+	    /* Extended frame. Not available in BasicCAN mode. */
+#ifdef SJA1000_PELICAN_MODE
 		fi |= FI_FF;
 		dreg = EFF_BUF;
 		priv->write_reg(priv, REG_FI, fi);
@@ -305,15 +370,26 @@
 		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);
+#endif
 	} else {
+	/* Standard frame */
+#ifdef SJA1000_PELICAN_MODE
 		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);
+#else
+		priv->write_reg(priv, REG_TXB, (id & 0x000007f8) >> 3);
+		priv->write_reg(priv, REG_TXB + 1, ((id & 0x00000007) << 5) | fi);
+#endif
 	}
 
 	for (i = 0; i < dlc; i++)
+#ifdef SJA1000_PELICAN_MODE
 		priv->write_reg(priv, dreg++, cf->data[i]);
+#else
+		priv->write_reg(priv, REG_TXB + 2 + i, cf->data[i]);
+#endif
 
 	dev->trans_start = jiffies;
 
@@ -344,8 +420,14 @@
 	if (skb == NULL)
 		return;
 
+#ifdef SJA1000_PELICAN_MODE
 	fi = priv->read_reg(priv, REG_FI);
+#else
+    /* Read RTR & DLC */
+	fi = priv->read_reg(priv, REG_RXB + 1) & 0x1F;
+#endif
 
+#ifdef SJA1000_PELICAN_MODE
 	if (fi & FI_FF) {
 		/* extended frame format (EFF) */
 		dreg = EFF_BUF;
@@ -360,13 +442,22 @@
 		id = (priv->read_reg(priv, REG_ID1) << 3)
 		    | (priv->read_reg(priv, REG_ID2) >> 5);
 	}
+#else
+	id = (priv->read_reg(priv, REG_RXB) << 3)
+		| ((priv->read_reg(priv, REG_RXB + 1) & 0xE0) >> 5);
+#endif
 
 	if (fi & FI_RTR) {
 		id |= CAN_RTR_FLAG;
 	} else {
+		/* DLC field is same in TXB/RXB (basiccan) and FI (pelican) registers */
 		cf->can_dlc = get_can_dlc(fi & 0x0F);
 		for (i = 0; i < cf->can_dlc; i++)
+#ifdef SJA1000_PELICAN_MODE
 			cf->data[i] = priv->read_reg(priv, dreg++);
+#else
+			cf->data[i] = priv->read_reg(priv, REG_RXB + 2 + i);
+#endif
 	}
 
 	cf->can_id = id;
@@ -423,6 +514,7 @@
 		} else
 			state = CAN_STATE_ERROR_ACTIVE;
 	}
+#ifdef SJA1000_PELICAN_MODE /* BasicCAN mode doesn't support Bus Error Interrupt */
 	if (isrc & IRQ_BEI) {
 		/* bus error interrupt */
 		priv->can.can_stats.bus_error++;
@@ -451,6 +543,9 @@
 		if ((ecc & ECC_DIR) == 0)
 			cf->data[2] |= CAN_ERR_PROT_TX;
 	}
+#endif
+
+#ifdef SJA1000_PELICAN_MODE /* BasicCAN mode doesn't support Error Passive Interrupt */
 	if (isrc & IRQ_EPI) {
 		/* error passive interrupt */
 		dev_dbg(ND2D(dev), "error passive interrupt\n");
@@ -459,6 +554,9 @@
 		else
 			state = CAN_STATE_ERROR_ACTIVE;
 	}
+#endif
+
+#ifdef SJA1000_PELICAN_MODE /* BasicCAN mode doesn't support Arbitration Lost Interrupt */
 	if (isrc & IRQ_ALI) {
 		/* arbitration lost interrupt */
 		dev_dbg(ND2D(dev), "arbitration lost interrupt\n");
@@ -468,11 +566,18 @@
 		cf->can_id |= CAN_ERR_LOSTARB;
 		cf->data[0] = alc & 0x1f;
 	}
+#endif
 
 	if (state != priv->can.state && (state == CAN_STATE_ERROR_WARNING ||
 					 state == CAN_STATE_ERROR_PASSIVE)) {
+#ifdef SJA1000_PELICAN_MODE
 		uint8_t rxerr = priv->read_reg(priv, REG_RXERR);
 		uint8_t txerr = priv->read_reg(priv, REG_TXERR);
+#else
+		uint8_t rxerr = 0;
+		uint8_t txerr = 0;
+#endif
+
 		cf->can_id |= CAN_ERR_CRTL;
 		if (state == CAN_STATE_ERROR_WARNING) {
 			priv->can.can_stats.error_warning++;
@@ -519,7 +624,11 @@
 	int n = 0;
 
 	/* Shared interrupts and IRQ off? */
+#ifdef SJA1000_PELICAN_MODE
 	if (priv->read_reg(priv, REG_IER) == IRQ_OFF)
+#else
+	if ((priv->read_reg(priv, REG_CR) & IRQ_ALL) == 0)
+#endif
 		return IRQ_NONE;
 
 	if (priv->pre_irq)
@@ -534,7 +643,11 @@
 
 		if (isrc & IRQ_TI) {
 			/* transmission complete interrupt */
-			stats->tx_bytes += priv->read_reg(priv, REG_FI) & 0xf;
+#ifdef SJA1000_PELICAN_MODE
+			stats->tx_bytes += priv->read_reg(priv, REG_FI) & 0xF;
+#else
+			stats->tx_bytes += priv->read_reg(priv, REG_TXB + 1) & 0xF;
+#endif
 			stats->tx_packets++;
 			can_get_echo_skb(dev, 0);
 			netif_wake_queue(dev);
@@ -546,7 +659,11 @@
 				status = priv->read_reg(priv, REG_SR);
 			}
 		}
+#ifdef SJA1000_PELICAN_MODE
 		if (isrc & (IRQ_DOI | IRQ_EI | IRQ_BEI | IRQ_EPI | IRQ_ALI)) {
+#else
+		if (isrc & (IRQ_DOI | IRQ_EI)) {
+#endif
 			/* error interrupt */
 			if (sja1000_err(dev, isrc, status))
 				break;
diff -ru trunk.orig/kernel/2.6/drivers/net/can/sja1000/sja1000.h trunk/kernel/2.6/drivers/net/can/sja1000/sja1000.h
--- trunk.orig/kernel/2.6/drivers/net/can/sja1000/sja1000.h	2011-11-14 20:49:44.526408577 +0400
+++ trunk/kernel/2.6/drivers/net/can/sja1000/sja1000.h	2011-11-14 20:50:20.813395105 +0400
@@ -50,10 +50,14 @@
 #include <socketcan/can/dev.h>
 #include <socketcan/can/platform/sja1000.h>
 
+#define SJA1000_PELICAN_MODE /* BasicCAN accepted if not defined */
+
 #define SJA1000_ECHO_SKB_MAX	1 /* the SJA1000 has one TX buffer object */
 
 #define SJA1000_MAX_IRQ 20	/* max. number of interrupts handled in ISR */
 
+#ifdef SJA1000_PELICAN_MODE
+
 /* SJA1000 registers - manual section 6.4 (Pelican Mode) */
 #define REG_MOD		0x00
 #define REG_CMR		0x01
@@ -76,19 +80,10 @@
 #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
@@ -96,6 +91,27 @@
 
 #define CAN_RAM		0x20
 
+#else /* SJA1000_PELICAN_MODE */
+
+/* SJA1000 registers - manual section 6.3 (Basiccan Mode) */
+#define REG_CR		0x00
+#define REG_CMR		0x01
+#define REG_SR		0x02
+#define REG_IR		0x03
+#define REG_AC		0x04
+#define REG_AM		0x05
+#define REG_TXB		0x0A
+#define REG_RXB		0x14
+
+#endif /* SJA1000_PELICAN_MODE */
+
+/* Common registers - manual section 6.5 */
+#define REG_BTR0	0x06
+#define REG_BTR1	0x07
+#define REG_OCR		0x08
+#define REG_CDR		0x1F
+
+#ifdef SJA1000_PELICAN_MODE
 /* mode register */
 #define MOD_RM		0x01
 #define MOD_LOM		0x02
@@ -137,11 +153,53 @@
 /* ECC register */
 #define ECC_SEG		0x1F
 #define ECC_DIR		0x20
-#define ECC_ERR		6
+#define ECC_ERR		0x06
 #define ECC_BIT		0x00
 #define ECC_FORM	0x40
 #define ECC_STUFF	0x80
-#define ECC_MASK	0xc0
+#define ECC_MASK	0xC0
+
+#define FI_FF		0x80
+#define FI_RTR		0x40
+
+#else /* SJA1000_PELICAN_MODE */
+
+/* control register */
+#define CR_RRQ		0x01
+#define CR_RIE		0x02
+#define CR_TIE		0x04
+#define CR_EIE		0x08
+#define CR_OIE		0x10
+#define IRQ_OFF		CR_RRQ
+#define IRQ_ALL		(CR_RIE | CR_TIE | CR_EIE | CR_OIE)
+
+/* command register */
+#define CMD_TR		0x01
+#define CMD_AT		0x02
+#define CMD_RRB		0x04
+#define CMD_CDO		0x08
+#define CMD_GTS		0x10
+
+/* status register */
+#define SR_RBS		0x01
+#define SR_DOS		0x02
+#define SR_TBS		0x04
+#define SR_TCS		0x08
+#define SR_RS		0x10
+#define SR_TS		0x20
+#define SR_ES		0x40
+#define SR_BS		0x80
+
+/* interrupt sources */
+#define IRQ_RI		0x01
+#define IRQ_TI		0x02
+#define IRQ_EI		0x04
+#define IRQ_DOI		0x08
+#define IRQ_WUI		0x10
+
+#define FI_RTR		0x10
+
+#endif /* SJA1000_PELICAN_MODE */
 
 /*
  * Flags for sja1000priv.flags

[-- Attachment #3: Type: text/plain, Size: 191 bytes --]

_______________________________________________
Socketcan-users mailing list
Socketcan-users-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org
https://lists.berlios.de/mailman/listinfo/socketcan-users

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: sja1000 BasicCAN mode
@ 2011-11-14 18:03 Oliver Hartkopp
       [not found] ` <CAF8b2jLH8CTOU5ZBTdH7yFhhb0=QmP2Y_Lkom80Bxfw0AvjA6g@mail.gmail.com>
  0 siblings, 1 reply; 3+ messages in thread
From: Oliver Hartkopp @ 2011-11-14 18:03 UTC (permalink / raw)
  To: Yuriy Kiselev; +Cc: socketcan-users, linux-can-u79uwXL29TY76Z2rM5mHXA

[-- Attachment #1: Type: text/plain, Size: 12486 bytes --]

Hello Yuriy,

what's your motivation for the BasicCAN mode support?

My biggest concern is that you leave the driver as a #ifdef hell ...
The second thing, is that you urge all CAN interfaces in the system to be
BasicCAN *or* PeliCAN mode. No chance to mix the hardware and to have a
per-device setting.

If such a functionality is to be implemented (and you have a good reason for
BasicCAN mode), this could be done by creating a new per-device flag.

E.g. 

#define SJA1000_BASIC_CAN 0x02

for sja1000priv.flags

Regards,
Oliver

ps. pls send patches always inline for a review
pps. and no html mails %-)

-------- Original Message --------
Subject: 	[Socketcan-users] sja1000 BasicCAN mode
Date: 	Mon, 14 Nov 2011 21:08:29 +0400
From: 	Yuriy Kiselev <kiselev.yuriy-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
To: 	socketcan-users-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org
CC: 	linux-can-u79uwXL29TY76Z2rM5mHXA@public.gmane.org



Hello!
Implementation of BasicCAN mode for SJA1000 is in attachment.
Now SJA1000_PELICAN_MODE macros in sja1000.h is used for definition PeliCAN or
BasicCAN mode. It would be nice to create some menuconfig-wrapper, I think.
I use this code for a few weeks and it looks stable.


diff -ru trunk.orig/kernel/2.6/drivers/net/can/sja1000/sja1000.c trunk/kernel/2.6/drivers/net/can/sja1000/sja1000.c
--- trunk.orig/kernel/2.6/drivers/net/can/sja1000/sja1000.c	2011-11-14 20:46:35.074737955 +0400
+++ trunk/kernel/2.6/drivers/net/can/sja1000/sja1000.c	2011-11-14 20:56:00.083183431 +0400
@@ -117,22 +117,43 @@
 static void set_reset_mode(struct net_device *dev)
 {
 	struct sja1000_priv *priv = netdev_priv(dev);
+#ifdef SJA1000_PELICAN_MODE
 	unsigned char status = priv->read_reg(priv, REG_MOD);
+#else
+	unsigned char status = priv->read_reg(priv, REG_CR);
+#endif
 	int i;
 
 	/* disable interrupts */
+#ifdef SJA1000_PELICAN_MODE
 	priv->write_reg(priv, REG_IER, IRQ_OFF);
+#else
+	priv->write_reg(priv, REG_CR, status & IRQ_OFF);
+#endif
 
 	for (i = 0; i < 100; i++) {
-		/* check reset bit */
+		// check reset bit
+#ifdef SJA1000_PELICAN_MODE
 		if (status & MOD_RM) {
+#else
+		if (status & CR_RRQ) {
+#endif
 			priv->can.state = CAN_STATE_STOPPED;
 			return;
 		}
 
-		priv->write_reg(priv, REG_MOD, MOD_RM);	/* reset chip */
+    	/* reset chip */
+#ifdef SJA1000_PELICAN_MODE
+		priv->write_reg(priv, REG_MOD, MOD_RM);
+#else
+		priv->write_reg(priv, REG_CR, CR_RRQ);
+#endif
 		udelay(10);
+#ifdef SJA1000_PELICAN_MODE
 		status = priv->read_reg(priv, REG_MOD);
+#else
+		status = priv->read_reg(priv, REG_CR);
+#endif
 	}
 
 	dev_err(ND2D(dev), "setting SJA1000 into reset mode failed!\n");
@@ -141,26 +162,50 @@
 static void set_normal_mode(struct net_device *dev)
 {
 	struct sja1000_priv *priv = netdev_priv(dev);
+#ifdef SJA1000_PELICAN_MODE
 	unsigned char status = priv->read_reg(priv, REG_MOD);
+#else
+	unsigned char status = priv->read_reg(priv, REG_CR);
+#endif
 	int i;
 
 	for (i = 0; i < 100; i++) {
 		/* check reset bit */
+#ifdef SJA1000_PELICAN_MODE
 		if ((status & MOD_RM) == 0) {
+#else
+		if ((status & CR_RRQ) == 0) {
+#endif
 			priv->can.state = CAN_STATE_ERROR_ACTIVE;
 			/* enable interrupts */
+#ifdef SJA1000_PELICAN_MODE
 			if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
 				priv->write_reg(priv, REG_IER, IRQ_ALL);
+
 			else
 				priv->write_reg(priv, REG_IER,
 						IRQ_ALL & ~IRQ_BEI);
 			return;
+#else
+			priv->write_reg(priv, REG_CR, status | IRQ_ALL);
+			return;
+#endif
 		}
 
+
 		/* set chip to normal mode */
+#ifdef SJA1000_PELICAN_MODE
 		priv->write_reg(priv, REG_MOD, 0x00);
+#else
+		//status = priv->read_reg(priv, REG_CR);
+		priv->write_reg(priv, REG_CR, status & ~CR_RRQ);
+#endif
 		udelay(10);
+#ifdef SJA1000_PELICAN_MODE
 		status = priv->read_reg(priv, REG_MOD);
+#else
+		status = priv->read_reg(priv, REG_CR);
+#endif
 	}
 
 	dev_err(ND2D(dev), "setting SJA1000 into normal mode failed!\n");
@@ -175,9 +220,11 @@
 		set_reset_mode(dev);
 
 	/* Clear error counters and error code capture */
+#ifdef SJA1000_PELICAN_MODE
 	priv->write_reg(priv, REG_TXERR, 0x0);
 	priv->write_reg(priv, REG_RXERR, 0x0);
 	priv->read_reg(priv, REG_ECC);
+#endif
 
 	/* leave reset mode */
 	set_normal_mode(dev);
@@ -230,8 +277,13 @@
 {
 	struct sja1000_priv *priv = netdev_priv(dev);
 
+#ifdef SJA1000_PELICAN_MODE
 	bec->txerr = priv->read_reg(priv, REG_TXERR);
 	bec->rxerr = priv->read_reg(priv, REG_RXERR);
+#else
+	bec->txerr = 0;
+	bec->rxerr = 0;
+#endif
 
 	return 0;
 }
@@ -247,11 +299,17 @@
 static void chipset_init(struct net_device *dev)
 {
 	struct sja1000_priv *priv = netdev_priv(dev);
+	struct can_bittiming bt;
 
 	/* set clock divider and output control register */
+#ifdef SJA1000_PELICAN_MODE
 	priv->write_reg(priv, REG_CDR, priv->cdr | CDR_PELICAN);
+#else
+	priv->write_reg(priv, REG_CDR, priv->cdr);
+#endif
 
 	/* set acceptance filter (accept all) */
+#ifdef SJA1000_PELICAN_MODE
 	priv->write_reg(priv, REG_ACCC0, 0x00);
 	priv->write_reg(priv, REG_ACCC1, 0x00);
 	priv->write_reg(priv, REG_ACCC2, 0x00);
@@ -261,6 +319,11 @@
 	priv->write_reg(priv, REG_ACCM1, 0xFF);
 	priv->write_reg(priv, REG_ACCM2, 0xFF);
 	priv->write_reg(priv, REG_ACCM3, 0xFF);
+#else
+	priv->write_reg(priv, REG_AC, 0x00);
+	priv->write_reg(priv, REG_AM, 0xFF);
+	
+#endif
 
 	priv->write_reg(priv, REG_OCR, priv->ocr | OCR_MODE_NORMAL);
 }
@@ -298,6 +361,8 @@
 		fi |= FI_RTR;
 
 	if (id & CAN_EFF_FLAG) {
+	    /* Extended frame. Not available in BasicCAN mode. */
+#ifdef SJA1000_PELICAN_MODE
 		fi |= FI_FF;
 		dreg = EFF_BUF;
 		priv->write_reg(priv, REG_FI, fi);
@@ -305,15 +370,26 @@
 		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);
+#endif
 	} else {
+	/* Standard frame */
+#ifdef SJA1000_PELICAN_MODE
 		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);
+#else
+		priv->write_reg(priv, REG_TXB, (id & 0x000007f8) >> 3);
+		priv->write_reg(priv, REG_TXB + 1, ((id & 0x00000007) << 5) | fi);
+#endif
 	}
 
 	for (i = 0; i < dlc; i++)
+#ifdef SJA1000_PELICAN_MODE
 		priv->write_reg(priv, dreg++, cf->data[i]);
+#else
+		priv->write_reg(priv, REG_TXB + 2 + i, cf->data[i]);
+#endif
 
 	dev->trans_start = jiffies;
 
@@ -344,8 +420,14 @@
 	if (skb == NULL)
 		return;
 
+#ifdef SJA1000_PELICAN_MODE
 	fi = priv->read_reg(priv, REG_FI);
+#else
+    /* Read RTR & DLC */
+	fi = priv->read_reg(priv, REG_RXB + 1) & 0x1F;
+#endif
 
+#ifdef SJA1000_PELICAN_MODE
 	if (fi & FI_FF) {
 		/* extended frame format (EFF) */
 		dreg = EFF_BUF;
@@ -360,13 +442,22 @@
 		id = (priv->read_reg(priv, REG_ID1) << 3)
 		    | (priv->read_reg(priv, REG_ID2) >> 5);
 	}
+#else
+	id = (priv->read_reg(priv, REG_RXB) << 3)
+		| ((priv->read_reg(priv, REG_RXB + 1) & 0xE0) >> 5);
+#endif
 
 	if (fi & FI_RTR) {
 		id |= CAN_RTR_FLAG;
 	} else {
+		/* DLC field is same in TXB/RXB (basiccan) and FI (pelican) registers */
 		cf->can_dlc = get_can_dlc(fi & 0x0F);
 		for (i = 0; i < cf->can_dlc; i++)
+#ifdef SJA1000_PELICAN_MODE
 			cf->data[i] = priv->read_reg(priv, dreg++);
+#else
+			cf->data[i] = priv->read_reg(priv, REG_RXB + 2 + i);
+#endif
 	}
 
 	cf->can_id = id;
@@ -423,6 +514,7 @@
 		} else
 			state = CAN_STATE_ERROR_ACTIVE;
 	}
+#ifdef SJA1000_PELICAN_MODE /* BasicCAN mode doesn't support Bus Error Interrupt */
 	if (isrc & IRQ_BEI) {
 		/* bus error interrupt */
 		priv->can.can_stats.bus_error++;
@@ -451,6 +543,9 @@
 		if ((ecc & ECC_DIR) == 0)
 			cf->data[2] |= CAN_ERR_PROT_TX;
 	}
+#endif
+
+#ifdef SJA1000_PELICAN_MODE /* BasicCAN mode doesn't support Error Passive Interrupt */
 	if (isrc & IRQ_EPI) {
 		/* error passive interrupt */
 		dev_dbg(ND2D(dev), "error passive interrupt\n");
@@ -459,6 +554,9 @@
 		else
 			state = CAN_STATE_ERROR_ACTIVE;
 	}
+#endif
+
+#ifdef SJA1000_PELICAN_MODE /* BasicCAN mode doesn't support Arbitration Lost Interrupt */
 	if (isrc & IRQ_ALI) {
 		/* arbitration lost interrupt */
 		dev_dbg(ND2D(dev), "arbitration lost interrupt\n");
@@ -468,11 +566,18 @@
 		cf->can_id |= CAN_ERR_LOSTARB;
 		cf->data[0] = alc & 0x1f;
 	}
+#endif
 
 	if (state != priv->can.state && (state == CAN_STATE_ERROR_WARNING ||
 					 state == CAN_STATE_ERROR_PASSIVE)) {
+#ifdef SJA1000_PELICAN_MODE
 		uint8_t rxerr = priv->read_reg(priv, REG_RXERR);
 		uint8_t txerr = priv->read_reg(priv, REG_TXERR);
+#else
+		uint8_t rxerr = 0;
+		uint8_t txerr = 0;
+#endif
+
 		cf->can_id |= CAN_ERR_CRTL;
 		if (state == CAN_STATE_ERROR_WARNING) {
 			priv->can.can_stats.error_warning++;
@@ -519,7 +624,11 @@
 	int n = 0;
 
 	/* Shared interrupts and IRQ off? */
+#ifdef SJA1000_PELICAN_MODE
 	if (priv->read_reg(priv, REG_IER) == IRQ_OFF)
+#else
+	if ((priv->read_reg(priv, REG_CR) & IRQ_ALL) == 0)
+#endif
 		return IRQ_NONE;
 
 	if (priv->pre_irq)
@@ -534,7 +643,11 @@
 
 		if (isrc & IRQ_TI) {
 			/* transmission complete interrupt */
-			stats->tx_bytes += priv->read_reg(priv, REG_FI) & 0xf;
+#ifdef SJA1000_PELICAN_MODE
+			stats->tx_bytes += priv->read_reg(priv, REG_FI) & 0xF;
+#else
+			stats->tx_bytes += priv->read_reg(priv, REG_TXB + 1) & 0xF;
+#endif
 			stats->tx_packets++;
 			can_get_echo_skb(dev, 0);
 			netif_wake_queue(dev);
@@ -546,7 +659,11 @@
 				status = priv->read_reg(priv, REG_SR);
 			}
 		}
+#ifdef SJA1000_PELICAN_MODE
 		if (isrc & (IRQ_DOI | IRQ_EI | IRQ_BEI | IRQ_EPI | IRQ_ALI)) {
+#else
+		if (isrc & (IRQ_DOI | IRQ_EI)) {
+#endif
 			/* error interrupt */
 			if (sja1000_err(dev, isrc, status))
 				break;
diff -ru trunk.orig/kernel/2.6/drivers/net/can/sja1000/sja1000.h trunk/kernel/2.6/drivers/net/can/sja1000/sja1000.h
--- trunk.orig/kernel/2.6/drivers/net/can/sja1000/sja1000.h	2011-11-14 20:49:44.526408577 +0400
+++ trunk/kernel/2.6/drivers/net/can/sja1000/sja1000.h	2011-11-14 20:50:20.813395105 +0400
@@ -50,10 +50,14 @@
 #include <socketcan/can/dev.h>
 #include <socketcan/can/platform/sja1000.h>
 
+#define SJA1000_PELICAN_MODE /* BasicCAN accepted if not defined */
+
 #define SJA1000_ECHO_SKB_MAX	1 /* the SJA1000 has one TX buffer object */
 
 #define SJA1000_MAX_IRQ 20	/* max. number of interrupts handled in ISR */
 
+#ifdef SJA1000_PELICAN_MODE
+
 /* SJA1000 registers - manual section 6.4 (Pelican Mode) */
 #define REG_MOD		0x00
 #define REG_CMR		0x01
@@ -76,19 +80,10 @@
 #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
@@ -96,6 +91,27 @@
 
 #define CAN_RAM		0x20
 
+#else /* SJA1000_PELICAN_MODE */
+
+/* SJA1000 registers - manual section 6.3 (Basiccan Mode) */
+#define REG_CR		0x00
+#define REG_CMR		0x01
+#define REG_SR		0x02
+#define REG_IR		0x03
+#define REG_AC		0x04
+#define REG_AM		0x05
+#define REG_TXB		0x0A
+#define REG_RXB		0x14
+
+#endif /* SJA1000_PELICAN_MODE */
+
+/* Common registers - manual section 6.5 */
+#define REG_BTR0	0x06
+#define REG_BTR1	0x07
+#define REG_OCR		0x08
+#define REG_CDR		0x1F
+
+#ifdef SJA1000_PELICAN_MODE
 /* mode register */
 #define MOD_RM		0x01
 #define MOD_LOM		0x02
@@ -137,11 +153,53 @@
 /* ECC register */
 #define ECC_SEG		0x1F
 #define ECC_DIR		0x20
-#define ECC_ERR		6
+#define ECC_ERR		0x06
 #define ECC_BIT		0x00
 #define ECC_FORM	0x40
 #define ECC_STUFF	0x80
-#define ECC_MASK	0xc0
+#define ECC_MASK	0xC0
+
+#define FI_FF		0x80
+#define FI_RTR		0x40
+
+#else /* SJA1000_PELICAN_MODE */
+
+/* control register */
+#define CR_RRQ		0x01
+#define CR_RIE		0x02
+#define CR_TIE		0x04
+#define CR_EIE		0x08
+#define CR_OIE		0x10
+#define IRQ_OFF		CR_RRQ
+#define IRQ_ALL		(CR_RIE | CR_TIE | CR_EIE | CR_OIE)
+
+/* command register */
+#define CMD_TR		0x01
+#define CMD_AT		0x02
+#define CMD_RRB		0x04
+#define CMD_CDO		0x08
+#define CMD_GTS		0x10
+
+/* status register */
+#define SR_RBS		0x01
+#define SR_DOS		0x02
+#define SR_TBS		0x04
+#define SR_TCS		0x08
+#define SR_RS		0x10
+#define SR_TS		0x20
+#define SR_ES		0x40
+#define SR_BS		0x80
+
+/* interrupt sources */
+#define IRQ_RI		0x01
+#define IRQ_TI		0x02
+#define IRQ_EI		0x04
+#define IRQ_DOI		0x08
+#define IRQ_WUI		0x10
+
+#define FI_RTR		0x10
+
+#endif /* SJA1000_PELICAN_MODE */
 
 /*
  * Flags for sja1000priv.flags

[-- Attachment #2: socketcan_sja1000_basicmod_impl.patch --]
[-- Type: application/octet-stream, Size: 11279 bytes --]

diff -ru trunk.orig/kernel/2.6/drivers/net/can/sja1000/sja1000.c trunk/kernel/2.6/drivers/net/can/sja1000/sja1000.c
--- trunk.orig/kernel/2.6/drivers/net/can/sja1000/sja1000.c	2011-11-14 20:46:35.074737955 +0400
+++ trunk/kernel/2.6/drivers/net/can/sja1000/sja1000.c	2011-11-14 20:56:00.083183431 +0400
@@ -117,22 +117,43 @@
 static void set_reset_mode(struct net_device *dev)
 {
 	struct sja1000_priv *priv = netdev_priv(dev);
+#ifdef SJA1000_PELICAN_MODE
 	unsigned char status = priv->read_reg(priv, REG_MOD);
+#else
+	unsigned char status = priv->read_reg(priv, REG_CR);
+#endif
 	int i;
 
 	/* disable interrupts */
+#ifdef SJA1000_PELICAN_MODE
 	priv->write_reg(priv, REG_IER, IRQ_OFF);
+#else
+	priv->write_reg(priv, REG_CR, status & IRQ_OFF);
+#endif
 
 	for (i = 0; i < 100; i++) {
-		/* check reset bit */
+		// check reset bit
+#ifdef SJA1000_PELICAN_MODE
 		if (status & MOD_RM) {
+#else
+		if (status & CR_RRQ) {
+#endif
 			priv->can.state = CAN_STATE_STOPPED;
 			return;
 		}
 
-		priv->write_reg(priv, REG_MOD, MOD_RM);	/* reset chip */
+    	/* reset chip */
+#ifdef SJA1000_PELICAN_MODE
+		priv->write_reg(priv, REG_MOD, MOD_RM);
+#else
+		priv->write_reg(priv, REG_CR, CR_RRQ);
+#endif
 		udelay(10);
+#ifdef SJA1000_PELICAN_MODE
 		status = priv->read_reg(priv, REG_MOD);
+#else
+		status = priv->read_reg(priv, REG_CR);
+#endif
 	}
 
 	dev_err(ND2D(dev), "setting SJA1000 into reset mode failed!\n");
@@ -141,26 +162,50 @@
 static void set_normal_mode(struct net_device *dev)
 {
 	struct sja1000_priv *priv = netdev_priv(dev);
+#ifdef SJA1000_PELICAN_MODE
 	unsigned char status = priv->read_reg(priv, REG_MOD);
+#else
+	unsigned char status = priv->read_reg(priv, REG_CR);
+#endif
 	int i;
 
 	for (i = 0; i < 100; i++) {
 		/* check reset bit */
+#ifdef SJA1000_PELICAN_MODE
 		if ((status & MOD_RM) == 0) {
+#else
+		if ((status & CR_RRQ) == 0) {
+#endif
 			priv->can.state = CAN_STATE_ERROR_ACTIVE;
 			/* enable interrupts */
+#ifdef SJA1000_PELICAN_MODE
 			if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
 				priv->write_reg(priv, REG_IER, IRQ_ALL);
+
 			else
 				priv->write_reg(priv, REG_IER,
 						IRQ_ALL & ~IRQ_BEI);
 			return;
+#else
+			priv->write_reg(priv, REG_CR, status | IRQ_ALL);
+			return;
+#endif
 		}
 
+
 		/* set chip to normal mode */
+#ifdef SJA1000_PELICAN_MODE
 		priv->write_reg(priv, REG_MOD, 0x00);
+#else
+		//status = priv->read_reg(priv, REG_CR);
+		priv->write_reg(priv, REG_CR, status & ~CR_RRQ);
+#endif
 		udelay(10);
+#ifdef SJA1000_PELICAN_MODE
 		status = priv->read_reg(priv, REG_MOD);
+#else
+		status = priv->read_reg(priv, REG_CR);
+#endif
 	}
 
 	dev_err(ND2D(dev), "setting SJA1000 into normal mode failed!\n");
@@ -175,9 +220,11 @@
 		set_reset_mode(dev);
 
 	/* Clear error counters and error code capture */
+#ifdef SJA1000_PELICAN_MODE
 	priv->write_reg(priv, REG_TXERR, 0x0);
 	priv->write_reg(priv, REG_RXERR, 0x0);
 	priv->read_reg(priv, REG_ECC);
+#endif
 
 	/* leave reset mode */
 	set_normal_mode(dev);
@@ -230,8 +277,13 @@
 {
 	struct sja1000_priv *priv = netdev_priv(dev);
 
+#ifdef SJA1000_PELICAN_MODE
 	bec->txerr = priv->read_reg(priv, REG_TXERR);
 	bec->rxerr = priv->read_reg(priv, REG_RXERR);
+#else
+	bec->txerr = 0;
+	bec->rxerr = 0;
+#endif
 
 	return 0;
 }
@@ -247,11 +299,17 @@
 static void chipset_init(struct net_device *dev)
 {
 	struct sja1000_priv *priv = netdev_priv(dev);
+	struct can_bittiming bt;
 
 	/* set clock divider and output control register */
+#ifdef SJA1000_PELICAN_MODE
 	priv->write_reg(priv, REG_CDR, priv->cdr | CDR_PELICAN);
+#else
+	priv->write_reg(priv, REG_CDR, priv->cdr);
+#endif
 
 	/* set acceptance filter (accept all) */
+#ifdef SJA1000_PELICAN_MODE
 	priv->write_reg(priv, REG_ACCC0, 0x00);
 	priv->write_reg(priv, REG_ACCC1, 0x00);
 	priv->write_reg(priv, REG_ACCC2, 0x00);
@@ -261,6 +319,11 @@
 	priv->write_reg(priv, REG_ACCM1, 0xFF);
 	priv->write_reg(priv, REG_ACCM2, 0xFF);
 	priv->write_reg(priv, REG_ACCM3, 0xFF);
+#else
+	priv->write_reg(priv, REG_AC, 0x00);
+	priv->write_reg(priv, REG_AM, 0xFF);
+	
+#endif
 
 	priv->write_reg(priv, REG_OCR, priv->ocr | OCR_MODE_NORMAL);
 }
@@ -298,6 +361,8 @@
 		fi |= FI_RTR;
 
 	if (id & CAN_EFF_FLAG) {
+	    /* Extended frame. Not available in BasicCAN mode. */
+#ifdef SJA1000_PELICAN_MODE
 		fi |= FI_FF;
 		dreg = EFF_BUF;
 		priv->write_reg(priv, REG_FI, fi);
@@ -305,15 +370,26 @@
 		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);
+#endif
 	} else {
+	/* Standard frame */
+#ifdef SJA1000_PELICAN_MODE
 		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);
+#else
+		priv->write_reg(priv, REG_TXB, (id & 0x000007f8) >> 3);
+		priv->write_reg(priv, REG_TXB + 1, ((id & 0x00000007) << 5) | fi);
+#endif
 	}
 
 	for (i = 0; i < dlc; i++)
+#ifdef SJA1000_PELICAN_MODE
 		priv->write_reg(priv, dreg++, cf->data[i]);
+#else
+		priv->write_reg(priv, REG_TXB + 2 + i, cf->data[i]);
+#endif
 
 	dev->trans_start = jiffies;
 
@@ -344,8 +420,14 @@
 	if (skb == NULL)
 		return;
 
+#ifdef SJA1000_PELICAN_MODE
 	fi = priv->read_reg(priv, REG_FI);
+#else
+    /* Read RTR & DLC */
+	fi = priv->read_reg(priv, REG_RXB + 1) & 0x1F;
+#endif
 
+#ifdef SJA1000_PELICAN_MODE
 	if (fi & FI_FF) {
 		/* extended frame format (EFF) */
 		dreg = EFF_BUF;
@@ -360,13 +442,22 @@
 		id = (priv->read_reg(priv, REG_ID1) << 3)
 		    | (priv->read_reg(priv, REG_ID2) >> 5);
 	}
+#else
+	id = (priv->read_reg(priv, REG_RXB) << 3)
+		| ((priv->read_reg(priv, REG_RXB + 1) & 0xE0) >> 5);
+#endif
 
 	if (fi & FI_RTR) {
 		id |= CAN_RTR_FLAG;
 	} else {
+		/* DLC field is same in TXB/RXB (basiccan) and FI (pelican) registers */
 		cf->can_dlc = get_can_dlc(fi & 0x0F);
 		for (i = 0; i < cf->can_dlc; i++)
+#ifdef SJA1000_PELICAN_MODE
 			cf->data[i] = priv->read_reg(priv, dreg++);
+#else
+			cf->data[i] = priv->read_reg(priv, REG_RXB + 2 + i);
+#endif
 	}
 
 	cf->can_id = id;
@@ -423,6 +514,7 @@
 		} else
 			state = CAN_STATE_ERROR_ACTIVE;
 	}
+#ifdef SJA1000_PELICAN_MODE /* BasicCAN mode doesn't support Bus Error Interrupt */
 	if (isrc & IRQ_BEI) {
 		/* bus error interrupt */
 		priv->can.can_stats.bus_error++;
@@ -451,6 +543,9 @@
 		if ((ecc & ECC_DIR) == 0)
 			cf->data[2] |= CAN_ERR_PROT_TX;
 	}
+#endif
+
+#ifdef SJA1000_PELICAN_MODE /* BasicCAN mode doesn't support Error Passive Interrupt */
 	if (isrc & IRQ_EPI) {
 		/* error passive interrupt */
 		dev_dbg(ND2D(dev), "error passive interrupt\n");
@@ -459,6 +554,9 @@
 		else
 			state = CAN_STATE_ERROR_ACTIVE;
 	}
+#endif
+
+#ifdef SJA1000_PELICAN_MODE /* BasicCAN mode doesn't support Arbitration Lost Interrupt */
 	if (isrc & IRQ_ALI) {
 		/* arbitration lost interrupt */
 		dev_dbg(ND2D(dev), "arbitration lost interrupt\n");
@@ -468,11 +566,18 @@
 		cf->can_id |= CAN_ERR_LOSTARB;
 		cf->data[0] = alc & 0x1f;
 	}
+#endif
 
 	if (state != priv->can.state && (state == CAN_STATE_ERROR_WARNING ||
 					 state == CAN_STATE_ERROR_PASSIVE)) {
+#ifdef SJA1000_PELICAN_MODE
 		uint8_t rxerr = priv->read_reg(priv, REG_RXERR);
 		uint8_t txerr = priv->read_reg(priv, REG_TXERR);
+#else
+		uint8_t rxerr = 0;
+		uint8_t txerr = 0;
+#endif
+
 		cf->can_id |= CAN_ERR_CRTL;
 		if (state == CAN_STATE_ERROR_WARNING) {
 			priv->can.can_stats.error_warning++;
@@ -519,7 +624,11 @@
 	int n = 0;
 
 	/* Shared interrupts and IRQ off? */
+#ifdef SJA1000_PELICAN_MODE
 	if (priv->read_reg(priv, REG_IER) == IRQ_OFF)
+#else
+	if ((priv->read_reg(priv, REG_CR) & IRQ_ALL) == 0)
+#endif
 		return IRQ_NONE;
 
 	if (priv->pre_irq)
@@ -534,7 +643,11 @@
 
 		if (isrc & IRQ_TI) {
 			/* transmission complete interrupt */
-			stats->tx_bytes += priv->read_reg(priv, REG_FI) & 0xf;
+#ifdef SJA1000_PELICAN_MODE
+			stats->tx_bytes += priv->read_reg(priv, REG_FI) & 0xF;
+#else
+			stats->tx_bytes += priv->read_reg(priv, REG_TXB + 1) & 0xF;
+#endif
 			stats->tx_packets++;
 			can_get_echo_skb(dev, 0);
 			netif_wake_queue(dev);
@@ -546,7 +659,11 @@
 				status = priv->read_reg(priv, REG_SR);
 			}
 		}
+#ifdef SJA1000_PELICAN_MODE
 		if (isrc & (IRQ_DOI | IRQ_EI | IRQ_BEI | IRQ_EPI | IRQ_ALI)) {
+#else
+		if (isrc & (IRQ_DOI | IRQ_EI)) {
+#endif
 			/* error interrupt */
 			if (sja1000_err(dev, isrc, status))
 				break;
diff -ru trunk.orig/kernel/2.6/drivers/net/can/sja1000/sja1000.h trunk/kernel/2.6/drivers/net/can/sja1000/sja1000.h
--- trunk.orig/kernel/2.6/drivers/net/can/sja1000/sja1000.h	2011-11-14 20:49:44.526408577 +0400
+++ trunk/kernel/2.6/drivers/net/can/sja1000/sja1000.h	2011-11-14 20:50:20.813395105 +0400
@@ -50,10 +50,14 @@
 #include <socketcan/can/dev.h>
 #include <socketcan/can/platform/sja1000.h>
 
+#define SJA1000_PELICAN_MODE /* BasicCAN accepted if not defined */
+
 #define SJA1000_ECHO_SKB_MAX	1 /* the SJA1000 has one TX buffer object */
 
 #define SJA1000_MAX_IRQ 20	/* max. number of interrupts handled in ISR */
 
+#ifdef SJA1000_PELICAN_MODE
+
 /* SJA1000 registers - manual section 6.4 (Pelican Mode) */
 #define REG_MOD		0x00
 #define REG_CMR		0x01
@@ -76,19 +80,10 @@
 #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
@@ -96,6 +91,27 @@
 
 #define CAN_RAM		0x20
 
+#else /* SJA1000_PELICAN_MODE */
+
+/* SJA1000 registers - manual section 6.3 (Basiccan Mode) */
+#define REG_CR		0x00
+#define REG_CMR		0x01
+#define REG_SR		0x02
+#define REG_IR		0x03
+#define REG_AC		0x04
+#define REG_AM		0x05
+#define REG_TXB		0x0A
+#define REG_RXB		0x14
+
+#endif /* SJA1000_PELICAN_MODE */
+
+/* Common registers - manual section 6.5 */
+#define REG_BTR0	0x06
+#define REG_BTR1	0x07
+#define REG_OCR		0x08
+#define REG_CDR		0x1F
+
+#ifdef SJA1000_PELICAN_MODE
 /* mode register */
 #define MOD_RM		0x01
 #define MOD_LOM		0x02
@@ -137,11 +153,53 @@
 /* ECC register */
 #define ECC_SEG		0x1F
 #define ECC_DIR		0x20
-#define ECC_ERR		6
+#define ECC_ERR		0x06
 #define ECC_BIT		0x00
 #define ECC_FORM	0x40
 #define ECC_STUFF	0x80
-#define ECC_MASK	0xc0
+#define ECC_MASK	0xC0
+
+#define FI_FF		0x80
+#define FI_RTR		0x40
+
+#else /* SJA1000_PELICAN_MODE */
+
+/* control register */
+#define CR_RRQ		0x01
+#define CR_RIE		0x02
+#define CR_TIE		0x04
+#define CR_EIE		0x08
+#define CR_OIE		0x10
+#define IRQ_OFF		CR_RRQ
+#define IRQ_ALL		(CR_RIE | CR_TIE | CR_EIE | CR_OIE)
+
+/* command register */
+#define CMD_TR		0x01
+#define CMD_AT		0x02
+#define CMD_RRB		0x04
+#define CMD_CDO		0x08
+#define CMD_GTS		0x10
+
+/* status register */
+#define SR_RBS		0x01
+#define SR_DOS		0x02
+#define SR_TBS		0x04
+#define SR_TCS		0x08
+#define SR_RS		0x10
+#define SR_TS		0x20
+#define SR_ES		0x40
+#define SR_BS		0x80
+
+/* interrupt sources */
+#define IRQ_RI		0x01
+#define IRQ_TI		0x02
+#define IRQ_EI		0x04
+#define IRQ_DOI		0x08
+#define IRQ_WUI		0x10
+
+#define FI_RTR		0x10
+
+#endif /* SJA1000_PELICAN_MODE */
 
 /*
  * Flags for sja1000priv.flags

[-- Attachment #3: Type: text/plain, Size: 191 bytes --]

_______________________________________________
Socketcan-users mailing list
Socketcan-users-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org
https://lists.berlios.de/mailman/listinfo/socketcan-users

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: sja1000 BasicCAN mode
       [not found] ` <CAF8b2jLH8CTOU5ZBTdH7yFhhb0=QmP2Y_Lkom80Bxfw0AvjA6g@mail.gmail.com>
@ 2011-11-14 20:02   ` Oliver Hartkopp
  0 siblings, 0 replies; 3+ messages in thread
From: Oliver Hartkopp @ 2011-11-14 20:02 UTC (permalink / raw)
  To: Yuriy Kiselev; +Cc: linux-can


> 
>     what's your motivation for the BasicCAN mode support?
> 
> BasicCAN is used for current version of protocol in our network.


Hm, are you sure that you are not mixing up the BasicCAN mode of the SJA1000
controller with standard frame format CAN frames??

BasicCAN/FullCAN is usually a misleading and therefore outdated classification
for CAN controllers having different filter and receive message box layouts.

What kind of SJA1000 CAN controller are you using?

- SJA1000
- 82C200
- FPGA implementaion from opencores
- ???

Regards,
Oliver

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2011-11-14 20:02 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-11-14 18:03 sja1000 BasicCAN mode Oliver Hartkopp
     [not found] ` <CAF8b2jLH8CTOU5ZBTdH7yFhhb0=QmP2Y_Lkom80Bxfw0AvjA6g@mail.gmail.com>
2011-11-14 20:02   ` Oliver Hartkopp
  -- strict thread matches above, loose matches on Subject: below --
2011-11-14 17:08 Yuriy Kiselev

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).