All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [RFC 0/5] CAN framework for U-Boot
@ 2009-11-01 11:33 Wolfgang Grandegger
  2009-11-01 11:33 ` [U-Boot] [RFC 1/5] CAN interface library Wolfgang Grandegger
  0 siblings, 1 reply; 18+ messages in thread
From: Wolfgang Grandegger @ 2009-11-01 11:33 UTC (permalink / raw)
  To: u-boot

From: Wolfgang Grandegger <wg@denx.de>

This patch series adds a simple CAN framework for U-Boot. The main purpose
is to do simple RX/TX testing when the device boots up but the interface
functions could also be used for more complex tasks. This is just a RFC
and a few more features need to be added or issues to be fixed, like
using a generic device interface, if it already exists, and board
specific device configuration, e.g. via i82527_register(addr, cfg-params).
The sources are based on GPL v2+ code to be compatible with future U-Boot
licence requirement.

Please comment.

Wolfgang

Wolfgang Grandegger (5):
  CAN interface library
  CAN device test command
  CAN device driver for the SJA1000
  CAN device driver for the Intel 82527
  CAN interface support for the TQM855L module

 Makefile                  |    1 +
 board/tqc/tqm8xx/tqm8xx.c |   17 ++
 common/Makefile           |    1 +
 common/cmd_can.c          |  119 +++++++++++++++
 drivers/can/Makefile      |   49 ++++++
 drivers/can/can.c         |   88 +++++++++++
 drivers/can/i82527.c      |  366 +++++++++++++++++++++++++++++++++++++++++++++
 drivers/can/sja1000.c     |  223 +++++++++++++++++++++++++++
 include/can.h             |   70 +++++++++
 include/configs/TQM855L.h |    8 +-
 include/i82527.h          |  201 +++++++++++++++++++++++++
 include/sja1000.h         |  159 ++++++++++++++++++++
 12 files changed, 1301 insertions(+), 1 deletions(-)
 create mode 100644 common/cmd_can.c
 create mode 100644 drivers/can/Makefile
 create mode 100644 drivers/can/can.c
 create mode 100644 drivers/can/i82527.c
 create mode 100644 drivers/can/sja1000.c
 create mode 100644 include/can.h
 create mode 100644 include/i82527.h
 create mode 100644 include/sja1000.h

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

* [U-Boot] [RFC 1/5] CAN interface library
  2009-11-01 11:33 [U-Boot] [RFC 0/5] CAN framework for U-Boot Wolfgang Grandegger
@ 2009-11-01 11:33 ` Wolfgang Grandegger
  2009-11-01 11:33   ` [U-Boot] [RFC 2/5] CAN device test command Wolfgang Grandegger
  2009-11-01 14:36   ` [U-Boot] [RFC 1/5] CAN interface library Mike Frysinger
  0 siblings, 2 replies; 18+ messages in thread
From: Wolfgang Grandegger @ 2009-11-01 11:33 UTC (permalink / raw)
  To: u-boot

From: Wolfgang Grandegger <wg@denx.de>

Signed-off-by: Wolfgang Grandegger <wg@denx.de>
---
 Makefile             |    1 +
 drivers/can/Makefile |   47 ++++++++++++++++++++++++++
 drivers/can/can.c    |   88 ++++++++++++++++++++++++++++++++++++++++++++++++++
 include/can.h        |   70 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 206 insertions(+), 0 deletions(-)
 create mode 100644 drivers/can/Makefile
 create mode 100644 drivers/can/can.c
 create mode 100644 include/can.h

diff --git a/Makefile b/Makefile
index bcb3fe9..dca15e0 100644
--- 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 100644
index 0000000..74d2ff5
--- /dev/null
+++ b/drivers/can/Makefile
@@ -0,0 +1,47 @@
+#
+# Copyright 2000-2008
+# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+#
+# 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-$(CONFIG_CAN)	+= can.o
+
+COBJS	:= $(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.c b/drivers/can/can.c
new file mode 100644
index 0000000..c09bccf
--- /dev/null
+++ b/drivers/can/can.c
@@ -0,0 +1,88 @@
+/*
+ * (C) Copyright 2007-2009, Wolfgang Grandegger <wg@denx.de>
+ *
+ * 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
+ */
+
+/*
+ * CAN device interface library
+ */
+#include <common.h>
+#include <command.h>
+#include <can.h>
+
+static struct can_dev *can_devs;
+
+static char *baudrates[] = { "125K", "250K", "500K" };
+
+int can_register (struct can_dev* can_dev)
+{
+	struct can_dev* dev;
+
+	can_dev->next = NULL;
+	if (!can_devs)
+		can_devs = can_dev;
+	else {
+		for (dev = can_devs; dev->next; dev = dev->next)
+			    ;
+		dev->next = can_dev;
+	}
+
+	printf ("CAN: %s at %lx registered\n", can_dev->name, can_dev->base);
+
+	return 0;
+}
+
+struct can_dev *can_init (int dev_num, int ibaud)
+{
+	struct can_dev *dev;
+	int i;
+
+	if (!can_devs) {
+		puts ("No CAN devices registered\n");
+		return NULL;
+	}
+
+	/* Advance to selected device */
+	for (i = 0, dev = can_devs; dev; i++, dev = dev->next) {
+		if (i == dev_num)
+			break;
+	}
+
+	if (!dev) {
+		printf ("CAN device %d does not exist\n", dev_num);
+		return NULL;
+	}
+
+	printf ("Initializing CAN%d at 0x%08x with baudrate %s\n",
+		i, dev->base, baudrates[ibaud]);
+
+	dev->init (dev, ibaud);
+
+	return dev;
+}
+
+void can_list (void)
+{
+	struct can_dev *dev;
+	int i;
+
+	for (i = 0, dev = can_devs; dev; i++, dev = dev->next)
+		printf ("CAN%d: %s at 0x%p\n", i, dev->name, dev->base);
+}
diff --git a/include/can.h b/include/can.h
new file mode 100644
index 0000000..5f5c3c1
--- /dev/null
+++ b/include/can.h
@@ -0,0 +1,70 @@
+/*
+ * (C) Copyright 2007-2009, Wolfgang Grandegger <wg@denx.de>
+ *
+ * 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 __CAN_H__
+#define __CAN_H__
+
+#define CAN_XMIT_TIMEOUT_US 1000000
+
+#define CAN_EFF_MASK  0x1FFFFFFF
+#define CAN_SFF_MASK  0x000007FF
+
+#define CAN_EFF_FLAG  0x80000000
+#define CAN_RTR_FLAG  0x40000000
+
+struct can_msg {
+	u32 id;
+	u8  data[8];
+	u8  dlc;
+	u8  flags;
+};
+
+struct can_dev {
+	char *name;
+	unsigned long base;
+	int (*init) (struct can_dev *dev, unsigned int ibaud);
+	int (*xmit) (struct can_dev *dev, struct can_msg *msg);
+	int (*recv) (struct can_dev *dev, struct can_msg *msg);
+	int (*status) (struct can_dev *dev, int level);
+	struct can_dev *next;
+};
+
+static inline int can_status (struct can_dev *dev, int level)
+{
+	return dev->status (dev, level);
+}
+
+static inline int can_recv (struct can_dev *dev, struct can_msg *msg)
+{
+	return dev->recv (dev, msg);
+}
+
+static inline int can_xmit (struct can_dev *dev, struct can_msg *msg)
+{
+	return dev->xmit (dev, msg);
+}
+
+int can_register (struct can_dev* dev);
+struct can_dev *can_init (int dev_nr, int ibaud);
+void can_list (void);
+
+#endif /* __CAN_H__ */
-- 
1.6.2.5

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

* [U-Boot] [RFC 2/5] CAN device test command
  2009-11-01 11:33 ` [U-Boot] [RFC 1/5] CAN interface library Wolfgang Grandegger
@ 2009-11-01 11:33   ` Wolfgang Grandegger
  2009-11-01 11:33     ` [U-Boot] [RFC 3/5] CAN device driver for the SJA1000 Wolfgang Grandegger
  2009-11-01 14:45     ` [U-Boot] [RFC 2/5] CAN device test command Mike Frysinger
  2009-11-01 14:36   ` [U-Boot] [RFC 1/5] CAN interface library Mike Frysinger
  1 sibling, 2 replies; 18+ messages in thread
From: Wolfgang Grandegger @ 2009-11-01 11:33 UTC (permalink / raw)
  To: u-boot

From: Wolfgang Grandegger <wg@denx.de>

Signed-off-by: Wolfgang Grandegger <wg@denx.de>
---
 common/Makefile  |    1 +
 common/cmd_can.c |  119 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 120 insertions(+), 0 deletions(-)
 create mode 100644 common/cmd_can.c

diff --git a/common/Makefile b/common/Makefile
index 3781738..b7f4c22 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -72,6 +72,7 @@ COBJS-$(CONFIG_CMD_BEDBUG) += bedbug.o cmd_bedbug.o
 COBJS-$(CONFIG_CMD_BMP) += cmd_bmp.o
 COBJS-$(CONFIG_CMD_BOOTLDR) += cmd_bootldr.o
 COBJS-$(CONFIG_CMD_CACHE) += cmd_cache.o
+COBJS-$(CONFIG_CMD_CAN) += cmd_can.o
 COBJS-$(CONFIG_CMD_CONSOLE) += cmd_console.o
 COBJS-$(CONFIG_CMD_CPLBINFO) += cmd_cplbinfo.o
 COBJS-$(CONFIG_DATAFLASH_MMC_SELECT) += cmd_dataflash_mmc_mux.o
diff --git a/common/cmd_can.c b/common/cmd_can.c
new file mode 100644
index 0000000..af7bf34
--- /dev/null
+++ b/common/cmd_can.c
@@ -0,0 +1,119 @@
+/*
+ * (C) Copyright 2007-2009, Wolfgang Grandegger <wg@denx.de>
+ *
+ * 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
+ */
+
+/*
+ * CAN device test command
+ */
+#include <common.h>
+#include <command.h>
+#include <can.h>
+
+static struct can_dev *can_dev;
+
+int do_can (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+	struct can_msg msg;
+	char op;
+	int i;
+
+	op = argv[1][0];
+
+	if (argc < 2) {
+		can_list ();
+		return 0;
+	}
+
+	if (!can_dev && op != 'i') {
+		can_dev = can_init (0, 0);
+		if (!can_dev)
+			return 1;
+	}
+
+	if (op == 's') {
+		unsigned int level = 0;
+		if (argc > 2)
+			level = simple_strtoul (argv[2], NULL, 10);
+		can_status (can_dev, level);
+	}
+
+	else if (op == 'i') {
+		unsigned int dev_num = 0, ibaud = 0;
+		struct can_dev *dev;
+
+		if (argc > 2)
+			dev_num = simple_strtoul (argv[2], NULL, 10);
+		if (argc > 3) {
+			ibaud = simple_strtoul (argv[3], NULL, 10);
+			if (ibaud > 2)
+				ibaud = 2;
+		}
+		dev = can_init (dev_num, ibaud);
+		if (!dev)
+			return 1;
+		can_dev = dev;
+	}
+
+	else if (op == 'r') {
+		while (!can_recv (can_dev, &msg)) {
+			printf ("<0x%03x>", msg.id & CAN_SFF_MASK);
+
+			printf (" [%d]", msg.dlc);
+			if (msg.id & CAN_RTR_FLAG)
+				puts (" rtr");
+			else {
+				for (i = 0; i < msg.dlc; i++)
+					printf (" %02x", msg.data[i]);
+			}
+			puts ("\n");
+		}
+	} else if (op == 'x') {
+		memset (&msg, 0, sizeof (msg));
+		msg.id = 0x123;
+		if (argc > 2)
+		    msg.id = simple_strtoul (argv[2], NULL, 16);
+		for (i = 0; argc > (3 + i); i++, msg.dlc++) {
+			msg.data[i] = simple_strtoul (argv[3 + i], NULL, 16);
+		}
+		if (argc == 2)
+			printf ("Transmitting id %#x dlc %d\n",
+				msg.id, msg.dlc);
+
+		if (can_xmit (can_dev, &msg))
+			puts("FAILED\n");
+		else
+			puts("OK\n");
+	} else {
+		printf ("Usage:\n%s\n", cmdtp->usage);
+		return 1;
+	}
+
+	return 0;
+}
+
+U_BOOT_CMD(
+	can, 3,	1, do_can,
+	"can - CAN bus commands\n",
+	"can status [level]\n"
+	"can init [dev] [baud-index]\n"
+	"can xmit [id] [d0] [d1] ... [d7]\n"
+	"can recv, abort with CTRL-C\n"
+);
-- 
1.6.2.5

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

* [U-Boot] [RFC 3/5] CAN device driver for the SJA1000
  2009-11-01 11:33   ` [U-Boot] [RFC 2/5] CAN device test command Wolfgang Grandegger
@ 2009-11-01 11:33     ` Wolfgang Grandegger
  2009-11-01 11:33       ` [U-Boot] [RFC 4/5] CAN device driver for the Intel 82527 Wolfgang Grandegger
  2009-11-02 12:02       ` [U-Boot] [RFC 3/5] CAN device driver for the SJA1000 Matthias Fuchs
  2009-11-01 14:45     ` [U-Boot] [RFC 2/5] CAN device test command Mike Frysinger
  1 sibling, 2 replies; 18+ messages in thread
From: Wolfgang Grandegger @ 2009-11-01 11:33 UTC (permalink / raw)
  To: u-boot

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__ */
+
-- 
1.6.2.5

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

* [U-Boot] [RFC 4/5] CAN device driver for the Intel 82527
  2009-11-01 11:33     ` [U-Boot] [RFC 3/5] CAN device driver for the SJA1000 Wolfgang Grandegger
@ 2009-11-01 11:33       ` Wolfgang Grandegger
  2009-11-01 11:33         ` [U-Boot] [RFC 5/5] CAN interface support for the TQM855L module Wolfgang Grandegger
  2009-11-02 12:02       ` [U-Boot] [RFC 3/5] CAN device driver for the SJA1000 Matthias Fuchs
  1 sibling, 1 reply; 18+ messages in thread
From: Wolfgang Grandegger @ 2009-11-01 11:33 UTC (permalink / raw)
  To: u-boot

From: Wolfgang Grandegger <wg@denx.de>

Signed-off-by: Wolfgang Grandegger <wg@denx.de>
---
 drivers/can/Makefile |    1 +
 drivers/can/i82527.c |  366 ++++++++++++++++++++++++++++++++++++++++++++++++++
 include/i82527.h     |  201 +++++++++++++++++++++++++++
 3 files changed, 568 insertions(+), 0 deletions(-)
 create mode 100644 drivers/can/i82527.c
 create mode 100644 include/i82527.h

diff --git a/drivers/can/Makefile b/drivers/can/Makefile
index e2b6bd6..d550a45 100644
--- a/drivers/can/Makefile
+++ b/drivers/can/Makefile
@@ -26,6 +26,7 @@ include $(TOPDIR)/config.mk
 LIB 	:= $(obj)libcan.a
 
 COBJS-$(CONFIG_CAN)		+= can.o
+COBJS-$(CONFIG_CAN_I82527)	+= i82527.o
 COBJS-$(CONFIG_CAN_SJA1000)	+= sja1000.o
 
 COBJS	:= $(COBJS-y)
diff --git a/drivers/can/i82527.c b/drivers/can/i82527.c
new file mode 100644
index 0000000..b3eacd6
--- /dev/null
+++ b/drivers/can/i82527.c
@@ -0,0 +1,366 @@
+/*
+ * (C) Copyright 2007-2009, Wolfgang Grandegger <wg@denx.de>
+ *
+ * Derived from OCAN driver:
+ *
+ * Copyright (C) 2002 Alessandro Rubini <rubini@linux.it>
+ * Copyright (C) 2002 System SpA <info.electronics@system-group.it>
+ *
+ * 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 <i82527.h>
+
+#define I82527_TX_OBJ	1
+#define I82527_RX_OBJ	15
+
+/*
+ * Basic functions to access registers
+ */
+#define i82527_read_reg(dev, reg)			\
+	in_8 ((volatile u8 *)((dev)->base + (reg)))
+
+#define i82527_write_reg(dev, reg, value)			\
+	out_8 ((volatile u8 *)((dev)->base + (reg)), value)
+
+/*
+ * Higher level functions
+ */
+static inline int i82527_read_msgcfg (struct can_dev *dev, int iobj)
+{
+	return i82527_read_reg (dev, (iobj * I82527_MSG_OFF) + I82527_MSG_CFG);
+}
+
+static inline void i82527_write_msgcfg (struct can_dev *dev, int iobj, int val)
+{
+	i82527_write_reg (dev, (iobj * I82527_MSG_OFF) + I82527_MSG_CFG, val);
+}
+
+static inline void i82527_write_std_mask (struct can_dev *dev, u16 val)
+{
+	/* errors are ignored, hmm... */
+	i82527_write_reg (dev, I82527_GMASK_STD, val >> 8);
+	i82527_write_reg (dev, I82527_GMASK_STD + 1, val & 0xff);
+}
+
+static inline void i82527_write_x_mask (struct can_dev *dev, u32 val)
+{
+	/* errors are ignored, hmm... */
+	i82527_write_reg (dev, I82527_GMASK_XTD, val >> 24);
+	i82527_write_reg (dev, I82527_GMASK_XTD + 1, (val >> 16) & 0xff);
+	i82527_write_reg (dev, I82527_GMASK_XTD + 2, (val >> 8) & 0xff);
+	i82527_write_reg (dev, I82527_GMASK_XTD + 3, (val >> 0) & 0xff);
+}
+
+static inline void i82527_write_15_mask (struct can_dev *dev, u32 val)
+{
+	/* errors are ignored, hmm... */
+	i82527_write_reg (dev, I82527_MSG15_MASK, val >> 24);
+	i82527_write_reg (dev, I82527_MSG15_MASK + 1, (val >> 16) & 0xff);
+	i82527_write_reg (dev, I82527_MSG15_MASK + 2, (val >> 8) & 0xff);
+	i82527_write_reg (dev, I82527_MSG15_MASK + 3, (val >> 0) & 0xff);
+}
+
+static inline void i82527_write_msgctrl (struct can_dev *dev, int iobj, u16 val)
+{
+	/* FIXME: this is used little-endian, but doesn't need to be 16b */
+
+	/* errors are ignored, hmm... */
+	i82527_write_reg (dev, (iobj * I82527_MSG_OFF) +
+			  I82527_MSG_CTRL, val & 0xff);
+	i82527_write_reg (dev, (iobj * I82527_MSG_OFF) +
+			  I82527_MSG_CTRL + 1, val >> 8);
+}
+
+/* write a single byte of msgctrl, twice as fast as the function above */
+static inline void i82527_msgflag (struct can_dev *dev, int iobj, u16 act)
+{
+	if ((act & 0xff) == 0xff)
+		i82527_write_reg (dev, (iobj * I82527_MSG_OFF) +
+				  I82527_MSG_CTRL + 1, act >> 8);
+	else
+		i82527_write_reg (dev, (iobj * I82527_MSG_OFF) +
+				  I82527_MSG_CTRL, act & 0xff);
+}
+
+static inline u32 i82527_read_msgarb (struct can_dev *dev, int iobj)
+{
+	int port = (iobj * I82527_MSG_OFF) + I82527_MSG_ARBIT;
+
+	u32 ret = (i82527_read_reg (dev, port) << 24 |
+		   i82527_read_reg (dev, port + 1) << 16 |
+		   i82527_read_reg (dev, port + 2) << 8 |
+		   i82527_read_reg (dev, port + 3));
+	return ret;
+}
+
+static inline void i82527_write_msgarb (struct can_dev *dev, int iobj, u32 val)
+{
+	int port = (iobj * I82527_MSG_OFF) + I82527_MSG_ARBIT;
+	i82527_write_reg (dev, port, val >> 24);
+	i82527_write_reg (dev, port + 1, (val >> 16) & 0xff);
+	i82527_write_reg (dev, port + 2, (val >> 8) & 0xff);
+	i82527_write_reg (dev, port + 3, (val >> 0) & 0xff);
+}
+
+static inline void i82527_read_msgdata (struct can_dev *dev, int iobj,
+					int n, u8 * data)
+{
+	int i;
+	u8 reg = (iobj * I82527_MSG_OFF) + I82527_MSG_DATA;
+
+	for (i = 0; i < n; i++)
+		data[i] = i82527_read_reg (dev, reg++);
+}
+
+static inline void i82527_write_msgdata (struct can_dev *dev, int iobj,
+					 int n, u8 * data)
+{
+	int i;
+	u8 reg = (iobj * I82527_MSG_OFF) + I82527_MSG_DATA;
+
+	if (!n)
+		return;
+	i82527_msgflag (dev, iobj, I82527_CPUUPD_S);	/* CPU updating */
+	for (i = 0; i < n && i < 8; i++)
+		i82527_write_reg (dev, reg++, data[i]);
+	i82527_msgflag (dev, iobj, I82527_CPUUPD_R);
+}
+
+static struct i82527_times i82527_baudrates[] = {
+	{1, 0, 0, 2, 0, 0, 3, 12, 1},	/* 125K */
+	{1, 0, 0, 2, 0, 0, 1, 12, 1},	/* 250K */
+	{1, 0, 0, 2, 0, 0, 0, 12, 1}	/* 500K */
+};
+
+static void i82527_baudrate (struct can_dev *dev, unsigned int ibaud)
+{
+	struct i82527_times *times;
+	int i;
+
+	i = sizeof (i82527_baudrates) / sizeof (struct i82527_times);
+	if (ibaud >= i)
+		ibaud = i - 1;
+	times = &i82527_baudrates[ibaud];
+
+	i = i82527_read_reg (dev, I82527_CPU_INT_REG) &
+	    ~(I82527_DSC | I82527_DMC);
+	i |= times->t_dsc * I82527_DSC;
+	i |= times->t_dmc * I82527_DMC;
+	i82527_write_reg (dev, I82527_CPU_INT_REG, i);
+
+	i = (times->t_clkout_div << I82527_CLKDIV_SHIFT)
+	    | (times->t_clkout_slew << I82527_SL_SHIFT);
+	i82527_write_reg (dev, I82527_CLKOUT_REG, i);
+
+	i = (times->t_sjw << I82527_SJW_SHIFT)
+	    | (times->t_brp << I82527_BRP_SHIFT);
+	i82527_write_reg (dev, I82527_BITT0_REG, i);
+
+	i = (times->t_spl << I82527_SPL_SHIFT)
+	    | (times->t_tseg1 << I82527_TSEG1_SHIFT)
+	    | (times->t_tseg2 << I82527_TSEG2_SHIFT);
+	i82527_write_reg (dev, I82527_BITT1_REG, i);
+
+}
+
+int i82527_init (struct can_dev *dev, unsigned int ibaud)
+{
+	int i;
+
+	i82527_write_reg (dev, I82527_CTRL_REG, I82527_CCE | I82527_INIT);
+
+	i82527_write_reg (dev, I82527_CLKOUT_REG, 3 << I82527_SL_SHIFT);
+	i82527_write_reg (dev, I82527_STAT_REG, 0x00);
+	i82527_write_reg (dev, I82527_P1CONF, 0x00);
+	i82527_write_reg (dev, I82527_P2CONF, 0x00);
+
+	i82527_write_15_mask (dev, 0x0);
+	i82527_write_std_mask (dev, 0xffff);
+	i82527_write_x_mask (dev, 0xffffffff);
+
+	/* Turn off all message objects and clear message identifiers */
+	for (i = I82527_FIRST_OBJ; i < I82527_MSG_OBJS; i++) {
+		i82527_write_msgctrl (dev, i,
+				      I82527_MSGVAL_R & I82527_INTPND_R &
+				      I82527_RMTPND_R & I82527_TXRQST_R &
+				      I82527_MSGLST_R & I82527_NEWDAT_R);
+		i82527_write_msgarb (dev, i, 0);
+	}
+
+	/* Configure Bus Configuration Register */
+	i82527_write_reg (dev, I82527_BUSCFG_REG,
+			  I82527_COBY | I82527_DCT1 | I82527_DCR1);
+
+	/*
+	 * Preconfigure CPU Interface Register. The XTAL of the CAN1
+	 * contoller is connected to CLKOUT of the CAN0 contoller.
+	 */
+	i82527_write_reg (dev, I82527_CPU_INT_REG,
+			  (dev) ? I82527_MUX : (I82527_MUX | I82527_CEN));
+
+	i82527_baudrate (dev, ibaud);
+
+	/* Inizialization end */
+	i82527_write_reg (dev, I82527_STAT_REG, I82527_STAT_REG_DEFAULT);
+
+	/* Start device */
+	i82527_write_reg (dev, I82527_CTRL_REG, 0);
+
+	return 0;
+}
+
+void i82527_config_xmit (struct can_dev *dev, struct can_msg *msg,
+			 int iobj, int xmit)
+{
+	int cfg;
+
+	/* it looks like message 15 fires an interrupt when re-enabled */
+	if (iobj != 15)
+		i82527_msgflag (dev, iobj, I82527_MSGVAL_R); /* being updated */
+
+	/* set DLC and X flag */
+	cfg = (msg->dlc << I82527_DLC_SHIFT);
+	msg->id <<= I82527_ID_STD_SHIFT;
+
+	i82527_write_msgarb (dev, iobj, msg->id);
+
+	if (xmit) {
+		if (msg->dlc > 8)
+			msg->dlc = 8;
+
+		cfg |= I82527_DIR_TX;
+
+		i82527_write_msgcfg (dev, iobj, cfg);
+		/* write data bytes */
+		i82527_write_msgdata (dev, iobj, msg->dlc, msg->data);
+
+		/* set MSGVAL; then clear CPUUpd and set newdat */
+		i82527_msgflag (dev, iobj, I82527_MSGVAL_S);
+
+		i82527_msgflag (dev, iobj, I82527_CPUUPD_R & I82527_NEWDAT_S &
+				I82527_TXRQST_S);
+	} else {
+		i82527_write_msgcfg (dev, iobj, cfg);
+		i82527_msgflag (dev, iobj, I82527_MSGVAL_S);
+		i82527_msgflag (dev, iobj, I82527_RMTPND_R & I82527_MSGLST_R &
+				I82527_NEWDAT_R);
+	}
+}
+
+int i82527_xmit (struct can_dev *dev, struct can_msg *msg)
+{
+	int i;
+
+	i82527_config_xmit (dev, msg, I82527_TX_OBJ, 1);
+
+	for (i = 0; i < CAN_XMIT_TIMEOUT_US; i += 10000) {
+		if (i82527_read_reg (dev, I82527_STAT_REG) & I82527_TXOK)
+			return 0;
+		if (ctrlc ())
+			break;
+		udelay (10000);
+	}
+
+	return -1;
+}
+
+int i82527_recv (struct can_dev *dev, struct can_msg *msg)
+{
+	int cfg, iobj = I82527_RX_OBJ;
+
+	/* Clear status registers (RXOK) */
+	i82527_write_reg (dev, I82527_STAT_REG, I82527_STAT_REG_DEFAULT);
+
+	msg->id = 0;
+	msg->dlc = 0;
+	i82527_config_xmit (dev, msg, iobj, 0);
+
+	while (!(i82527_read_reg (dev, I82527_STAT_REG) & I82527_RXOK)) {
+		if (ctrlc ())
+			return -1;
+	}
+
+	if (iobj != 15)
+		i82527_msgflag (dev, iobj, I82527_NEWDAT_R);
+
+	msg->id = i82527_read_msgarb (dev, iobj) >> I82527_ID_STD_SHIFT;
+
+	cfg = i82527_read_msgcfg (dev, iobj);
+
+	msg->dlc = (cfg & I82527_DLC_MASK) >> I82527_DLC_SHIFT;
+
+	i82527_read_msgdata (dev, iobj, msg->dlc, msg->data);
+
+	i82527_msgflag (dev, iobj, I82527_INTPND_R);
+	if (iobj == 15)
+		i82527_msgflag (dev, iobj, I82527_NEWDAT_R & I82527_RMTPND_R);
+
+	return 0;
+}
+
+int i82527_status (struct can_dev *dev, int level)
+{
+	printf ("i82527 at %#lx", dev->base);
+	if (level > 0) {
+		int stat = i82527_read_reg (dev, I82527_STAT_REG) & 0xff;
+		printf (", status 0x%02x", stat);
+		if (stat & I82527_BOFF)
+			puts (" busoff");
+		if (stat & I82527_WARN)
+			puts (" warning");
+		if (stat & I82527_WAKE)
+			puts (" wake");
+		if (stat & I82527_RXOK)
+			puts (" rxok");
+		if (stat & I82527_TXOK)
+			puts (" txok");
+		stat &= I82527_LEC_MASK;
+		if (stat > 0 && stat < 7)
+			printf (" lec=%d", stat);
+	}
+
+	puts ("\n");
+	if (level > 1) {
+		int i;
+		for (i = 0; i < I82527_SIZE; i++) {
+			if ((i % 0x10) == 0)
+				printf ("\n%02x:", i);
+			printf (" %02x", i82527_read_reg (dev, i));
+		}
+		puts ("\n");
+	}
+	return 0;
+}
+
+void i82527_register (struct can_dev *dev, unsigned long base)
+{
+	dev->name = "i82527";
+	dev->base = base;
+	dev->init = i82527_init;
+	dev->xmit = i82527_xmit;
+	dev->recv = i82527_recv;
+	dev->status = i82527_status;
+
+	can_register (dev);
+}
diff --git a/include/i82527.h b/include/i82527.h
new file mode 100644
index 0000000..8cd70e2
--- /dev/null
+++ b/include/i82527.h
@@ -0,0 +1,201 @@
+/*
+ * (C) Copyright 2007-2009, Wolfgang Grandegger <wg@denx.de>
+ *
+ * Derived from OCAN driver:
+ *
+ * Copyright (C) 2002 Alessandro Rubini <rubini@linux.it>
+ * Copyright (C) 2002 System SpA <info.electronics@system-group.it>
+ *
+ * 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 __I82527_H__
+#define __I82527_H__
+
+#include <can.h>
+
+#define I82527_MSG_OBJS	     16 /* 0 is the whole device, 1..15 are objects */
+#define I82527_FIRST_OBJ      1
+
+#define I82527_ID_STD_SHIFT  21
+#define I82527_ID_XTD_SHIFT   3
+
+/*
+ * i82527 address map (referred from base address) & internal bits.
+ * See the 82527 data-sheet page 9 and following
+*/
+#define I82527_MAP_SIZE   0x100
+
+#define I82527_CTRL_REG		0x00
+   #define I82527_CCE		   0x40
+   #define I82527_EIE		   0x08
+   #define I82527_SIE		   0x04
+   #define I82527_IE		   0x02
+   #define I82527_INIT		   0x01
+
+#define I82527_STAT_REG		0x01
+   #define I82527_BOFF		   0x80
+   #define I82527_WARN		   0x40
+   #define I82527_WAKE		   0x20
+   #define I82527_RXOK		   0x10
+   #define I82527_TXOK		   0x08
+   #define I82527_LEC_MASK	   0x07
+#define I82527_STAT_REG_DEFAULT    I82527_LEC_MASK
+
+#define I82527_CPU_INT_REG	0x02
+   #define I82527_RSTST		   0x80
+   #define I82527_DSC		   0x40
+   #define I82527_DMC		   0x20
+   #define I82527_PWD		   0x10
+   #define I82527_SLEEP		   0x08
+   #define I82527_MUX		   0x04
+   #define I82527_CEN		   0x01
+
+/* Reserved                     0x03 */
+
+#define I82527_HI_SPEED_RD	0x04
+#define I82527_GMASK_STD	0x06
+#define I82527_GMASK_XTD	0x08
+#define I82527_MSG15_MASK	0x0c
+
+/* Message 1			0x10 */
+#define I82527_MSG_OFF		0x10   /* No size definition here */
+   #define I82527_MSG_CTRL	   0x00
+      #define I82527_MSGVAL_R	  0xff7f   /* *********************** */
+      #define I82527_MSGVAL_S	  0xffbf   /* WARNING!!!              */
+      #define I82527_TXIE_R	  0xffdf   /* These masks must be     */
+      #define I82527_TXIE_S	  0xffef   /* &-ed and *NOT* |-ed     */
+      #define I82527_RXIE_R	  0xfff7   /*                         */
+      #define I82527_RXIE_S	  0xfffb   /*                         */
+      #define I82527_INTPND_R	  0xfffd   /*                         */
+      #define I82527_INTPND_S	  0xfffe   /*                         */
+      #define I82527_RMTPND_R	  0x7fff   /* WARNING!!!              */
+      #define I82527_RMTPND_S	  0xbfff   /* These masks must be     */
+      #define I82527_TXRQST_R	  0xdfff   /* &-ed and *NOT* |-ed     */
+      #define I82527_TXRQST_S	  0xefff   /*                         */
+      #define I82527_MSGLST_R	  0xf7ff   /*                         */
+      #define I82527_MSGLST_S	  0xfbff   /*                         */
+      #define I82527_CPUUPD_R	  0xf7ff   /* WARNING!!!              */
+      #define I82527_CPUUPD_S	  0xfbff   /* These masks must be     */
+      #define I82527_NEWDAT_R	  0xfdff   /* &-ed and *NOT* |-ed     */
+      #define I82527_NEWDAT_S	  0xfeff   /* *********************** */
+
+   #define I82527_MSG_ARBIT	0x02
+   #define I82527_MSG_CFG	0x06
+      #define I82527_DLC_MASK	   0xf0
+      #define I82527_DLC_SHIFT	   4
+      #define I82527_DLC_MASK0	   0x0f
+      #define I82527_DIR	   0x08
+         #define I82527_DIR_TX	      0x08
+         #define I82527_DIR_RX	      0x00
+      #define I82527_XTD	   0x04
+         #define I82527_XTD_XTD	      0x04
+         #define I82527_XTD_STD	      0x00
+   #define I82527_MSG_DATA	0x07   /* 8 bytes */
+#define I82527_CLKOUT_REG	0x1f
+   #define I82527_SL_MASK	   0x30
+   #define I82527_SL_SHIFT	   4
+   #define I82527_SL_MASK0	   0x03
+   #define I82527_CLKDIV_MASK	   0x0f
+   #define I82527_CLKDIV_SHIFT	   0
+   #define I82527_CLKDIV_MASK0	   0x0f
+
+/* Message 2			0x20 */
+#define I82527_BUSCFG_REG	0x2f
+   #define I82527_COBY		   0x40
+   #define I82527_POL		   0x20
+   #define I82527_DCT1		   0x08
+   #define I82527_DCR1		   0x02
+   #define I82527_DCR0		   0x01
+
+/* Message 3			0x30 */
+#define I82527_BITT0_REG	0x3f
+   #define I82527_SJW_MASK         0xc0
+   #define I82527_SJW_SHIFT        6
+   #define I82527_SJW_MASK0        0x03
+   #define I82527_BRP_MASK         0x3f
+   #define I82527_BRP_SHIFT        0
+   #define I82527_BRP_MASK0        0x3f
+
+/* Message 4			0x40 */
+#define I82527_BITT1_REG	0x4f
+   #define I82527_SPL_MASK         0x80
+   #define I82527_SPL_SHIFT        7
+   #define I82527_SPL_MASK0        0x01
+   #define I82527_TSEG2_MASK       0x70
+   #define I82527_TSEG2_SHIFT      4
+   #define I82527_TSEG2_MASK0      0x07
+   #define I82527_TSEG1_MASK       0x0f
+   #define I82527_TSEG1_SHIFT      0
+   #define I82527_TSEG1_MASK0      0x0f
+
+/* Message 5			0x50 */
+#define I82527_INT_REG		0x5f
+
+/* Message 6			0x60 */
+/* Reserved                     0x6f */
+
+/* Message 7			0x70 */
+/* Reserved                     0x7f */
+
+/* Message 8			0x80 */
+/* Reserved                     0x8f */
+
+/* Message 9			0x90 */
+#define I82527_P1CONF		0x9f
+
+/* Message 10			0xa0 */
+#define I82527_P2CONF		0xaf
+
+/* Message 11			0xb0 */
+#define I82527_P1IN		0xbf
+
+/* Message 12			0xc0 */
+#define I82527_P2IN		0xcf
+
+/* Message 13			0xd0 */
+#define I82527_P1OUT		0xdf
+
+/* Message 14			0xe0 */
+#define I82527_P2OUT		0xef
+
+/* Message 15			0xf0 */
+#define I82527_SER_RST_ADD	0xff
+
+
+#define I82527_SIZE		0x100
+
+/*
+ * Bit timing
+ */
+struct i82527_times {
+	u8  t_dsc;
+	u8  t_dmc;
+	u8  t_clkout_div;
+	u8  t_clkout_slew;
+	u8  t_sjw;
+	u8  t_spl;
+	u8  t_brp;
+	u8  t_tseg1;
+	u8  t_tseg2;
+};
+
+void i82527_register (struct can_dev *dev, unsigned long base);
+
+#endif /*__I82527_H__*/
-- 
1.6.2.5

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

* [U-Boot] [RFC 5/5] CAN interface support for the TQM855L module
  2009-11-01 11:33       ` [U-Boot] [RFC 4/5] CAN device driver for the Intel 82527 Wolfgang Grandegger
@ 2009-11-01 11:33         ` Wolfgang Grandegger
  0 siblings, 0 replies; 18+ messages in thread
From: Wolfgang Grandegger @ 2009-11-01 11:33 UTC (permalink / raw)
  To: u-boot

From: Wolfgang Grandegger <wg@denx.de>

Signed-off-by: Wolfgang Grandegger <wg@denx.de>
---
 board/tqc/tqm8xx/tqm8xx.c |   17 +++++++++++++++++
 include/configs/TQM855L.h |    8 +++++++-
 2 files changed, 24 insertions(+), 1 deletions(-)

diff --git a/board/tqc/tqm8xx/tqm8xx.c b/board/tqc/tqm8xx/tqm8xx.c
index f92c598..f1aab43 100644
--- a/board/tqc/tqm8xx/tqm8xx.c
+++ b/board/tqc/tqm8xx/tqm8xx.c
@@ -26,6 +26,10 @@
 #ifdef CONFIG_PS2MULT
 #include <ps2mult.h>
 #endif
+#ifdef	CONFIG_CAN
+#include <can.h>
+#include <i82527.h>
+#endif
 
 extern flash_info_t flash_info[];	/* FLASH chips info */
 
@@ -447,6 +451,19 @@ int board_early_init_r (void)
 
 #endif /* CONFIG_PS2MULT */
 
+#if defined(CONFIG_CAN_DRIVER) && defined(CONFIG_CAN)
+static struct can_dev tqm8xx_can[2];
+
+#ifdef CONFIG_BOARD_EARLY_INIT_R
+int board_early_init_r (void)
+{
+	i82527_register (&tqm8xx_can[0], CONFIG_SYS_CAN_BASE);
+	i82527_register( &tqm8xx_can[1], CONFIG_SYS_CAN_BASE + 0x100);
+
+	return (0);
+}
+#endif
+#endif
 
 #ifdef CONFIG_MISC_INIT_R
 extern void load_sernum_ethaddr(void);
diff --git a/include/configs/TQM855L.h b/include/configs/TQM855L.h
index 1255928..1603d30 100644
--- a/include/configs/TQM855L.h
+++ b/include/configs/TQM855L.h
@@ -88,7 +88,13 @@
 
 #define	CONFIG_STATUS_LED	1	/* Status LED enabled		*/
 
-#undef	CONFIG_CAN_DRIVER		/* CAN Driver support disabled	*/
+#define	CONFIG_CAN_DRIVER			/* CAN Driver support enabled	*/
+#ifdef CONFIG_CAN_DRIVER
+#define CONFIG_CAN
+#define CONFIG_CAN_I82527
+#define CONFIG_CMD_CAN
+#define CONFIG_BOARD_EARLY_INIT_R
+#endif
 
 /*
  * BOOTP options
-- 
1.6.2.5

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

* [U-Boot] [RFC 1/5] CAN interface library
  2009-11-01 11:33 ` [U-Boot] [RFC 1/5] CAN interface library Wolfgang Grandegger
  2009-11-01 11:33   ` [U-Boot] [RFC 2/5] CAN device test command Wolfgang Grandegger
@ 2009-11-01 14:36   ` Mike Frysinger
  2009-11-01 16:16     ` Wolfgang Grandegger
  1 sibling, 1 reply; 18+ messages in thread
From: Mike Frysinger @ 2009-11-01 14:36 UTC (permalink / raw)
  To: u-boot

On Sunday 01 November 2009 06:33:33 Wolfgang Grandegger wrote:
> --- 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

this isnt an issue specific to CAN, but i wonder if we should switch LIBS to 
LIBS-y now that the top level Makefile can rely on autoconf.mk settings after 
the point config.mk is included.  it would save time on pointlessly recursing 
into all the empty dirs and creating empty archives.

> --- /dev/null
> +++ b/drivers/can/Makefile
> @@ -0,0 +1,47 @@
> +include $(TOPDIR)/config.mk
> +
> +LIB 	:= $(obj)libcan.a
> +
> +COBJS-$(CONFIG_CAN)	+= can.o
> +
> +COBJS	:= $(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
> +
> +####################################################

also not specific to CAN, but i think it's time we start creating .mk files 
for subdirs to include

> --- /dev/null
> +++ b/drivers/can/can.c
>
> +static char *baudrates[] = { "125K", "250K", "500K" };

so we're restricting ourselves to these three speeds ?  i have passing 
familiarity with CAN, but i didnt think the protocol was restricted to 
specific speeds.

> +int can_register (struct can_dev* can_dev)

no space before the paren, and the * is cuddled on the wrong side of the 
space.  seems like a lot of this code suffers from these two issues.

> +{
> +	struct can_dev* dev;
> +
> +	can_dev->next = NULL;
> +	if (!can_devs)
> +		can_devs = can_dev;
> +	else {
> +		for (dev = can_devs; dev->next; dev = dev->next)
> +			    ;
> +		dev->next = can_dev;
> +	}

invert the if logic and i think the code would look "nicer" -- use braces on 
the first branch instead of the second.

> +struct can_dev *can_init (int dev_num, int ibaud)
> +{
> +	struct can_dev *dev;
> +	int i;
> +
> +	if (!can_devs) {
> +		puts ("No CAN devices registered\n");
> +		return NULL;
> +	}
> +
> +	/* Advance to selected device */
> +	for (i = 0, dev = can_devs; dev; i++, dev = dev->next) {
> +		if (i == dev_num)
> +			break;
> +	}
> +
> +	if (!dev) {
> +		printf ("CAN device %d does not exist\n", dev_num);
> +		return NULL;
> +	}
> +
> +	printf ("Initializing CAN%d at 0x%08x with baudrate %s\n",
> +		i, dev->base, baudrates[ibaud]);
> +
> +	dev->init (dev, ibaud);
> +
> +	return dev;
> +}

wonder if we should have a generic device list code base since this looks 
similar to a lot of other u-boot device lists ...

> --- /dev/null
> +++ b/include/can.h
> @@ -0,0 +1,70 @@
> +/*
> + * (C) Copyright 2007-2009, Wolfgang Grandegger <wg@denx.de>

have you really been working on this stuff since 2007 ?

> +struct can_dev {
> +	char *name;

const ?
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20091101/747d1ff9/attachment.pgp 

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

* [U-Boot] [RFC 2/5] CAN device test command
  2009-11-01 11:33   ` [U-Boot] [RFC 2/5] CAN device test command Wolfgang Grandegger
  2009-11-01 11:33     ` [U-Boot] [RFC 3/5] CAN device driver for the SJA1000 Wolfgang Grandegger
@ 2009-11-01 14:45     ` Mike Frysinger
  2009-11-01 16:24       ` Wolfgang Grandegger
  1 sibling, 1 reply; 18+ messages in thread
From: Mike Frysinger @ 2009-11-01 14:45 UTC (permalink / raw)
  To: u-boot

On Sunday 01 November 2009 06:33:34 Wolfgang Grandegger wrote:
> +	if (op == 's') {
> +	else if (op == 'i') {
> +	else if (op == 'r') {
> +	} else if (op == 'x') {
> +	} else {

your if style here is inconsistent, but ignoring that, shouldnt this really be 
a switch() ?  although, by only checking the first char, you allow people to 
encode typos into their commands and not realize it until some point in the 
future where things get stricter.  i.e. people can do `can ilovecandy ...`

> +		unsigned int dev_num = 0, ibaud = 0;
> +		struct can_dev *dev;
> +
> +		if (argc > 2)
> +			dev_num = simple_strtoul (argv[2], NULL, 10);
> +		if (argc > 3) {
> +			ibaud = simple_strtoul (argv[3], NULL, 10);
> +			if (ibaud > 2)
> +				ibaud = 2;
> +		}
> +		dev = can_init (dev_num, ibaud);
> +		if (!dev)
> +			return 1;
> +		can_dev = dev;

if i told CAN to init an unknown device, i would expect to get an error and 
the command state to remain in said error state until i selected a proper CAN 
device.  otherwise, a script that didnt check the can init status would 
incorrectly operate on the previously selected can device.

how do other commands work ?  am i complaining about common convention here ?

> +		printf ("Usage:\n%s\n", cmdtp->usage);

cmd_usage() ?

> +	can, 3,	1, do_can,
> +	"can - CAN bus commands\n",
> +	"can status [level]\n"
> +	"can init [dev] [baud-index]\n"
> +	"can xmit [id] [d0] [d1] ... [d7]\n"
> +	"can recv, abort with CTRL-C\n"

does the help really display correctly here ?  i think the "can status" line 
will have too many "can"'s ?
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20091101/7d9b8d17/attachment.pgp 

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

* [U-Boot] [RFC 1/5] CAN interface library
  2009-11-01 14:36   ` [U-Boot] [RFC 1/5] CAN interface library Mike Frysinger
@ 2009-11-01 16:16     ` Wolfgang Grandegger
  2009-11-01 18:05       ` Mike Frysinger
  0 siblings, 1 reply; 18+ messages in thread
From: Wolfgang Grandegger @ 2009-11-01 16:16 UTC (permalink / raw)
  To: u-boot

Mike Frysinger wrote:
> On Sunday 01 November 2009 06:33:33 Wolfgang Grandegger wrote:
[snip]
>> --- /dev/null
>> +++ b/drivers/can/can.c
>>
>> +static char *baudrates[] = { "125K", "250K", "500K" };
> 
> so we're restricting ourselves to these three speeds ?  i have passing 
> familiarity with CAN, but i didnt think the protocol was restricted to 
> specific speeds.

Well, this is an RFC and as I wrote in the introduction some features
need to be added or extended, especially for CAN device configuration.
My idea is to have a more complete default bit-timing table, which board
specific code may overwrite using, for example:

   sja1000_register(&my_sja1000, &my_config_opts);

This would also allow to set the CAN clock, cdr and ocr registers.

>> +int can_register (struct can_dev* can_dev)
> 
> no space before the paren, and the * is cuddled on the wrong side of the 
> space.  seems like a lot of this code suffers from these two issues.

U-Boot coding style requires a space after the function name and before
"(". But the "*" is misplaced, of course.

>> +{
>> +	struct can_dev* dev;
>> +
>> +	can_dev->next = NULL;
>> +	if (!can_devs)
>> +		can_devs = can_dev;
>> +	else {
>> +		for (dev = can_devs; dev->next; dev = dev->next)
>> +			    ;
>> +		dev->next = can_dev;
>> +	}
> 
> invert the if logic and i think the code would look "nicer" -- use braces on 
> the first branch instead of the second.

OK.

>> +struct can_dev *can_init (int dev_num, int ibaud)
>> +{
>> +	struct can_dev *dev;
>> +	int i;
>> +
>> +	if (!can_devs) {
>> +		puts ("No CAN devices registered\n");
>> +		return NULL;
>> +	}
>> +
>> +	/* Advance to selected device */
>> +	for (i = 0, dev = can_devs; dev; i++, dev = dev->next) {
>> +		if (i == dev_num)
>> +			break;
>> +	}
>> +
>> +	if (!dev) {
>> +		printf ("CAN device %d does not exist\n", dev_num);
>> +		return NULL;
>> +	}
>> +
>> +	printf ("Initializing CAN%d at 0x%08x with baudrate %s\n",
>> +		i, dev->base, baudrates[ibaud]);
>> +
>> +	dev->init (dev, ibaud);
>> +
>> +	return dev;
>> +}
> 
> wonder if we should have a generic device list code base since this looks 
> similar to a lot of other u-boot device lists ...

Do we already have a generic interface?

>> --- /dev/null
>> +++ b/include/can.h
>> @@ -0,0 +1,70 @@
>> +/*
>> + * (C) Copyright 2007-2009, Wolfgang Grandegger <wg@denx.de>
> 
> have you really been working on this stuff since 2007 ?

The code was written in 2007. "2007, 2009" is more appropriate.

>> +struct can_dev {
>> +	char *name;
> 
> const ?

OK.

Wolfgang.

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

* [U-Boot] [RFC 2/5] CAN device test command
  2009-11-01 14:45     ` [U-Boot] [RFC 2/5] CAN device test command Mike Frysinger
@ 2009-11-01 16:24       ` Wolfgang Grandegger
  2009-11-01 18:07         ` Mike Frysinger
  0 siblings, 1 reply; 18+ messages in thread
From: Wolfgang Grandegger @ 2009-11-01 16:24 UTC (permalink / raw)
  To: u-boot

Mike Frysinger wrote:
> On Sunday 01 November 2009 06:33:34 Wolfgang Grandegger wrote:
>> +	if (op == 's') {
>> +	else if (op == 'i') {
>> +	else if (op == 'r') {
>> +	} else if (op == 'x') {
>> +	} else {
> 
> your if style here is inconsistent, but ignoring that, shouldnt this really be 
> a switch() ?  although, by only checking the first char, you allow people to 
> encode typos into their commands and not realize it until some point in the 
> future where things get stricter.  i.e. people can do `can ilovecandy ...`

Will fix.

>> +		unsigned int dev_num = 0, ibaud = 0;
>> +		struct can_dev *dev;
>> +
>> +		if (argc > 2)
>> +			dev_num = simple_strtoul (argv[2], NULL, 10);
>> +		if (argc > 3) {
>> +			ibaud = simple_strtoul (argv[3], NULL, 10);
>> +			if (ibaud > 2)
>> +				ibaud = 2;
>> +		}
>> +		dev = can_init (dev_num, ibaud);
>> +		if (!dev)
>> +			return 1;
>> +		can_dev = dev;
> 
> if i told CAN to init an unknown device, i would expect to get an error and 
> the command state to remain in said error state until i selected a proper CAN 
> device.  otherwise, a script that didnt check the can init status would 
> incorrectly operate on the previously selected can device.

can_init will already print an error message. But that might be changed.

> how do other commands work ?  am i complaining about common convention here ?
> 
>> +		printf ("Usage:\n%s\n", cmdtp->usage);
> 
> cmd_usage() ?

OK.

>> +	can, 3,	1, do_can,
>> +	"can - CAN bus commands\n",
>> +	"can status [level]\n"
>> +	"can init [dev] [baud-index]\n"
>> +	"can xmit [id] [d0] [d1] ... [d7]\n"
>> +	"can recv, abort with CTRL-C\n"
> 
> does the help really display correctly here ?  i think the "can status" line 
> will have too many "can"'s ?

I think the output was OK. But I will check later next week.

Note that this is a RFC trying to discuss the real requirements of a CAN
interface in U-Boot. I think it would also be nice to have can_xmit()
and can_recv() with a timeout parameter, e.g.:

  can_xmit(struct can_dev *dev, int timeout_us);

And maybe also a can_xmit_done() function.

Wolfgang.

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

* [U-Boot] [RFC 1/5] CAN interface library
  2009-11-01 16:16     ` Wolfgang Grandegger
@ 2009-11-01 18:05       ` Mike Frysinger
  2009-11-01 22:00         ` Wolfgang Grandegger
  0 siblings, 1 reply; 18+ messages in thread
From: Mike Frysinger @ 2009-11-01 18:05 UTC (permalink / raw)
  To: u-boot

On Sunday 01 November 2009 11:16:59 Wolfgang Grandegger wrote:
> Mike Frysinger wrote:
> > On Sunday 01 November 2009 06:33:33 Wolfgang Grandegger wrote:
> >> --- /dev/null
> >> +++ b/drivers/can/can.c
> >>
> >> +static char *baudrates[] = { "125K", "250K", "500K" };
> >
> > so we're restricting ourselves to these three speeds ?  i have passing
> > familiarity with CAN, but i didnt think the protocol was restricted to
> > specific speeds.
> 
> Well, this is an RFC and as I wrote in the introduction some features
> need to be added or extended, especially for CAN device configuration.
> My idea is to have a more complete default bit-timing table, which board
> specific code may overwrite using, for example:
> 
>    sja1000_register(&my_sja1000, &my_config_opts);
> 
> This would also allow to set the CAN clock, cdr and ocr registers.

this makes sense if the device supports a limited number of baud rates.  but 
what if the baud rate is arbitrary (between two limits) ?

> >> +int can_register (struct can_dev* can_dev)
> >
> > no space before the paren, and the * is cuddled on the wrong side of the
> > space.  seems like a lot of this code suffers from these two issues.
> 
> U-Boot coding style requires a space after the function name and before
> "(". But the "*" is misplaced, of course.

it's (thankfully) been changing to Linux kernel style

> >> +struct can_dev *can_init (int dev_num, int ibaud)
> >
> > wonder if we should have a generic device list code base since this looks
> > similar to a lot of other u-boot device lists ...
> 
> Do we already have a generic interface?

i dont think so

> >> --- /dev/null
> >> +++ b/include/can.h
> >> @@ -0,0 +1,70 @@
> >> +/*
> >> + * (C) Copyright 2007-2009, Wolfgang Grandegger <wg@denx.de>
> >
> > have you really been working on this stuff since 2007 ?
> 
> The code was written in 2007. "2007, 2009" is more appropriate.

the intro made it sound like this was a recent development (i.e. last few 
days/weeks).  if code is actually from 2007, then the range is fine.
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20091101/6367ebef/attachment.pgp 

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

* [U-Boot] [RFC 2/5] CAN device test command
  2009-11-01 16:24       ` Wolfgang Grandegger
@ 2009-11-01 18:07         ` Mike Frysinger
  0 siblings, 0 replies; 18+ messages in thread
From: Mike Frysinger @ 2009-11-01 18:07 UTC (permalink / raw)
  To: u-boot

On Sunday 01 November 2009 11:24:59 Wolfgang Grandegger wrote:
> Note that this is a RFC trying to discuss the real requirements of a CAN
> interface in U-Boot. I think it would also be nice to have can_xmit()
> and can_recv() with a timeout parameter, e.g.:
> 
>   can_xmit(struct can_dev *dev, int timeout_us);
> 
> And maybe also a can_xmit_done() function.

i only have a passing familiarity with CAN (havent done real work with it), 
but i can find someone to look over the current stuff
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20091101/b78a8ed4/attachment.pgp 

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

* [U-Boot] [RFC 1/5] CAN interface library
  2009-11-01 18:05       ` Mike Frysinger
@ 2009-11-01 22:00         ` Wolfgang Grandegger
  0 siblings, 0 replies; 18+ messages in thread
From: Wolfgang Grandegger @ 2009-11-01 22:00 UTC (permalink / raw)
  To: u-boot

Mike Frysinger wrote:
> On Sunday 01 November 2009 11:16:59 Wolfgang Grandegger wrote:
>> Mike Frysinger wrote:
>>> On Sunday 01 November 2009 06:33:33 Wolfgang Grandegger wrote:
>>>> --- /dev/null
>>>> +++ b/drivers/can/can.c
>>>>
>>>> +static char *baudrates[] = { "125K", "250K", "500K" };
>>> so we're restricting ourselves to these three speeds ?  i have passing
>>> familiarity with CAN, but i didnt think the protocol was restricted to
>>> specific speeds.
>> Well, this is an RFC and as I wrote in the introduction some features
>> need to be added or extended, especially for CAN device configuration.
>> My idea is to have a more complete default bit-timing table, which board
>> specific code may overwrite using, for example:
>>
>>    sja1000_register(&my_sja1000, &my_config_opts);
>>
>> This would also allow to set the CAN clock, cdr and ocr registers.
> 
> this makes sense if the device supports a limited number of baud rates.  but 
> what if the baud rate is arbitrary (between two limits) ?

Board specific code can define what ever table it likes, including
non-standard bit-rate and bit-timings. Nevertheless, for most CAN
controllers the default bit-timing parameters are just fine.

>>>> +int can_register (struct can_dev* can_dev)
>>> no space before the paren, and the * is cuddled on the wrong side of the
>>> space.  seems like a lot of this code suffers from these two issues.
>> U-Boot coding style requires a space after the function name and before
>> "(". But the "*" is misplaced, of course.
> 
> it's (thankfully) been changing to Linux kernel style

I really appreciate that.

>>>> +struct can_dev *can_init (int dev_num, int ibaud)
>>> wonder if we should have a generic device list code base since this looks
>>> similar to a lot of other u-boot device lists ...
>> Do we already have a generic interface?
> 
> i dont think so

Nor do I.

Wolfgang.

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

* [U-Boot] [RFC 3/5] CAN device driver for the SJA1000
  2009-11-01 11:33     ` [U-Boot] [RFC 3/5] CAN device driver for the SJA1000 Wolfgang Grandegger
  2009-11-01 11:33       ` [U-Boot] [RFC 4/5] CAN device driver for the Intel 82527 Wolfgang Grandegger
@ 2009-11-02 12:02       ` Matthias Fuchs
  2009-11-02 12:50         ` Wolfgang Grandegger
  1 sibling, 1 reply; 18+ messages in thread
From: Matthias Fuchs @ 2009-11-02 12:02 UTC (permalink / raw)
  To: u-boot

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__ */
> +

-- 
-------------------------------------------------------------------------
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
-------------------------------------------------------------------------

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

* [U-Boot] [RFC 3/5] CAN device driver for the SJA1000
  2009-11-02 12:02       ` [U-Boot] [RFC 3/5] CAN device driver for the SJA1000 Matthias Fuchs
@ 2009-11-02 12:50         ` Wolfgang Grandegger
  2009-11-02 14:22           ` Matthias Fuchs
  0 siblings, 1 reply; 18+ messages in thread
From: Wolfgang Grandegger @ 2009-11-02 12:50 UTC (permalink / raw)
  To: u-boot

Matthias Fuchs wrote:
> 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 :-(

Then it should be changed, of course. This patch is far from being
accepted and for the moment it's an implementation detail. I'm
especially interested to hear if such a generic CAN interface would
serve your purposes as well, as you require access to the SJA1000 somehow.

Wolfgang.

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

* [U-Boot] [RFC 3/5] CAN device driver for the SJA1000
  2009-11-02 12:50         ` Wolfgang Grandegger
@ 2009-11-02 14:22           ` Matthias Fuchs
  2009-11-02 20:20             ` Wolfgang Grandegger
  0 siblings, 1 reply; 18+ messages in thread
From: Matthias Fuchs @ 2009-11-02 14:22 UTC (permalink / raw)
  To: u-boot

Hi Wolfgang,

of course I can think of situations where some simple CAN mechanism
might be helpful (e.g. simple hardware testing). 

But do we really need this inside a bootloader? Surely not
for a production build. But please keep on hacking!

On Monday 02 November 2009 13:50, Wolfgang Grandegger wrote:
> Matthias Fuchs wrote:
> > 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 :-(
> 
> Then it should be changed, of course. This patch is far from being
> accepted and for the moment it's an implementation detail. I'm
> especially interested to hear if such a generic CAN interface would
> serve your purposes as well, as you require access to the SJA1000 somehow.

I just need to bit bang around in the OCR register. So no need for a full blown
and flash consuming CAN implementation. Of course I could life with your
register access style. Especially because it makes the code more common with
Socket-CAN files which prevents us from rewriting fully functional code ;-)

Matthias

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

* [U-Boot] [RFC 3/5] CAN device driver for the SJA1000
  2009-11-02 14:22           ` Matthias Fuchs
@ 2009-11-02 20:20             ` Wolfgang Grandegger
  2009-11-05 20:28               ` Wolfgang Denk
  0 siblings, 1 reply; 18+ messages in thread
From: Wolfgang Grandegger @ 2009-11-02 20:20 UTC (permalink / raw)
  To: u-boot

Matthias Fuchs wrote:
> Hi Wolfgang,
> 
> of course I can think of situations where some simple CAN mechanism
> might be helpful (e.g. simple hardware testing). 
> 
> But do we really need this inside a bootloader? Surely not
> for a production build. But please keep on hacking!
> 
> On Monday 02 November 2009 13:50, Wolfgang Grandegger wrote:
>> Matthias Fuchs wrote:
>>> 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 :-(
>> Then it should be changed, of course. This patch is far from being
>> accepted and for the moment it's an implementation detail. I'm
>> especially interested to hear if such a generic CAN interface would
>> serve your purposes as well, as you require access to the SJA1000 somehow.
> 
> I just need to bit bang around in the OCR register. So no need for a full blown
> and flash consuming CAN implementation. Of course I could life with your
> register access style. Especially because it makes the code more common with
> Socket-CAN files which prevents us from rewriting fully functional code ;-)

Well, I think Wolfgang will tell me to use structs sooner than later.

Wolfgang.

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

* [U-Boot] [RFC 3/5] CAN device driver for the SJA1000
  2009-11-02 20:20             ` Wolfgang Grandegger
@ 2009-11-05 20:28               ` Wolfgang Denk
  0 siblings, 0 replies; 18+ messages in thread
From: Wolfgang Denk @ 2009-11-05 20:28 UTC (permalink / raw)
  To: u-boot

Dear Wolfgang Grandegger,

In message <4AEF3F18.6000103@grandegger.com> you wrote:
>
> Well, I think Wolfgang will tell me to use structs sooner than later.

Why should I? You already know it!

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"There is no statute of limitations on stupidity."
- Randomly produced by a computer program called Markov3.

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

end of thread, other threads:[~2009-11-05 20:28 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-11-01 11:33 [U-Boot] [RFC 0/5] CAN framework for U-Boot Wolfgang Grandegger
2009-11-01 11:33 ` [U-Boot] [RFC 1/5] CAN interface library Wolfgang Grandegger
2009-11-01 11:33   ` [U-Boot] [RFC 2/5] CAN device test command Wolfgang Grandegger
2009-11-01 11:33     ` [U-Boot] [RFC 3/5] CAN device driver for the SJA1000 Wolfgang Grandegger
2009-11-01 11:33       ` [U-Boot] [RFC 4/5] CAN device driver for the Intel 82527 Wolfgang Grandegger
2009-11-01 11:33         ` [U-Boot] [RFC 5/5] CAN interface support for the TQM855L module Wolfgang Grandegger
2009-11-02 12:02       ` [U-Boot] [RFC 3/5] CAN device driver for the SJA1000 Matthias Fuchs
2009-11-02 12:50         ` Wolfgang Grandegger
2009-11-02 14:22           ` Matthias Fuchs
2009-11-02 20:20             ` Wolfgang Grandegger
2009-11-05 20:28               ` Wolfgang Denk
2009-11-01 14:45     ` [U-Boot] [RFC 2/5] CAN device test command Mike Frysinger
2009-11-01 16:24       ` Wolfgang Grandegger
2009-11-01 18:07         ` Mike Frysinger
2009-11-01 14:36   ` [U-Boot] [RFC 1/5] CAN interface library Mike Frysinger
2009-11-01 16:16     ` Wolfgang Grandegger
2009-11-01 18:05       ` Mike Frysinger
2009-11-01 22:00         ` Wolfgang Grandegger

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.