* [U-Boot] [PATCH] add u-boot sja1000/can support
@ 2009-10-24 4:17 miaofng
2009-10-24 6:35 ` Mike Frysinger
` (4 more replies)
0 siblings, 5 replies; 15+ messages in thread
From: miaofng @ 2009-10-24 4:17 UTC (permalink / raw)
To: u-boot
^ permalink raw reply [flat|nested] 15+ messages in thread
* [U-Boot] [PATCH] add u-boot sja1000/can support
2009-10-24 4:17 [U-Boot] [PATCH] add u-boot sja1000/can support miaofng
@ 2009-10-24 6:35 ` Mike Frysinger
[not found] ` <200910261248270312273@gmail.com>
` (3 subsequent siblings)
4 siblings, 0 replies; 15+ messages in thread
From: Mike Frysinger @ 2009-10-24 6:35 UTC (permalink / raw)
To: u-boot
On Saturday 24 October 2009 00:17:50 miaofng wrote:
> From 1f6aaba856fbf484c442eb33cf220774d57fba8d Mon Sep 17 00:00:00 2001
> From: miaofng <miaofng@gmail.com>
> Date: Fri, 23 Oct 2009 17:06:50 +0800
> Subject: [PATCH] [can] add u-boot sja1000/can support
this should be split into two patches -- one for the core CAN code and one for
the sja1000-specific implementation.
it's also lacking documentation updates to the top level README or perhaps a
standalone doc/README.can file
unconditionally calling can_init() is broken (in lib_arm/board.c). can is
like any other driver and can be enabled/disabled. it needs a dedicated
CONFIG_CAN option which would be leveraged in drviers/can/Makefile to add
can_core.c to the build.
> --- /dev/null
> +++ b/drivers/can/can_core.c
> +#define can_debug printf
> +#define can_error printf
uhh, what ? we already have debug() macros. dont go creating your own brand
new stuff.
> +#ifdef CONFIG_CMD_CAN
CONFIG_CMD_xxx is reserved for actual commands as in U_BOOT_CMD. you arent
implementing that, so this is wrong. besides, it isnt needed once you use a
proper CONFIG_CAN and add it to the top level Makefile.
> +void canif_rx(struct can_frame *cf, struct can_device *dev)
> +{
> + int len;
> +
> + //error frame?
C++ style comments are not allowed. use normal C /* comments */.
> + if(cf->can_id&CAN_ERR_FLAG)
> + {
you need to read the style documentation. u-boot code follows the linux
kernel. that means this should have been:
if (cf->can_id & CAN_ERR_FLAG) {
all of your code is horribly broken in these regards
> +int can_init(void)
> +{
> +#ifdef CONFIG_CMD_CAN
> + int index;
> + for(index = 0; index < CONFIG_CAN_DEV_MAX; index ++) can_devs[index] = 0;
use memset() like god intended. then again, can_devs is declared static and
in the .bss, so this init step is unnecessary.
> + board_can_init();
> +#endif
> + return 0;
> +}
these need to be weak's like all the other subsystems do it. look at
net/eth.c and how it does it:
- can_initialize()
- weak board_can_init()
- weak cpu_can_init()
> +int register_candev(struct can_device *dev)
use "can" or "candev", dont mix the two
> --- /dev/null
> +++ b/drivers/can/sja1000.c
> +//MODULE_AUTHOR("Oliver Hartkopp <oliver.hartkopp@volkswagen.de>");
> +//MODULE_LICENSE("Dual BSD/GPL");
> +//MODULE_DESCRIPTION(DRV_NAME "CAN netdevice driver");
dont leave crap behind -- delete it
> +int sja1000_interrupt(struct can_device *dev)
u-boot is a polled architecture, not an interrupt based one. i guess this
driver needs rewriting to do that.
> +int register_sja1000dev(struct can_device *dev)
can drivers should have a standard naming convention. perhaps something like:
can_<driver>_register()
> +void unregister_sja1000dev(struct can_device *dev)
> +{
> + set_reset_mode(dev);
> + unregister_candev(dev);
> +}
do we really need an unregister framework ? none of the other subsystems do
and it hasnt been a problem.
> --- /dev/null
> +++ b/include/candev.h
> @@ -0,0 +1,46 @@
> +/*
> + * (C) Copyright 2009 miaofng<miaofng@gmail.com>
> + *
> + *
> + * See file CREDITS for list of people who contributed to this
> + * project.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +
> +/*
> + * netdev.h - definitions an prototypes for network devices
> + */
> +
> +#ifndef _CANDEV_H_
> +#define _CANDEV_H_
clearly you've been copying & pasting code from the Linux kernel, yet you've
been stripping out people's copyrights. that wont fly.
-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/20091024/a0aa315c/attachment.pgp
^ permalink raw reply [flat|nested] 15+ messages in thread
* [U-Boot] [PATCH] add u-boot sja1000/can support
@ 2009-10-26 5:39 miaofng
0 siblings, 0 replies; 15+ messages in thread
From: miaofng @ 2009-10-26 5:39 UTC (permalink / raw)
To: u-boot
Hi Mike,
Thanks for your careful review. I'll resend the patch according to your remarks except below:
1)
> +int register_candev(struct can_device *dev)
use "can" or "candev", dont mix the two
answer: register_candev is origin from register_netdev(...). CAN is something like network, it may has high level
protocols such as open-can and etc, so i want to keep that story.
2)
> +int sja1000_interrupt(struct can_device *dev)
u-boot is a polled architecture, not an interrupt based one. i guess this
driver needs rewriting to do that.
answer: no, i want to keep that structure. Then linux drivers can be ported to u-boot easily.
take an example, in sja1000, i only need to replace "_net" to "_can" at most of time. To gain this convience,
i added the wrap layer of can_core.c. In order to work in u-boot polled mode, people only need to call sja1000_interrupt periodly.
It works fine on my board.
On Saturday 24 October 2009 00:17:50 miaofng wrote:
> From 1f6aaba856fbf484c442eb33cf220774d57fba8d Mon Sep 17 00:00:00 2001
> From: miaofng <miaofng@gmail.com>
> Date: Fri, 23 Oct 2009 17:06:50 +0800
> Subject: [PATCH] [can] add u-boot sja1000/can support
this should be split into two patches -- one for the core CAN code and one for
the sja1000-specific implementation.
it's also lacking documentation updates to the top level README or perhaps a
standalone doc/README.can file
unconditionally calling can_init() is broken (in lib_arm/board.c). can is
like any other driver and can be enabled/disabled. it needs a dedicated
CONFIG_CAN option which would be leveraged in drviers/can/Makefile to add
can_core.c to the build.
> --- /dev/null
> +++ b/drivers/can/can_core.c
> +#define can_debug printf
> +#define can_error printf
uhh, what ? we already have debug() macros. dont go creating your own brand
new stuff.
> +#ifdef CONFIG_CMD_CAN
CONFIG_CMD_xxx is reserved for actual commands as in U_BOOT_CMD. you arent
implementing that, so this is wrong. besides, it isnt needed once you use a
proper CONFIG_CAN and add it to the top level Makefile.
> +void canif_rx(struct can_frame *cf, struct can_device *dev)
> +{
> + int len;
> +
> + //error frame?
C++ style comments are not allowed. use normal C /* comments */.
> + if(cf->can_id&CAN_ERR_FLAG)
> + {
you need to read the style documentation. u-boot code follows the linux
kernel. that means this should have been:
if (cf->can_id & CAN_ERR_FLAG) {
all of your code is horribly broken in these regards
> +int can_init(void)
> +{
> +#ifdef CONFIG_CMD_CAN
> + int index;
> + for(index = 0; index < CONFIG_CAN_DEV_MAX; index ++) can_devs[index] = 0;
use memset() like god intended. then again, can_devs is declared static and
in the .bss, so this init step is unnecessary.
> + board_can_init();
> +#endif
> + return 0;
> +}
these need to be weak's like all the other subsystems do it. look at
net/eth.c and how it does it:
- can_initialize()
- weak board_can_init()
- weak cpu_can_init()
> +int register_candev(struct can_device *dev)
use "can" or "candev", dont mix the two
> --- /dev/null
> +++ b/drivers/can/sja1000.c
> +//MODULE_AUTHOR("Oliver Hartkopp <oliver.hartkopp@volkswagen.de>");
> +//MODULE_LICENSE("Dual BSD/GPL");
> +//MODULE_DESCRIPTION(DRV_NAME "CAN netdevice driver");
dont leave crap behind -- delete it
> +int sja1000_interrupt(struct can_device *dev)
u-boot is a polled architecture, not an interrupt based one. i guess this
driver needs rewriting to do that.
> +int register_sja1000dev(struct can_device *dev)
can drivers should have a standard naming convention. perhaps something like:
can_<driver>_register()
> +void unregister_sja1000dev(struct can_device *dev)
> +{
> + set_reset_mode(dev);
> + unregister_candev(dev);
> +}
do we really need an unregister framework ? none of the other subsystems do
and it hasnt been a problem.
> --- /dev/null
> +++ b/include/candev.h
> @@ -0,0 +1,46 @@
> +/*
> + * (C) Copyright 2009 miaofng<miaofng@gmail.com>
> + *
> + *
> + * See file CREDITS for list of people who contributed to this
> + * project.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +
> +/*
> + * netdev.h - definitions an prototypes for network devices
> + */
> +
> +#ifndef _CANDEV_H_
> +#define _CANDEV_H_
clearly you've been copying & pasting code from the Linux kernel, yet you've
been stripping out people's copyrights. that wont fly.
-mike
^ permalink raw reply [flat|nested] 15+ messages in thread
* [U-Boot] [PATCH] add u-boot sja1000/can support
[not found] ` <200910261248270312273@gmail.com>
@ 2009-10-26 7:02 ` Mike Frysinger
[not found] ` <200910261629132341038@gmail.com>
1 sibling, 0 replies; 15+ messages in thread
From: Mike Frysinger @ 2009-10-26 7:02 UTC (permalink / raw)
To: u-boot
On Monday 26 October 2009 00:48:39 miaofng wrote:
> Thanks for careful review. I'll resend the patch according to your remarks
> except follwing: 1)
>
> > +int register_candev(struct can_device *dev)
>
> use "can" or "candev", dont mix the two
>
> answer: register_candev is origin from register_netdev(...). CAN is
> something like network, it may has high level protocols such as open-can
> and etc, so i want to keep that story.
i know what CAN is. the Linux approach makes sense because they've
architected CAN at the socket() layer, and all of the network layers are
written with common coding style. but there is no such socket/network layer
in u-boot so the can/candev distinction isnt necessary.
> > +int sja1000_interrupt(struct can_device *dev)
>
> u-boot is a polled architecture, not an interrupt based one. i guess this
> driver needs rewriting to do that.
>
> answer: no, i want to keep that structure. Then linux drivers can be ported
> to u-boot easily. take an example, in sja1000, i only need to replace
> "_net" to "_can" at most of time. To gain this convience, i added the wrap
> layer of can_core.c.
the convenience factor doesnt mean you can ignore u-boot design principles.
the default behavior for all frameworks/drivers is a polled mode because it's
simple and straightforward. not all u-boot ports even support interrupts
> In order to work in u-boot polled mode, people only
> need to call sja1000_interrupt periodly. It works fine on my board.
erm, no, that's not how things work in u-boot. u-boot processes commands
given to it (either via scripts or from user input), and each command does not
return until it is completely done processing. there is no "backgrounding" of
drivers -- u-boot is not an OS and it is not threaded. that means any CAN
operation does not return until it has finished sending/receiving everything
it was told to.
-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/20091026/bb00e688/attachment.pgp
^ permalink raw reply [flat|nested] 15+ messages in thread
* [U-Boot] [PATCH] add u-boot sja1000/can support
2009-10-24 4:17 [U-Boot] [PATCH] add u-boot sja1000/can support miaofng
2009-10-24 6:35 ` Mike Frysinger
[not found] ` <200910261248270312273@gmail.com>
@ 2009-10-26 8:18 ` Matthias Fuchs
2009-10-26 12:14 ` Wolfgang Grandegger
2009-10-26 21:56 ` Wolfgang Denk
4 siblings, 0 replies; 15+ messages in thread
From: Matthias Fuchs @ 2009-10-26 8:18 UTC (permalink / raw)
To: u-boot
Do we have boards that use this code?
Matthias
On Saturday 24 October 2009 06:17, miaofng wrote:
> >From 1f6aaba856fbf484c442eb33cf220774d57fba8d Mon Sep 17 00:00:00 2001
> From: miaofng <miaofng@gmail.com>
> Date: Fri, 23 Oct 2009 17:06:50 +0800
> Subject: [PATCH] [can] add u-boot sja1000/can support
>
> Signed-off-by: miaofng <miaofng@gmail.com>
> ---
> Makefile | 1 +
> drivers/can/Makefile | 46 ++++
> drivers/can/can_core.c | 266 ++++++++++++++++++++++
> drivers/can/sja1000.c | 584 ++++++++++++++++++++++++++++++++++++++++++++++++
> drivers/can/sja1000.h | 160 +++++++++++++
> include/can.h | 216 ++++++++++++++++++
> include/can_error.h | 93 ++++++++
> include/candev.h | 46 ++++
> lib_arm/board.c | 2 +
> 9 files changed, 1414 insertions(+), 0 deletions(-)
> create mode 100755 drivers/can/Makefile
> create mode 100755 drivers/can/can_core.c
> create mode 100755 drivers/can/sja1000.c
> create mode 100755 drivers/can/sja1000.h
> create mode 100755 include/can.h
> create mode 100755 include/can_error.h
> create mode 100755 include/candev.h
> mode change 100644 => 100755 lib_arm/board.c
>
> diff --git a/Makefile b/Makefile
> index d6d6368..1ba59f8 100755
> --- a/Makefile
> +++ b/Makefile
> @@ -203,6 +203,7 @@ LIBS += net/libnet.a
> LIBS += disk/libdisk.a
> LIBS += drivers/bios_emulator/libatibiosemu.a
> LIBS += drivers/block/libblock.a
> +LIBS += drivers/can/libcan.a
> LIBS += drivers/dma/libdma.a
> LIBS += drivers/fpga/libfpga.a
> LIBS += drivers/gpio/libgpio.a
> diff --git a/drivers/can/Makefile b/drivers/can/Makefile
> new file mode 100755
> index 0000000..d3d47bb
> --- /dev/null
> +++ b/drivers/can/Makefile
> @@ -0,0 +1,46 @@
> +#
> +# Copyright (C) 2009 miaofng<miaofng@126.com>
> +#
> +# See file CREDITS for list of people who contributed to this
> +# project.
> +#
> +# This program is free software; you can redistribute it and/or
> +# modify it under the terms of the GNU General Public License as
> +# published by the Free Software Foundation; either version 2 of
> +# the License, or (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program; if not, write to the Free Software
> +# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> +# MA 02111-1307 USA
> +#
> +
> +include $(TOPDIR)/config.mk
> +
> +LIB := $(obj)libcan.a
> +
> +COBJS-y += can_core.o
> +COBJS-$(CONFIG_DRIVER_SJA1000) += sja1000.o
> +
> +COBJS := $(sort $(COBJS-y))
> +SRCS := $(COBJS:.o=.c)
> +OBJS := $(addprefix $(obj),$(COBJS))
> +
> +all: $(LIB)
> +
> +$(LIB): $(obj).depend $(OBJS)
> + $(AR) $(ARFLAGS) $@ $(OBJS)
> +
> +#########################################################################
> +
> +# defines $(obj).depend target
> +include $(SRCTREE)/rules.mk
> +
> +sinclude $(obj).depend
> +
> +#########################################################################
> diff --git a/drivers/can/can_core.c b/drivers/can/can_core.c
> new file mode 100755
> index 0000000..a723e8a
> --- /dev/null
> +++ b/drivers/can/can_core.c
> @@ -0,0 +1,266 @@
> +/*
> + * Copyright (C) 2009 miaofng<miaofng@gmail.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the version 2 of the GNU General Public License
> + * as published by the Free Software Foundation
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> + */
> +
> +#include <common.h>
> +#include <can.h>
> +#include <malloc.h>
> +
> +#define can_debug printf
> +#define can_error printf
> +
> +#ifdef CONFIG_CMD_CAN
> +#ifndef CONFIG_CAN_DEV_MAX
> +#define CONFIG_CAN_DEV_MAX 8
> +#endif
> +
> +static struct can_device *can_devs[CONFIG_CAN_DEV_MAX];
> +#endif
> +
> +static inline struct can_device* index_to_cdev(int index)
> +{
> + return (index<CONFIG_CAN_DEV_MAX)? can_devs[index]:0;
> +}
> +
> +static inline int cdev_to_index(struct can_device *dev)
> +{
> + return (dev)?dev->index:-1;
> +}
> +
> +static void canif_tx(struct can_device *dev)
> +{
> + struct can_frame *cf;
> + int len;
> +
> + len = buf_pop(&dev->tbuf, (char*)&cf, sizeof(cf));
> + if(len == sizeof(cf)) {
> + dev->start_xmit(cf, dev);
> + free(cf);
> + }
> +}
> +
> +void canif_rx(struct can_frame *cf, struct can_device *dev)
> +{
> + int len;
> +
> + //error frame?
> + if(cf->can_id&CAN_ERR_FLAG)
> + {
> + //error frame, drop it
> + free(cf);
> + return;
> + }
> +
> + //soft id filter?
> +
> + //store to cirbuf
> + if(dev->rbuf.size == dev->rbuf.totalsize) {
> + can_debug("CAN: rx buffer is full\n");
> + dev->stats.rx_dropped ++;
> + free(cf);
> + return;
> + }
> +
> + buf_push(&dev->rbuf, (char*)&cf, sizeof(cf));
> +}
> +
> +void canif_wake_queue(struct can_device *dev)
> +{
> + canif_start_queue(dev);
> + canif_tx(dev);
> +}
> +
> +int can_init(void)
> +{
> +#ifdef CONFIG_CMD_CAN
> + int index;
> + for(index = 0; index < CONFIG_CAN_DEV_MAX; index ++) can_devs[index] = 0;
> + board_can_init();
> +#endif
> + return 0;
> +}
> +
> +/*
> + * Register the CAN network device
> + */
> + #ifndef CONFIG_CAN_BUF_TX_SZ
> + #define CONFIG_CAN_BUF_TX_SZ (8*sizeof(void*))
> + #endif
> +
> + #ifndef CONFIG_CAN_BUF_RX_SZ
> + #define CONFIG_CAN_BUF_RX_SZ (8*sizeof(void*))
> + #endif
> +
> +int register_candev(struct can_device *dev)
> +{
> + int ret;
> + int index;
> +
> + //insert into the list
> + dev->index = -1;
> + for(index =0; index < CONFIG_CAN_DEV_MAX; index ++)
> + {
> + if(!can_devs[index]) {
> + can_devs[index] = dev;
> + dev->index = index;
> + break;
> + }
> + }
> + if( dev->index < 0)
> + can_debug("CAN: too many can devices\n");
> +
> + //allocate circbuf for tx and rx
> + ret = buf_init(&dev->tbuf, CONFIG_CAN_BUF_TX_SZ);
> + if(ret != 1) {
> + can_debug("CAN: cann't init cirbuf of tx\n");
> + can_devs[index] = 0;
> + return -1;
> + }
> + ret = buf_init(&dev->rbuf, CONFIG_CAN_BUF_RX_SZ);
> + if(ret != 1) {
> + can_debug("CAN: cann't init cirbuf of rx\n");
> + can_devs[index] = 0;
> + buf_free(&dev->tbuf);
> + return -1;
> + }
> + dev->qstatus = CAN_QUEUE_INIT;
> +
> + //success
> + printf("CAN: %s @index %d\n", dev->name, dev->index);
> + return 0;
> +}
> +
> +/*
> + * Unregister the CAN network device
> + */
> +void unregister_candev(struct can_device *dev)
> +{
> + int index = cdev_to_index(dev);
> +
> + if(index < 0) {
> + can_debug("CAN: invalid para\n");
> + return;
> + }
> +
> + //close the dev first
> + can_close((int)dev);
> +
> + //release tx/rx buffer
> + buf_free(&dev->tbuf);
> + buf_free(&dev->rbuf);
> +
> + //remove from the list
> + can_devs[index] = 0;
> +}
> +
> +//api
> +int can_setbrg(int brg, int index)
> +{
> + struct can_device *dev = index_to_cdev(index);
> +
> + if(!dev) {
> + can_debug("CAN: invalid para\n");
> + return -1;
> + }
> +
> + if( dev->state != CAN_STATE_STOPPED) {
> + can_debug("CAN: invalid dev status<%d>\n", dev->state);
> + return -1;
> + }
> +
> + if(dev->setbrg)
> + return dev->setbrg(brg, dev);
> +
> + can_debug("CAN: op not supported by the dev\n");
> + return -1;
> +}
> +
> +int can_open(int index)
> +{
> + struct can_device *dev = index_to_cdev(index);
> +
> + if(!dev) {
> + can_debug("CAN: invalid para\n");
> + return 0;
> + }
> +
> + if(dev->state != CAN_STATE_STOPPED) {
> + can_debug("CAN: invalid dev status<%d>\n", dev->state);
> + return 0;
> + }
> +
> + if(dev && dev->open) dev->open(dev);
> + return (int)dev;
> +}
> +
> +void can_close(int dev_id)
> +{
> + struct can_device *dev = (struct can_device*) dev_id;
> + struct can_frame *cf;
> +
> + if(!dev) {
> + can_debug("CAN: invalid para\n");
> + return;
> + }
> +
> + //can device close
> + if(dev->close) dev->close(dev);
> +
> + //tbuf,rbuf dump
> + while(buf_pop(&dev->tbuf, (char*)&cf, sizeof(cf)) ) free(cf);
> + while(buf_pop(&dev->rbuf, (char*)&cf, sizeof(cf)) ) free(cf);
> +}
> +
> +//non block write
> +int can_send(struct can_frame *cf, int dev_id)
> +{
> + struct can_device *dev = (struct can_device*) dev_id;
> +
> + if(!cf || !dev ) {
> + can_debug("CAN: invalid para\n");
> + return -1;
> + }
> +
> + if(dev->tbuf.size == dev->tbuf.totalsize){ //tbuf overflow
> + can_debug("CAN: tx buffer is full\n");
> + return -1;
> + }
> +
> + buf_push(&dev->tbuf, (char*)&cf, sizeof(cf));
> +
> + //start queue?
> + if( dev->qstatus == CAN_QUEUE_READY )
> + canif_tx(dev);
> +
> + return 0;
> +}
> +
> +//non block read
> +struct can_frame* can_recv(int dev_id)
> +{
> + struct can_device *dev = (struct can_device*) dev_id;
> + struct can_frame *cf;
> + int len;
> +
> + if(!dev ) {
> + can_debug("CAN: invalid para\n");
> + return 0;
> + }
> +
> + len = buf_pop(&dev->rbuf, (char*)&cf, sizeof(cf));
> + if(len != sizeof(cf)) return (struct can_frame*)0;
> + else return cf;
> +}
> diff --git a/drivers/can/sja1000.c b/drivers/can/sja1000.c
> new file mode 100755
> index 0000000..07560bd
> --- /dev/null
> +++ b/drivers/can/sja1000.c
> @@ -0,0 +1,584 @@
> +/*
> + * sja1000.c - Philips SJA1000 network device driver
> + *
> + * Copyright (c) 2009 miaofng<miaofng@gmail.com>
> + *
> + * Copyright (c) 2003 Matthias Brukner, Trajet Gmbh, Rebenring 33,
> + * 38106 Braunschweig, GERMANY
> + *
> + * Copyright (c) 2002-2007 Volkswagen Group Electronic Research
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + * notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in the
> + * documentation and/or other materials provided with the distribution.
> + * 3. Neither the name of Volkswagen nor the names of its contributors
> + * may be used to endorse or promote products derived from this software
> + * without specific prior written permission.
> + *
> + * Alternatively, provided that this notice is retained in full, this
> + * software may be distributed under the terms of the GNU General
> + * Public License ("GPL") version 2, in which case the provisions of the
> + * GPL apply INSTEAD OF those given above.
> + *
> + * The provided data structures and external interfaces from this code
> + * are not restricted to be used by modules with a GPL compatible license.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
> + * DAMAGE.
> + *
> + * Send feedback to <socketcan-users@lists.berlios.de>
> + *
> + */
> +
> +#include <common.h>
> +#include <asm/io.h>
> +#include <can.h>
> +#include <malloc.h>
> +#include <linux/string.h>
> +
> +#include "sja1000.h"
> +
> +#define DRV_NAME "sja1000"
> +
> +//MODULE_AUTHOR("Oliver Hartkopp <oliver.hartkopp@volkswagen.de>");
> +//MODULE_LICENSE("Dual BSD/GPL");
> +//MODULE_DESCRIPTION(DRV_NAME "CAN netdevice driver");
> +
> +#define sja_debug printf
> +
> +/*
> + * Flags for sja1000priv.flags
> + */
> +#define SJA1000_CUSTOM_IRQ_HANDLER 0x1
> +
> +/*
> + * SJA1000 private data structure
> + */
> +struct sja1000_priv {
> + struct can_device can; /* must be the first member */
> +
> + /* the lower-layer is responsible for appropriate locking */
> + void* reg_base; /* ioremap'ed address to registers */
> +
> + u8 (*read_reg) (const struct sja1000_priv *priv, u8 reg);
> + void (*write_reg) (const struct sja1000_priv *priv, u8 reg, u8 val);
> +};
> +
> +static int set_reset_mode(struct can_device *dev)
> +{
> + struct sja1000_priv *priv = candev_priv(dev);
> + unsigned char status = priv->read_reg(priv, REG_MOD);
> + int i;
> +
> + /* disable interrupts */
> + priv->write_reg(priv, REG_IER, IRQ_OFF);
> +
> + for (i = 0; i < 100; i++) {
> + /* check reset bit */
> + if (status & MOD_RM) {
> + priv->can.state = CAN_STATE_STOPPED;
> + return 0;
> + }
> +
> + priv->write_reg(priv, REG_MOD, MOD_RM); /* reset chip */
> + udelay(10);
> + status = priv->read_reg(priv, REG_MOD);
> + }
> +
> + //sja_debug("SJA1000: setting into reset mode failed!\n");
> + return -1;
> +}
> +
> +static void set_normal_mode(struct can_device *dev)
> +{
> + struct sja1000_priv *priv = candev_priv(dev);
> + unsigned char status = priv->read_reg(priv, REG_MOD);
> + int i;
> +
> + for (i = 0; i < 100; i++) {
> + /* check reset bit */
> + if ((status & MOD_RM) == 0) {
> + priv->can.state = CAN_STATE_ERROR_ACTIVE;
> + /* enable all interrupts */
> + priv->write_reg(priv, REG_IER, IRQ_ALL);
> + return;
> + }
> +
> + /* set chip to normal mode */
> + priv->write_reg(priv, REG_MOD, 0x00);
> + udelay(10);
> + status = priv->read_reg(priv, REG_MOD);
> + }
> +
> + sja_debug("SJA1000@%d: setting into normal mode failed!\n", dev->index);
> +}
> +
> +static void sja1000_start(struct can_device *dev)
> +{
> + struct sja1000_priv *priv = candev_priv(dev);
> +
> + /* leave reset mode */
> + if (priv->can.state != CAN_STATE_STOPPED)
> + set_reset_mode(dev);
> +
> + /* Clear error counters and error code capture */
> + priv->write_reg(priv, REG_TXERR, 0x0);
> + priv->write_reg(priv, REG_RXERR, 0x0);
> + priv->read_reg(priv, REG_ECC);
> +
> + /* leave reset mode */
> + set_normal_mode(dev);
> +}
> +
> +#ifndef CONFIG_SJA1000_CLK_HZ
> +#define CONFIG_SJA1000_CLK_HZ 24000000
> +#endif
> +
> +static int sja1000_setbrg(int brg, struct can_device *dev)
> +{
> + struct sja1000_priv *priv = candev_priv(dev);
> + int fosc = CONFIG_SJA1000_CLK_HZ;
> + int fscl, btr0, btr1;
> + u8 sjw = 1; // 0~3 +1
> + u8 brp; // 0~63 +1
> + u8 sam = 1; // 0~1
> + u8 tseg2 = 5; // 0~7 +1
> + u8 tseg1 = 6; // 0~15 +1
> +
> + //calculation
> + fscl = (1+tseg1+tseg2)*brg;
> + brp = (fosc>>1)/fscl;
> + if(brg > 250000) sam = 0;
> +
> + //set register
> + btr0 = ((sjw - 1) << 6) | (brp - 1);
> + btr1 = (sam << 7) | ((tseg2 -1) << 4) | (tseg1 -1);
> +
> + sja_debug("SJA1000@%d: setting BTR0=0x%02x BTR1=0x%02x\n", dev->index, btr0, btr1);
> +
> + priv->write_reg(priv, REG_BTR0, btr0);
> + priv->write_reg(priv, REG_BTR1, btr1);
> +
> + return 0;
> +}
> +
> +/*
> + * initialize SJA1000 chip:
> + * - reset chip
> + * - set output mode
> + * - set baudrate
> + * - enable interrupts
> + * - start operating mode
> + */
> +static void chipset_init(struct can_device *dev)
> +{
> + struct sja1000_priv *priv = candev_priv(dev);
> +
> + /* set clock divider and output control register */
> + priv->write_reg(priv, REG_CDR, CDR_PELICAN|CDR_CBP|CDR_CLK_OFF);
> +
> + /* set acceptance filter (accept all) */
> + priv->write_reg(priv, REG_ACCC0, 0x00);
> + priv->write_reg(priv, REG_ACCC1, 0x00);
> + priv->write_reg(priv, REG_ACCC2, 0x00);
> + priv->write_reg(priv, REG_ACCC3, 0x00);
> +
> + priv->write_reg(priv, REG_ACCM0, 0xFF);
> + priv->write_reg(priv, REG_ACCM1, 0xFF);
> + priv->write_reg(priv, REG_ACCM2, 0xFF);
> + priv->write_reg(priv, REG_ACCM3, 0xFF);
> +
> + priv->write_reg(priv, REG_OCR, OCR_TX0_PUSHPULL|OCR_TX1_PUSHPULL| OCR_MODE_NORMAL);
> +}
> +
> +/*
> + * transmit a CAN message
> + */
> +static int sja1000_start_xmit(struct can_frame *cf, struct can_device *dev)
> +{
> + struct sja1000_priv *priv = candev_priv(dev);
> + struct can_device_stats *stats = &dev->stats;
> + uint8_t fi;
> + uint8_t dlc;
> + canid_t id;
> + uint8_t dreg;
> + int i;
> +
> + canif_stop_queue(dev);
> +
> + fi = dlc = cf->can_dlc;
> + id = cf->can_id;
> +
> + if (id & CAN_RTR_FLAG)
> + fi |= FI_RTR;
> +
> + if (id & CAN_EFF_FLAG) {
> + fi |= FI_FF;
> + dreg = EFF_BUF;
> + priv->write_reg(priv, REG_FI, fi);
> + priv->write_reg(priv, REG_ID1, (id & 0x1fe00000) >> (5 + 16));
> + priv->write_reg(priv, REG_ID2, (id & 0x001fe000) >> (5 + 8));
> + priv->write_reg(priv, REG_ID3, (id & 0x00001fe0) >> 5);
> + priv->write_reg(priv, REG_ID4, (id & 0x0000001f) << 3);
> + } else {
> + dreg = SFF_BUF;
> + priv->write_reg(priv, REG_FI, fi);
> + priv->write_reg(priv, REG_ID1, (id & 0x000007f8) >> 3);
> + priv->write_reg(priv, REG_ID2, (id & 0x00000007) << 5);
> + }
> +
> + for (i = 0; i < dlc; i++)
> + priv->write_reg(priv, dreg++, cf->data[i]);
> + priv->write_reg(priv, REG_CMR, CMD_TR);
> +
> + stats->tx_bytes += dlc;
> +
> + return 0;
> +}
> +
> +static void sja1000_rx(struct can_device *dev)
> +{
> + struct sja1000_priv *priv = candev_priv(dev);
> + struct can_device_stats *stats = &dev->stats;
> + struct can_frame *cf;
> + uint8_t fi;
> + uint8_t dreg;
> + canid_t id;
> + uint8_t dlc;
> + int i;
> +
> + cf = malloc(sizeof(struct can_frame));
> + if (cf == NULL) {
> + sja_debug("SJA1000%d: out of mem!\n",dev->index);
> + return;
> + }
> +
> + fi = priv->read_reg(priv, REG_FI);
> + dlc = fi & 0x0F;
> +
> + if (fi & FI_FF) {
> + /* extended frame format (EFF) */
> + dreg = EFF_BUF;
> + id = (priv->read_reg(priv, REG_ID1) << (5 + 16))
> + | (priv->read_reg(priv, REG_ID2) << (5 + 8))
> + | (priv->read_reg(priv, REG_ID3) << 5)
> + | (priv->read_reg(priv, REG_ID4) >> 3);
> + id |= CAN_EFF_FLAG;
> + } else {
> + /* standard frame format (SFF) */
> + dreg = SFF_BUF;
> + id = (priv->read_reg(priv, REG_ID1) << 3)
> + | (priv->read_reg(priv, REG_ID2) >> 5);
> + }
> +
> + if (fi & FI_RTR)
> + id |= CAN_RTR_FLAG;
> +
> + memset(cf, 0, sizeof(struct can_frame));
> + cf->can_id = id;
> + cf->can_dlc = dlc;
> + for (i = 0; i < dlc; i++)
> + cf->data[i] = priv->read_reg(priv, dreg++);
> +
> + while (i < 8)
> + cf->data[i++] = 0;
> +
> + /* release receive buffer */
> + priv->write_reg(priv, REG_CMR, CMD_RRB);
> +
> + canif_rx(cf, dev);
> +
> + //dev->last_rx = jiffies;
> + stats->rx_packets++;
> + stats->rx_bytes += dlc;
> +}
> +
> +static int sja1000_err(struct can_device *dev, uint8_t isrc, uint8_t status)
> +{
> + struct sja1000_priv *priv = candev_priv(dev);
> + struct can_device_stats *stats = &dev->stats;
> + struct can_frame *cf;
> + enum can_state state = priv->can.state;
> + uint8_t ecc, alc;
> +
> + cf = malloc(sizeof(struct can_frame));
> + if (cf == NULL)
> + {
> + sja_debug("SJA1000@%d: out of mem!\n", dev->index);
> + return -1;
> + }
> + memset(cf, 0, sizeof(struct can_frame));
> + cf->can_id = CAN_ERR_FLAG;
> + cf->can_dlc = CAN_ERR_DLC;
> +
> + if (isrc & IRQ_DOI) {
> + /* data overrun interrupt */
> + sja_debug("SJA1000@%d: data overrun interrupt\n", dev->index);
> + cf->can_id |= CAN_ERR_CRTL;
> + cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
> + //stats->rx_over_errors++;
> + stats->rx_errors++;
> + priv->write_reg(priv, REG_CMR, CMD_CDO); /* clear bit */
> + }
> +
> + if (isrc & IRQ_EI) {
> + /* error warning interrupt */
> + sja_debug("SJA1000@%d: error warning interrupt\n", dev->index);
> +
> + if (status & SR_BS) {
> + state = CAN_STATE_BUS_OFF;
> + cf->can_id |= CAN_ERR_BUSOFF;
> + //can_bus_off(dev);
> + } else if (status & SR_ES) {
> + state = CAN_STATE_ERROR_WARNING;
> + } else
> + state = CAN_STATE_ERROR_ACTIVE;
> + }
> + if (isrc & IRQ_BEI) {
> + /* bus error interrupt */
> + priv->can.stats.bus_error++;
> + stats->rx_errors++;
> +
> + ecc = priv->read_reg(priv, REG_ECC);
> +
> + cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
> +
> + switch (ecc & ECC_MASK) {
> + case ECC_BIT:
> + cf->data[2] |= CAN_ERR_PROT_BIT;
> + break;
> + case ECC_FORM:
> + cf->data[2] |= CAN_ERR_PROT_FORM;
> + break;
> + case ECC_STUFF:
> + cf->data[2] |= CAN_ERR_PROT_STUFF;
> + break;
> + default:
> + cf->data[2] |= CAN_ERR_PROT_UNSPEC;
> + cf->data[3] = ecc & ECC_SEG;
> + break;
> + }
> + /* error occured during transmission? */
> + if ((ecc & ECC_DIR) == 0)
> + cf->data[2] |= CAN_ERR_PROT_TX;
> + }
> + if (isrc & IRQ_EPI) {
> + /* error passive interrupt */
> + sja_debug("SJA1000@%d: error passive interrupt\n", dev->index);
> + if (status & SR_ES)
> + state = CAN_STATE_ERROR_PASSIVE;
> + else
> + state = CAN_STATE_ERROR_ACTIVE;
> + }
> + if (isrc & IRQ_ALI) {
> + /* arbitration lost interrupt */
> + sja_debug("SJA1000@%d: arbitration lost interrupt\n", dev->index);
> + alc = priv->read_reg(priv, REG_ALC);
> + priv->can.stats.arbitration_lost++;
> + stats->rx_errors++;
> + cf->can_id |= CAN_ERR_LOSTARB;
> + cf->data[0] = alc & 0x1f;
> + }
> +
> + if (state != priv->can.state && (state == CAN_STATE_ERROR_WARNING ||
> + state == CAN_STATE_ERROR_PASSIVE)) {
> + uint8_t rxerr = priv->read_reg(priv, REG_RXERR);
> + uint8_t txerr = priv->read_reg(priv, REG_TXERR);
> + cf->can_id |= CAN_ERR_CRTL;
> + if (state == CAN_STATE_ERROR_WARNING) {
> + priv->can.stats.error_warning++;
> + cf->data[1] = (txerr > rxerr) ?
> + CAN_ERR_CRTL_TX_WARNING :
> + CAN_ERR_CRTL_RX_WARNING;
> + } else {
> + priv->can.stats.error_passive++;
> + cf->data[1] = (txerr > rxerr) ?
> + CAN_ERR_CRTL_TX_PASSIVE :
> + CAN_ERR_CRTL_RX_PASSIVE;
> + }
> + }
> +
> + priv->can.state = state;
> +
> + canif_rx(cf,dev);
> +
> + return 0;
> +}
> +
> +#define SJA1000_MAX_IRQ 20 /* max. number of interrupts handled in ISR */
> +
> +int sja1000_interrupt(struct can_device *dev)
> +{
> + struct sja1000_priv *priv = candev_priv(dev);
> + struct can_device_stats *stats = &dev->stats;
> + uint8_t isrc, status;
> + int n = 0;
> +
> + /* Shared interrupts and IRQ off? */
> + if (priv->read_reg(priv, REG_IER) == IRQ_OFF)
> + return -1;
> +
> + while ((isrc = priv->read_reg(priv, REG_IR)) && (n < SJA1000_MAX_IRQ)) {
> + n++;
> + status = priv->read_reg(priv, REG_SR);
> +
> + if (isrc & IRQ_WUI)
> + sja_debug("SJA1000@%d: wakeup interrupt\n", dev->index);
> +
> + if (isrc & IRQ_TI) {
> + /* transmission complete interrupt */
> + stats->tx_packets++;
> +
> + //can_get_echo_skb(dev, 0);
> + canif_wake_queue(dev);
> + }
> + if (isrc & IRQ_RI) {
> + /* receive interrupt */
> + while (status & SR_RBS) {
> + sja1000_rx(dev);
> + status = priv->read_reg(priv, REG_SR);
> + }
> + }
> + if (isrc & (IRQ_DOI | IRQ_EI | IRQ_BEI | IRQ_EPI | IRQ_ALI)) {
> + /* error interrupt */
> + if (sja1000_err(dev, isrc, status))
> + break;
> + }
> + }
> +
> + if (n >= SJA1000_MAX_IRQ)
> + sja_debug("SJA1000@%d: %d messages handled in ISR", dev->index, n);
> +
> + return (n) ? 0 : -1;
> +}
> +
> +static int sja1000_open(struct can_device *dev)
> +{
> + /* set chip into reset mode */
> + set_reset_mode(dev);
> +
> + /* register interrupt handler, if not done by the device driver */
> +#ifdef CONFIG_USBCAN
> + extern int request_irq_usbcan(int (*isr)(struct can_device*), struct can_device*);
> + int err = request_irq_usbcan(&sja1000_interrupt, dev);
> + if (err) {
> + sja_debug("SJA1000@%d: unable to request the irq\n", dev->index);
> + return -1;
> + }
> +#endif
> +
> + /* init and start chi */
> + sja1000_start(dev);
> +
> + //priv->open_time = jiffies;
> + canif_start_queue(dev);
> +
> + return 0;
> +}
> +
> +static int sja1000_close(struct can_device *dev)
> +{
> + canif_stop_queue(dev);
> + set_reset_mode(dev);
> +
> + //can_free_irq(dev->irq, (void *)dev);
> +
> + return 0;
> +}
> +
> +static int sja1000_probe_chip(struct can_device *dev)
> +{
> + struct sja1000_priv *priv = candev_priv(dev);
> + int ret;
> +
> + ret = set_reset_mode(dev);
> + if(ret) {
> + sja_debug("%s: probing @0x%x failed\n", DRV_NAME, (u32)(priv->reg_base));
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +int register_sja1000dev(struct can_device *dev)
> +{
> + if (sja1000_probe_chip(dev))
> + return -1;
> +
> + strcpy(dev->name, DRV_NAME);
> + dev->setbrg = sja1000_setbrg;
> + dev->open = sja1000_open;
> + dev->start_xmit = sja1000_start_xmit;
> + dev->close = sja1000_close;
> +
> + set_reset_mode(dev);
> + chipset_init(dev);
> +
> + return register_candev(dev);
> +}
> +
> +void unregister_sja1000dev(struct can_device *dev)
> +{
> + set_reset_mode(dev);
> + unregister_candev(dev);
> +}
> +
> +
> +static u8 sja1000_read_reg(const struct sja1000_priv *priv, u8 reg)
> +{
> +#if (CONFIG_USBCAN == 1)
> + writeb(reg, priv->reg_base+4); //addr latch
> + return readb(priv->reg_base);
> +#else
> + return writeb(priv->reg_base + reg);
> +#endif
> +}
> +
> +static void sja1000_write_reg(const struct sja1000_priv *priv, u8 reg, u8 val)
> +{
> +#if (CONFIG_USBCAN == 1)
> + writeb(reg, priv->reg_base+4); //addr latch
> + writeb(val, priv->reg_base);
> +#else
> + return readb(val, priv->reg_base + reg);
> +#endif
> +}
> +
> +int sja1000_init(u32 reg_base)
> +{
> + struct sja1000_priv * priv = malloc(sizeof(struct sja1000_priv));
> + if(priv == NULL) {
> + sja_debug("SJA1000: out of mem!!!\n");
> + return -1;
> + }
> +
> + memset(priv, 0, sizeof(priv));
> + priv->reg_base = (void*)reg_base;
> + priv->read_reg = sja1000_read_reg;
> + priv->write_reg = sja1000_write_reg;
> +
> + if( register_sja1000dev(&priv->can) )
> + {
> + free(priv);
> + //sja_debug("SJA1000: register device fail!!!\n");
> + return -1;
> + }
> +
> + return 0;
> +}
> diff --git a/drivers/can/sja1000.h b/drivers/can/sja1000.h
> new file mode 100755
> index 0000000..6311f75
> --- /dev/null
> +++ b/drivers/can/sja1000.h
> @@ -0,0 +1,160 @@
> +/*
> + * sja1000.h - Philips SJA1000 network device driver
> + *
> + * Copyright (C) 2009 miaofng<miaofng@126.com>
> + * Copyright (c) 2003 Matthias Brukner, Trajet Gmbh, Rebenring 33,
> + * 38106 Braunschweig, GERMANY
> + *
> + * Copyright (c) 2002-2007 Volkswagen Group Electronic Research
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + * notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in the
> + * documentation and/or other materials provided with the distribution.
> + * 3. Neither the name of Volkswagen nor the names of its contributors
> + * may be used to endorse or promote products derived from this software
> + * without specific prior written permission.
> + *
> + * Alternatively, provided that this notice is retained in full, this
> + * software may be distributed under the terms of the GNU General
> + * Public License ("GPL") version 2, in which case the provisions of the
> + * GPL apply INSTEAD OF those given above.
> + *
> + * The provided data structures and external interfaces from this code
> + * are not restricted to be used by modules with a GPL compatible license.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
> + * DAMAGE.
> + *
> + * Send feedback to <socketcan-users@lists.berlios.de>
> + *
> + */
> +
> +#ifndef SJA1000_DEV_H
> +#define SJA1000_DEV_H
> +
> +/* SJA1000 registers - manual section 6.4 (Pelican Mode) */
> +#define REG_MOD 0x00
> +#define REG_CMR 0x01
> +#define REG_SR 0x02
> +#define REG_IR 0x03
> +#define REG_IER 0x04
> +#define REG_ALC 0x0B
> +#define REG_ECC 0x0C
> +#define REG_EWL 0x0D
> +#define REG_RXERR 0x0E
> +#define REG_TXERR 0x0F
> +#define REG_ACCC0 0x10
> +#define REG_ACCC1 0x11
> +#define REG_ACCC2 0x12
> +#define REG_ACCC3 0x13
> +#define REG_ACCM0 0x14
> +#define REG_ACCM1 0x15
> +#define REG_ACCM2 0x16
> +#define REG_ACCM3 0x17
> +#define REG_RMC 0x1D
> +#define REG_RBSA 0x1E
> +
> +/* Common registers - manual section 6.5 */
> +#define REG_BTR0 0x06
> +#define REG_BTR1 0x07
> +#define REG_OCR 0x08
> +#define REG_CDR 0x1F
> +
> +#define REG_FI 0x10
> +#define SFF_BUF 0x13
> +#define EFF_BUF 0x15
> +
> +#define FI_FF 0x80
> +#define FI_RTR 0x40
> +
> +#define REG_ID1 0x11
> +#define REG_ID2 0x12
> +#define REG_ID3 0x13
> +#define REG_ID4 0x14
> +
> +#define CAN_RAM 0x20
> +
> +/* mode register */
> +#define MOD_RM 0x01
> +#define MOD_LOM 0x02
> +#define MOD_STM 0x04
> +#define MOD_AFM 0x08
> +#define MOD_SM 0x10
> +
> +/* commands */
> +#define CMD_SRR 0x10
> +#define CMD_CDO 0x08
> +#define CMD_RRB 0x04
> +#define CMD_AT 0x02
> +#define CMD_TR 0x01
> +
> +/* interrupt sources */
> +#define IRQ_BEI 0x80
> +#define IRQ_ALI 0x40
> +#define IRQ_EPI 0x20
> +#define IRQ_WUI 0x10
> +#define IRQ_DOI 0x08
> +#define IRQ_EI 0x04
> +#define IRQ_TI 0x02
> +#define IRQ_RI 0x01
> +#define IRQ_ALL 0xFF
> +#define IRQ_OFF 0x00
> +
> +/* status register content */
> +#define SR_BS 0x80
> +#define SR_ES 0x40
> +#define SR_TS 0x20
> +#define SR_RS 0x10
> +#define SR_TCS 0x08
> +#define SR_TBS 0x04
> +#define SR_DOS 0x02
> +#define SR_RBS 0x01
> +
> +#define SR_CRIT (SR_BS|SR_ES)
> +
> +/* ECC register */
> +#define ECC_SEG 0x1F
> +#define ECC_DIR 0x20
> +#define ECC_ERR 6
> +#define ECC_BIT 0x00
> +#define ECC_FORM 0x40
> +#define ECC_STUFF 0x80
> +#define ECC_MASK 0xc0
> +
> +/* clock divider register */
> +#define CDR_CLKOUT_MASK 0x07
> +#define CDR_CLK_OFF 0x08 /* Clock off (CLKOUT pin) */
> +#define CDR_RXINPEN 0x20 /* TX1 output is RX irq output */
> +#define CDR_CBP 0x40 /* CAN input comparator bypass */
> +#define CDR_PELICAN 0x80 /* PeliCAN mode */
> +
> +/* output control register */
> +#define OCR_MODE_BIPHASE 0x00
> +#define OCR_MODE_TEST 0x01
> +#define OCR_MODE_NORMAL 0x02
> +#define OCR_MODE_CLOCK 0x03
> +#define OCR_TX0_INVERT 0x04
> +#define OCR_TX0_PULLDOWN 0x08
> +#define OCR_TX0_PULLUP 0x10
> +#define OCR_TX0_PUSHPULL 0x18
> +#define OCR_TX1_INVERT 0x20
> +#define OCR_TX1_PULLDOWN 0x40
> +#define OCR_TX1_PULLUP 0x80
> +#define OCR_TX1_PUSHPULL 0xc0
> +#endif /* SJA1000_DEV_H */
> diff --git a/include/can.h b/include/can.h
> new file mode 100755
> index 0000000..55e6643
> --- /dev/null
> +++ b/include/can.h
> @@ -0,0 +1,216 @@
> +/*
> + * linux/can.h
> + *
> + * Definitions for CAN network layer (socket addr / CAN frame / CAN filter)
> + *
> + * Copyright (C) 2009 miaofng<miaofng@gmail.com>
> + *
> + * Authors: Oliver Hartkopp <oliver.hartkopp@volkswagen.de>
> + * Urs Thuermann <urs.thuermann@volkswagen.de>
> + * Copyright (c) 2002-2007 Volkswagen Group Electronic Research
> + * All rights reserved.
> + *
> + * Send feedback to <socketcan-users@lists.berlios.de>
> + *
> + */
> +
> +#ifndef CAN_H
> +#define CAN_H
> +
> +#include <linux/types.h>
> +#include <can_error.h>
> +#include <circbuf.h>
> +#include <candev.h>
> +
> +/* controller area network (CAN) kernel definitions */
> +
> +/* special address description flags for the CAN_ID */
> +#define CAN_EFF_FLAG 0x80000000U /* EFF/SFF is set in the MSB */
> +#define CAN_RTR_FLAG 0x40000000U /* remote transmission request */
> +#define CAN_ERR_FLAG 0x20000000U /* error frame */
> +
> +/* valid bits in CAN ID for frame formats */
> +#define CAN_SFF_MASK 0x000007FFU /* standard frame format (SFF) */
> +#define CAN_EFF_MASK 0x1FFFFFFFU /* extended frame format (EFF) */
> +#define CAN_ERR_MASK 0x1FFFFFFFU /* omit EFF, RTR, ERR flags */
> +
> +/*
> + * Controller Area Network Identifier structure
> + *
> + * bit 0-28 : CAN identifier (11/29 bit)
> + * bit 29 : error frame flag (0 = data frame, 1 = error frame)
> + * bit 30 : remote transmission request flag (1 = rtr frame)
> + * bit 31 : frame format flag (0 = standard 11 bit, 1 = extended 29 bit)
> + */
> +typedef __u32 canid_t;
> +
> +/**
> + * struct can_frame - basic CAN frame structure
> + * @can_id: the CAN ID of the frame and CAN_*_FLAG flags, see above.
> + * @can_dlc: the data length field of the CAN frame
> + * @data: the CAN frame payload.
> + */
> +struct can_frame {
> + canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */
> + __u8 can_dlc; /* data length code: 0 .. 8 */
> + __u8 data[8] __attribute__((aligned(8)));
> +};
> +
> +/**
> + * struct can_filter - CAN ID based filter in can_register().
> + * @can_id: relevant bits of CAN ID which are not masked out.
> + * @can_mask: CAN mask (see description)
> + *
> + * Description:
> + * A filter matches, when
> + *
> + * <received_can_id> & mask == can_id & mask
> + *
> + * The filter can be inverted (CAN_INV_FILTER bit set in can_id) or it can
> + * filter for error frames (CAN_ERR_FLAG bit set in mask).
> + */
> +struct can_filter {
> + canid_t can_id;
> + canid_t can_mask;
> +
> + struct can_filter* next;
> +};
> +
> +#define CAN_INV_FILTER 0x20000000U /* to be set in can_filter.can_id */
> +
> +//can_device.state
> +enum can_state {
> + CAN_STATE_ERROR_ACTIVE = 0, /* RX/TX error count < 96 */
> + CAN_STATE_ERROR_WARNING, /* RX/TX error count < 128 */
> + CAN_STATE_ERROR_PASSIVE, /* RX/TX error count < 256 */
> + CAN_STATE_BUS_OFF, /* RX/TX error count >= 256 */
> + CAN_STATE_STOPPED, /* Device is stopped */
> + CAN_STATE_SLEEPING, /* Device is sleeping */
> + CAN_STATE_MAX
> +};
> +
> +//can_device.stats, refer to net_device_stats
> +struct can_device_stats
> +{
> + unsigned long rx_packets; /* total packets received */
> + unsigned long tx_packets; /* total packets transmitted */
> + unsigned long rx_bytes; /* total bytes received */
> + unsigned long tx_bytes; /* total bytes transmitted */
> + unsigned long rx_errors; /* bad packets received */
> + unsigned long tx_errors; /* packet transmit problems */
> + unsigned long rx_dropped; /* no space in linux buffers */
> + unsigned long tx_dropped; /* no space available in linux */
> + unsigned long multicast; /* multicast packets received */
> + unsigned long collisions;
> +
> + //can stats
> + unsigned long error_passive;
> + unsigned long error_warning;
> + unsigned long arbitration_lost;
> + unsigned long bus_error;
> +};
> +
> +/*queue status definition*/
> +#define CAN_QUEUE_INIT 0
> +#define CAN_QUEUE_READY 1
> +#define CAN_QUEUE_BUSY 2
> +
> +#define NAMESIZE_CAN 8
> +
> +struct can_device {
> + //can core readonly
> + char name[NAMESIZE_CAN];
> + enum can_state state;
> + struct can_device_stats stats;
> +
> + //can dev methods
> + int (*setbrg)(int, struct can_device*);
> + int (*setfilter)(struct can_filter*, struct can_device*);
> + int (*open) (struct can_device*);
> + int (*start_xmit) (struct can_frame*, struct can_device*);
> + int (*close)(struct can_device*);
> +
> + //can_core private
> + int qstatus; //queue status
> + circbuf_t tbuf; //tx buffer
> + circbuf_t rbuf; //rx buffer
> + //struct can_device *next;
> + int index;
> +};
> +
> +//help routines
> +static inline void *candev_priv(const struct can_device *dev) { return (void *) dev; }
> +int register_candev(struct can_device*);
> +void unregister_candev(struct can_device*);
> +void canif_rx(struct can_frame*, struct can_device*);
> +
> +/* *
> + * these 3 functions are used to set the queue status
> + *
> + */
> +static inline void canif_stop_queue(struct can_device *dev) {dev->qstatus = CAN_QUEUE_BUSY;}
> +static inline void canif_start_queue(struct can_device *dev) {dev->qstatus = CAN_QUEUE_READY;}
> +void canif_wake_queue(struct can_device*);
> +
> +//note: these functions must be called before can_open()
> +int can_init(void);
> +
> +/**
> + * function can_setbrg - set the bus speed of can device
> + * @brg bus speed to set, unit bps, such as: 250000,1000000 and etc
> + * @index device to set the speed, should be 0,1,2,....
> + * @return success->0, or fail->-1
> + * description:
> + * please set the speed when the device in reset mode.
> + */
> +int can_setbrg(int brg, int index);
> +
> +/**
> + * function can_setfilter - set the can id filter
> + * @filter filter list to be set
> + * @index device to do the operation, such as 0,1,2 ...
> + * @return success->0, or fail->-1
> + * description:
> + * please set the filter when the device in reset mode.
> + */
> +int can_setfilter(struct can_filter *filter, int index);
> +
> +/**
> + * function can_open - open a specified can device(or channel) for read/write
> + * @index index of the can channel to open, value as 0,1,2 ...
> + * @return device id, for can_send/can_recv ... , in case of fail, return 0
> + * description:
> + * can device will leave the reset mode by this operation.
> + */
> +int can_open(int index);
> +
> +/**
> + * function can_send - send a can frame
> + * @cf frame to be sent
> + * @dev_id device to do 'send' operation
> + * @return success->0, or fail->-1
> + * description:
> + * this is non block operation. can_core will store the frame pointer to the tx cirbuf.
> + */
> +int can_send(struct can_frame *cf, int dev_id);
> +
> +/**
> + * function can_recv - get a can frame from the specified can device(or channel)
> + * @dev_id can device to read
> + * @return success-> the pointer to a can frame, fail->0
> + * description:
> + * this is non block operation. can_core will get a frame pointer from the rx cirbuf of the device.
> + * the memory of the frame should be released by caller.
> + */
> +struct can_frame* can_recv(int dev_id);
> +
> +/**
> + * function can_close - close a specified can device(or channel)
> + * @dev_id can device to close
> + * description:
> + * can_close will do following operation:
> + * 1) dump the device's tx/rx buffer
> + * 2) set device into reset mode
> + */
> +void can_close(int dev_id);
> +#endif /* CAN_H */
> diff --git a/include/can_error.h b/include/can_error.h
> new file mode 100755
> index 0000000..d4127fd
> --- /dev/null
> +++ b/include/can_error.h
> @@ -0,0 +1,93 @@
> +/*
> + * linux/can/error.h
> + *
> + * Definitions of the CAN error frame to be filtered and passed to the user.
> + *
> + * Author: Oliver Hartkopp <oliver.hartkopp@volkswagen.de>
> + * Copyright (c) 2002-2007 Volkswagen Group Electronic Research
> + * All rights reserved.
> + *
> + * Send feedback to <socketcan-users@lists.berlios.de>
> + *
> + */
> +
> +#ifndef CAN_ERROR_H
> +#define CAN_ERROR_H
> +
> +#define CAN_ERR_DLC 8 /* dlc for error frames */
> +
> +/* error class (mask) in can_id */
> +#define CAN_ERR_TX_TIMEOUT 0x00000001U /* TX timeout (by netdevice driver) */
> +#define CAN_ERR_LOSTARB 0x00000002U /* lost arbitration / data[0] */
> +#define CAN_ERR_CRTL 0x00000004U /* controller problems / data[1] */
> +#define CAN_ERR_PROT 0x00000008U /* protocol violations / data[2..3] */
> +#define CAN_ERR_TRX 0x00000010U /* transceiver status / data[4] */
> +#define CAN_ERR_ACK 0x00000020U /* received no ACK on transmission */
> +#define CAN_ERR_BUSOFF 0x00000040U /* bus off */
> +#define CAN_ERR_BUSERROR 0x00000080U /* bus error (may flood!) */
> +#define CAN_ERR_RESTARTED 0x00000100U /* controller restarted */
> +
> +/* arbitration lost in bit ... / data[0] */
> +#define CAN_ERR_LOSTARB_UNSPEC 0x00 /* unspecified */
> + /* else bit number in bitstream */
> +
> +/* error status of CAN-controller / data[1] */
> +#define CAN_ERR_CRTL_UNSPEC 0x00 /* unspecified */
> +#define CAN_ERR_CRTL_RX_OVERFLOW 0x01 /* RX buffer overflow */
> +#define CAN_ERR_CRTL_TX_OVERFLOW 0x02 /* TX buffer overflow */
> +#define CAN_ERR_CRTL_RX_WARNING 0x04 /* reached warning level for RX errors */
> +#define CAN_ERR_CRTL_TX_WARNING 0x08 /* reached warning level for TX errors */
> +#define CAN_ERR_CRTL_RX_PASSIVE 0x10 /* reached error passive status RX */
> +#define CAN_ERR_CRTL_TX_PASSIVE 0x20 /* reached error passive status TX */
> + /* (at least one error counter exceeds */
> + /* the protocol-defined level of 127) */
> +
> +/* error in CAN protocol (type) / data[2] */
> +#define CAN_ERR_PROT_UNSPEC 0x00 /* unspecified */
> +#define CAN_ERR_PROT_BIT 0x01 /* single bit error */
> +#define CAN_ERR_PROT_FORM 0x02 /* frame format error */
> +#define CAN_ERR_PROT_STUFF 0x04 /* bit stuffing error */
> +#define CAN_ERR_PROT_BIT0 0x08 /* unable to send dominant bit */
> +#define CAN_ERR_PROT_BIT1 0x10 /* unable to send recessive bit */
> +#define CAN_ERR_PROT_OVERLOAD 0x20 /* bus overload */
> +#define CAN_ERR_PROT_ACTIVE 0x40 /* active error announcement */
> +#define CAN_ERR_PROT_TX 0x80 /* error occured on transmission */
> +
> +/* error in CAN protocol (location) / data[3] */
> +#define CAN_ERR_PROT_LOC_UNSPEC 0x00 /* unspecified */
> +#define CAN_ERR_PROT_LOC_SOF 0x03 /* start of frame */
> +#define CAN_ERR_PROT_LOC_ID28_21 0x02 /* ID bits 28 - 21 (SFF: 10 - 3) */
> +#define CAN_ERR_PROT_LOC_ID20_18 0x06 /* ID bits 20 - 18 (SFF: 2 - 0 )*/
> +#define CAN_ERR_PROT_LOC_SRTR 0x04 /* substitute RTR (SFF: RTR) */
> +#define CAN_ERR_PROT_LOC_IDE 0x05 /* identifier extension */
> +#define CAN_ERR_PROT_LOC_ID17_13 0x07 /* ID bits 17-13 */
> +#define CAN_ERR_PROT_LOC_ID12_05 0x0F /* ID bits 12-5 */
> +#define CAN_ERR_PROT_LOC_ID04_00 0x0E /* ID bits 4-0 */
> +#define CAN_ERR_PROT_LOC_RTR 0x0C /* RTR */
> +#define CAN_ERR_PROT_LOC_RES1 0x0D /* reserved bit 1 */
> +#define CAN_ERR_PROT_LOC_RES0 0x09 /* reserved bit 0 */
> +#define CAN_ERR_PROT_LOC_DLC 0x0B /* data length code */
> +#define CAN_ERR_PROT_LOC_DATA 0x0A /* data section */
> +#define CAN_ERR_PROT_LOC_CRC_SEQ 0x08 /* CRC sequence */
> +#define CAN_ERR_PROT_LOC_CRC_DEL 0x18 /* CRC delimiter */
> +#define CAN_ERR_PROT_LOC_ACK 0x19 /* ACK slot */
> +#define CAN_ERR_PROT_LOC_ACK_DEL 0x1B /* ACK delimiter */
> +#define CAN_ERR_PROT_LOC_EOF 0x1A /* end of frame */
> +#define CAN_ERR_PROT_LOC_INTERM 0x12 /* intermission */
> +
> +/* error status of CAN-transceiver / data[4] */
> +/* CANH CANL */
> +#define CAN_ERR_TRX_UNSPEC 0x00 /* 0000 0000 */
> +#define CAN_ERR_TRX_CANH_NO_WIRE 0x04 /* 0000 0100 */
> +#define CAN_ERR_TRX_CANH_SHORT_TO_BAT 0x05 /* 0000 0101 */
> +#define CAN_ERR_TRX_CANH_SHORT_TO_VCC 0x06 /* 0000 0110 */
> +#define CAN_ERR_TRX_CANH_SHORT_TO_GND 0x07 /* 0000 0111 */
> +#define CAN_ERR_TRX_CANL_NO_WIRE 0x40 /* 0100 0000 */
> +#define CAN_ERR_TRX_CANL_SHORT_TO_BAT 0x50 /* 0101 0000 */
> +#define CAN_ERR_TRX_CANL_SHORT_TO_VCC 0x60 /* 0110 0000 */
> +#define CAN_ERR_TRX_CANL_SHORT_TO_GND 0x70 /* 0111 0000 */
> +#define CAN_ERR_TRX_CANL_SHORT_TO_CANH 0x80 /* 1000 0000 */
> +
> +/* controller specific additional information / data[5..7] */
> +
> +#endif /* CAN_ERROR_H */
> diff --git a/include/candev.h b/include/candev.h
> new file mode 100755
> index 0000000..0e0dee7
> --- /dev/null
> +++ b/include/candev.h
> @@ -0,0 +1,46 @@
> +/*
> + * (C) Copyright 2009 miaofng<miaofng@gmail.com>
> + *
> + *
> + * See file CREDITS for list of people who contributed to this
> + * project.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +
> +/*
> + * netdev.h - definitions an prototypes for network devices
> + */
> +
> +#ifndef _CANDEV_H_
> +#define _CANDEV_H_
> +
> +/*
> + * Board and CPU-specific initialization functions
> + * board_eth_init() has highest priority. cpu_eth_init() only
> + * gets called if board_eth_init() isn't instantiated or fails.
> + * Return values:
> + * 0: success
> + * -1: failure
> + */
> +
> +int board_can_init(void);
> +void board_can_update(void);
> +
> +/* Driver initialization prototypes */
> +int sja1000_init(u32 reg_base);
> +
> +#endif /* _CANDEV_H_ */
> diff --git a/lib_arm/board.c b/lib_arm/board.c
> old mode 100644
> new mode 100755
> index 5e3d7f6..aa11dd3
> --- a/lib_arm/board.c
> +++ b/lib_arm/board.c
> @@ -356,6 +356,8 @@ void start_armboot (void)
> serial_initialize();
> #endif
>
> + can_init();
> +
> /* IP Address */
> gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
>
--
-------------------------------------------------------------------------
Dipl.-Ing. Matthias Fuchs
Head of System Design
esd electronic system design gmbh
Vahrenwalder Str. 207 - 30165 Hannover - GERMANY
Phone: +49-511-37298-0 - Fax: +49-511-37298-68
Please visit our homepage http://www.esd.eu
Quality Products - Made in Germany
-------------------------------------------------------------------------
Gesch?ftsf?hrer: Klaus Detering, Dr. Werner Schulze
Amtsgericht Hannover HRB 51373 - VAT-ID DE 115672832
-------------------------------------------------------------------------
^ permalink raw reply [flat|nested] 15+ messages in thread
* [U-Boot] [PATCH] add u-boot sja1000/can support
[not found] ` <200910261629132341038@gmail.com>
@ 2009-10-26 8:41 ` Mike Frysinger
2009-10-26 13:01 ` miaofng
2009-10-26 8:47 ` [U-Boot] Fw: Re: " miaofng
1 sibling, 1 reply; 15+ messages in thread
From: Mike Frysinger @ 2009-10-26 8:41 UTC (permalink / raw)
To: u-boot
On Monday 26 October 2009 04:30:10 miaofng wrote:
> Hi mike,
please do not top post
> It seems there's a big difference between my current project
> and u-boot common usage. I can only enjoy the patch myself now
>
> i want to get a packet from usb/network, then redirect it to can bus.
> So blocked write/read of can is not allowed.
what's wrong with receiving data over usb/network into external memory, then
transferring it over CAN ? this is typically how things are done -- load an
file over the network and once it is complete, operate on it (write it to
flash, boot it, whatever).
-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/20091026/1429b119/attachment.pgp
^ permalink raw reply [flat|nested] 15+ messages in thread
* [U-Boot] Fw: Re: Re: [PATCH] add u-boot sja1000/can support
[not found] ` <200910261629132341038@gmail.com>
2009-10-26 8:41 ` Mike Frysinger
@ 2009-10-26 8:47 ` miaofng
2009-10-26 12:32 ` Wolfgang Grandegger
2009-10-26 22:00 ` Wolfgang Denk
1 sibling, 2 replies; 15+ messages in thread
From: miaofng @ 2009-10-26 8:47 UTC (permalink / raw)
To: u-boot
Hi mike,
It seems there's a big difference between my current project
and u-boot common usage. I can only enjoy the patch myself now
i want to get a packet from usb/network, then redirect it to can bus.
So blocked write/read of can is not allowed.
On Monday 26 October 2009 00:48:39 miaofng wrote:
> Thanks for careful review. I'll resend the patch according to your remarks
> except follwing: 1)
>
> > +int register_candev(struct can_device *dev)
>
> use "can" or "candev", dont mix the two
>
> answer: register_candev is origin from register_netdev(...). CAN is
> something like network, it may has high level protocols such as open-can
> and etc, so i want to keep that story.
i know what CAN is. the Linux approach makes sense because they've
architected CAN at the socket() layer, and all of the network layers are
written with common coding style. but there is no such socket/network layer
in u-boot so the can/candev distinction isnt necessary.
> > +int sja1000_interrupt(struct can_device *dev)
>
> u-boot is a polled architecture, not an interrupt based one. i guess this
> driver needs rewriting to do that.
>
> answer: no, i want to keep that structure. Then linux drivers can be ported
> to u-boot easily. take an example, in sja1000, i only need to replace
> "_net" to "_can" at most of time. To gain this convience, i added the wrap
> layer of can_core.c.
the convenience factor doesnt mean you can ignore u-boot design principles.
the default behavior for all frameworks/drivers is a polled mode because it's
simple and straightforward. not all u-boot ports even support interrupts
> In order to work in u-boot polled mode, people only
> need to call sja1000_interrupt periodly. It works fine on my board.
erm, no, that's not how things work in u-boot. u-boot processes commands
given to it (either via scripts or from user input), and each command does not
return until it is completely done processing. there is no "backgrounding" of
drivers -- u-boot is not an OS and it is not threaded. that means any CAN
operation does not return until it has finished sending/receiving everything
it was told to.
-mike
^ permalink raw reply [flat|nested] 15+ messages in thread
* [U-Boot] [PATCH] add u-boot sja1000/can support
2009-10-24 4:17 [U-Boot] [PATCH] add u-boot sja1000/can support miaofng
` (2 preceding siblings ...)
2009-10-26 8:18 ` [U-Boot] " Matthias Fuchs
@ 2009-10-26 12:14 ` Wolfgang Grandegger
2009-10-26 21:56 ` Wolfgang Denk
4 siblings, 0 replies; 15+ messages in thread
From: Wolfgang Grandegger @ 2009-10-26 12:14 UTC (permalink / raw)
To: u-boot
Hello,
miaofng wrote:
>>From 1f6aaba856fbf484c442eb33cf220774d57fba8d Mon Sep 17 00:00:00 2001
> From: miaofng <miaofng@gmail.com>
> Date: Fri, 23 Oct 2009 17:06:50 +0800
> Subject: [PATCH] [can] add u-boot sja1000/can support
There are already CAN controllers supported for some board, e.g.
./tqm5200/cmd_stk52xx.c, and a generic CAN device drive interface would
be nice to have, indeed. At a first glance I find your Socket-CAN based
approach to heavy. Could you please elaborate on the use cases you have
in mind.
Wolfgang.
^ permalink raw reply [flat|nested] 15+ messages in thread
* [U-Boot] Fw: Re: Re: [PATCH] add u-boot sja1000/can support
2009-10-26 8:47 ` [U-Boot] Fw: Re: " miaofng
@ 2009-10-26 12:32 ` Wolfgang Grandegger
2009-10-26 13:29 ` miaofng
2009-10-26 22:00 ` Wolfgang Denk
1 sibling, 1 reply; 15+ messages in thread
From: Wolfgang Grandegger @ 2009-10-26 12:32 UTC (permalink / raw)
To: u-boot
miaofng wrote:
> Hi mike,
> It seems there's a big difference between my current project
> and u-boot common usage. I can only enjoy the patch myself now
Yes, can you describe your use-case. CAN in U-BOOT, so far, was just
used to send or receive one or a few messages, mainly for testing purposes.
>
> i want to get a packet from usb/network, then redirect it to can bus.
> So blocked write/read of can is not allowed.
You have that working?
Wolfgang.
^ permalink raw reply [flat|nested] 15+ messages in thread
* [U-Boot] [PATCH] add u-boot sja1000/can support
2009-10-26 8:41 ` Mike Frysinger
@ 2009-10-26 13:01 ` miaofng
0 siblings, 0 replies; 15+ messages in thread
From: miaofng @ 2009-10-26 13:01 UTC (permalink / raw)
To: u-boot
It seems there's a big difference between my current project
>> and u-boot common usage. I can only enjoy the patch myself now
>>
>> i want to get a packet from usb/network, then redirect it to can bus.
>> So blocked write/read of can is not allowed.
>>
>
> what's wrong with receiving data over usb/network into external memory, then
> transferring it over CAN ? this is typically how things are done -- load an
> file over the network and once it is complete, operate on it (write it to
> flash, boot it, whatever).
> -mike
>
It seems a good method, especially when we download a file from computer.
But i'm afraid u-boot doesn't support upload well.
Basically I agree blocked CAN read/write can fulfill my requirement,
even though it's not so flexible as what i wished.
^ permalink raw reply [flat|nested] 15+ messages in thread
* [U-Boot] Fw: Re: Re: [PATCH] add u-boot sja1000/can support
2009-10-26 12:32 ` Wolfgang Grandegger
@ 2009-10-26 13:29 ` miaofng
2009-10-26 14:44 ` Wolfgang Grandegger
2009-10-26 22:03 ` Wolfgang Denk
0 siblings, 2 replies; 15+ messages in thread
From: miaofng @ 2009-10-26 13:29 UTC (permalink / raw)
To: u-boot
Wolfgang Grandegger wrote:
> miaofng wrote:
>
>> Hi mike,
>> It seems there's a big difference between my current project
>> and u-boot common usage. I can only enjoy the patch myself now
>>
>
> Yes, can you describe your use-case. CAN in U-BOOT, so far, was just
> used to send or receive one or a few messages, mainly for testing purposes.
>
>
what i want to do is something like a protocol gateway. It converts the
data from one type to another.
u-boot has support so many cpu/board/...., i thinks it can do much more
tasks than just for testing purposes.
It could be a non-OS based software plaform :)
>> i want to get a packet from usb/network, then redirect it to can bus.
>> So blocked write/read of can is not allowed.
>>
>
> You have that working?
>
>
not yet. i have finished usb and can part.
^ permalink raw reply [flat|nested] 15+ messages in thread
* [U-Boot] Fw: Re: Re: [PATCH] add u-boot sja1000/can support
2009-10-26 13:29 ` miaofng
@ 2009-10-26 14:44 ` Wolfgang Grandegger
2009-10-26 22:03 ` Wolfgang Denk
1 sibling, 0 replies; 15+ messages in thread
From: Wolfgang Grandegger @ 2009-10-26 14:44 UTC (permalink / raw)
To: u-boot
miaofng wrote:
> Wolfgang Grandegger wrote:
>> miaofng wrote:
>>
>>> Hi mike,
>>> It seems there's a big difference between my current project
>>> and u-boot common usage. I can only enjoy the patch myself now
>>>
>> Yes, can you describe your use-case. CAN in U-BOOT, so far, was just
>> used to send or receive one or a few messages, mainly for testing purposes.
>>
>>
> what i want to do is something like a protocol gateway. It converts the
> data from one type to another.
> u-boot has support so many cpu/board/...., i thinks it can do much more
> tasks than just for testing purposes.
> It could be a non-OS based software plaform :)
Well, U-Boot is a bootloader and I strongly suggest to use Linux for
that purpose. Nevertheless, maybe a simple generic CAN framework could
be useful for both, normal testing purposes and your special app. Some
time ago I wrote a simple framework supporting the SJA100 and the
i82527. I will try to find it now.
Wolfgang.
^ permalink raw reply [flat|nested] 15+ messages in thread
* [U-Boot] [PATCH] add u-boot sja1000/can support
2009-10-24 4:17 [U-Boot] [PATCH] add u-boot sja1000/can support miaofng
` (3 preceding siblings ...)
2009-10-26 12:14 ` Wolfgang Grandegger
@ 2009-10-26 21:56 ` Wolfgang Denk
4 siblings, 0 replies; 15+ messages in thread
From: Wolfgang Denk @ 2009-10-26 21:56 UTC (permalink / raw)
To: u-boot
Dear "miaofng",
In message <200910241217470153391@gmail.com> you wrote:
> From 1f6aaba856fbf484c442eb33cf220774d57fba8d Mon Sep 17 00:00:00 2001
> From: miaofng <miaofng@gmail.com>
> Date: Fri, 23 Oct 2009 17:06:50 +0800
> Subject: [PATCH] [can] add u-boot sja1000/can support
>
> Signed-off-by: miaofng <miaofng@gmail.com>
Please provide a real name here and in all Copyright entries.
...
> diff --git a/drivers/can/can_core.c b/drivers/can/can_core.c
> new file mode 100755
> index 0000000..a723e8a
> --- /dev/null
> +++ b/drivers/can/can_core.c
> @@ -0,0 +1,266 @@
> +/*
> + * Copyright (C) 2009 miaofng<miaofng@gmail.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the version 2 of the GNU General Public License
> + * as published by the Free Software Foundation
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> + */
> +
> +#include <common.h>
> +#include <can.h>
> +#include <malloc.h>
> +
> +#define can_debug printf
Why not
#define can_debug debug
?
And why not use plain debug() in the first place?
> +#define can_error printf
What is this good for? I don't see "can_error" used anywhere?
> +#ifdef CONFIG_CMD_CAN
> +#ifndef CONFIG_CAN_DEV_MAX
> +#define CONFIG_CAN_DEV_MAX 8
> +#endif
> +
> +static struct can_device *can_devs[CONFIG_CAN_DEV_MAX];
> +#endif
> +
> +static inline struct can_device* index_to_cdev(int index)
> +{
> + return (index<CONFIG_CAN_DEV_MAX)? can_devs[index]:0;
> +}
> +
> +static inline int cdev_to_index(struct can_device *dev)
> +{
> + return (dev)?dev->index:-1;
> +}
> +
> +static void canif_tx(struct can_device *dev)
> +{
> + struct can_frame *cf;
> + int len;
> +
> + len = buf_pop(&dev->tbuf, (char*)&cf, sizeof(cf));
> + if(len == sizeof(cf)) {
> + dev->start_xmit(cf, dev);
> + free(cf);
> + }
> +}
This look like Linux code to me which is somewhat out of place in a
U-Boot context?
> +void canif_rx(struct can_frame *cf, struct can_device *dev)
> +{
> + int len;
> +
> + //error frame?
Please do not use any C++ comments. [Fix globally]
> + if(cf->can_id&CAN_ERR_FLAG)
> + {
Incorrect brace style. Please fix globally.
> + //error frame, drop it
> + free(cf);
> + return;
> + }
> +
> + //soft id filter?
> +
> + //store to cirbuf
> + if(dev->rbuf.size == dev->rbuf.totalsize) {
> + can_debug("CAN: rx buffer is full\n");
> + dev->stats.rx_dropped ++;
> + free(cf);
> + return;
> + }
> +
> + buf_push(&dev->rbuf, (char*)&cf, sizeof(cf));
> +}
> +
> +void canif_wake_queue(struct can_device *dev)
> +{
> + canif_start_queue(dev);
> + canif_tx(dev);
> +}
Are you sure we could need this in U-Boot? Keep in mind that U-Bootis
strictly single-tasking.
> +int can_init(void)
> +{
> +#ifdef CONFIG_CMD_CAN
> + int index;
> + for(index = 0; index < CONFIG_CAN_DEV_MAX; index ++) can_devs[index] = 0;
Incorrect indentation.
> + board_can_init();
> +#endif
> + return 0;
> +}
No can_init() should be performed at all (and thus not compiled
either) if CONFIG_CMD_CAN is not defined.
> +/*
> + * Register the CAN network device
> + */
> + #ifndef CONFIG_CAN_BUF_TX_SZ
> + #define CONFIG_CAN_BUF_TX_SZ (8*sizeof(void*))
> + #endif
> +
> + #ifndef CONFIG_CAN_BUF_RX_SZ
> + #define CONFIG_CAN_BUF_RX_SZ (8*sizeof(void*))
> + #endif
Please don't do this right in the middle of a source file. Move to
header.
> +int register_candev(struct can_device *dev)
> +{
> + int ret;
> + int index;
> +
> + //insert into the list
> + dev->index = -1;
> + for(index =0; index < CONFIG_CAN_DEV_MAX; index ++)
> + {
> + if(!can_devs[index]) {
> + can_devs[index] = dev;
> + dev->index = index;
> + break;
> + }
> + }
> + if( dev->index < 0)
> + can_debug("CAN: too many can devices\n");
> +
> + //allocate circbuf for tx and rx
> + ret = buf_init(&dev->tbuf, CONFIG_CAN_BUF_TX_SZ);
> + if(ret != 1) {
> + can_debug("CAN: cann't init cirbuf of tx\n");
> + can_devs[index] = 0;
> + return -1;
> + }
> + ret = buf_init(&dev->rbuf, CONFIG_CAN_BUF_RX_SZ);
> + if(ret != 1) {
> + can_debug("CAN: cann't init cirbuf of rx\n");
> + can_devs[index] = 0;
> + buf_free(&dev->tbuf);
> + return -1;
> + }
> + dev->qstatus = CAN_QUEUE_INIT;
> +
> + //success
> + printf("CAN: %s @index %d\n", dev->name, dev->index);
> + return 0;
> +}
Looks like overkill to me, and doesn;t seem to fit into U-Boot design
rules. Please see http://www.denx.de/wiki/U-Boot/DesignPrinciples
> +/*
> + * Unregister the CAN network device
> + */
> +void unregister_candev(struct can_device *dev)
> +{
> + int index = cdev_to_index(dev);
> +
> + if(index < 0) {
> + can_debug("CAN: invalid para\n");
> + return;
> + }
> +
> + //close the dev first
> + can_close((int)dev);
> +
> + //release tx/rx buffer
> + buf_free(&dev->tbuf);
> + buf_free(&dev->rbuf);
> +
> + //remove from the list
> + can_devs[index] = 0;
> +}
Ditto.
> +//api
> +int can_setbrg(int brg, int index)
> +{
> + struct can_device *dev = index_to_cdev(index);
> +
> + if(!dev) {
> + can_debug("CAN: invalid para\n");
> + return -1;
> + }
> +
> + if( dev->state != CAN_STATE_STOPPED) {
> + can_debug("CAN: invalid dev status<%d>\n", dev->state);
> + return -1;
> + }
> +
> + if(dev->setbrg)
> + return dev->setbrg(brg, dev);
> +
> + can_debug("CAN: op not supported by the dev\n");
> + return -1;
> +}
These error messages should be that, i. e. error messages, no debug.
And they could be a bit more self-explanatory. "op not supported" -
what's an "op"? Ans which "op" is not supported? Etc.
> +int can_open(int index)
> +{
> + struct can_device *dev = index_to_cdev(index);
> +
> + if(!dev) {
> + can_debug("CAN: invalid para\n");
> + return 0;
> + }
> +
> + if(dev->state != CAN_STATE_STOPPED) {
> + can_debug("CAN: invalid dev status<%d>\n", dev->state);
> + return 0;
> + }
> +
> + if(dev && dev->open) dev->open(dev);
> + return (int)dev;
> +}
> +
> +void can_close(int dev_id)
> +{
> + struct can_device *dev = (struct can_device*) dev_id;
> + struct can_frame *cf;
> +
> + if(!dev) {
> + can_debug("CAN: invalid para\n");
> + return;
> + }
> +
> + //can device close
> + if(dev->close) dev->close(dev);
> +
> + //tbuf,rbuf dump
> + while(buf_pop(&dev->tbuf, (char*)&cf, sizeof(cf)) ) free(cf);
> + while(buf_pop(&dev->rbuf, (char*)&cf, sizeof(cf)) ) free(cf);
> +}
Do we need this? In a single-threaded contxt?
> +//non block write
> +int can_send(struct can_frame *cf, int dev_id)
> +{
...
> +//non block read
> +struct can_frame* can_recv(int dev_id)
> +{
...
Please explain how you think this fits into U-Boot context, which is
single-threaded by design.
> diff --git a/include/candev.h b/include/candev.h
> new file mode 100755
> index 0000000..0e0dee7
> --- /dev/null
> +++ b/include/candev.h
...
> +/*
> + * netdev.h - definitions an prototypes for network devices
> + */
Inappropriate comment, it seems?
> diff --git a/lib_arm/board.c b/lib_arm/board.c
> old mode 100644
> new mode 100755
> index 5e3d7f6..aa11dd3
> --- a/lib_arm/board.c
> +++ b/lib_arm/board.c
> @@ -356,6 +356,8 @@ void start_armboot (void)
> serial_initialize();
> #endif
>
> + can_init();
> +
> /* IP Address */
> gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
Such a change would have to go into a separate patch.
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
365 Days of drinking Lo-Cal beer. = 1 Lite-year
^ permalink raw reply [flat|nested] 15+ messages in thread
* [U-Boot] Fw: Re: Re: [PATCH] add u-boot sja1000/can support
2009-10-26 8:47 ` [U-Boot] Fw: Re: " miaofng
2009-10-26 12:32 ` Wolfgang Grandegger
@ 2009-10-26 22:00 ` Wolfgang Denk
1 sibling, 0 replies; 15+ messages in thread
From: Wolfgang Denk @ 2009-10-26 22:00 UTC (permalink / raw)
To: u-boot
Dear "=?utf-8?B?bWlhb2ZuZw==?=",
In message <200910261647227347739@gmail.com> you wrote:
> Hi mike,
> It seems there's a big difference between my current project
> and u-boot common usage. I can only enjoy the patch myself now
>
> i want to get a packet from usb/network, then redirect it to can bus.
> So blocked write/read of can is not allowed.
>
> On Monday 26 October 2009 00:48:39 miaofng wrote:
> > Thanks for careful review. I'll resend the patch according to your remarks
> > except follwing: 1)
> >
> > > +int register_candev(struct can_device *dev)
> >
> > use "can" or "candev", dont mix the two
> >
> > answer: register_candev is origin from register_netdev(...). CAN is
> > something like network, it may has high level protocols such as open-can
> > and etc, so i want to keep that story.
> i know what CAN is. the Linux approach makes sense because they've
> architected CAN at the socket() layer, and all of the network layers are
> written with common coding style. but there is no such socket/network layer
Arghhhh...
Your quoting is as broken as your (missing or incorrect) In-reply-to:
and References: file headers. Please make sure to read
http://www.netmeister.org/news/learn2quote.html, and make sure not to
corrupt mail threads.
Thanks.
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
You can't have everything... where would you put it? - Steven Wright
^ permalink raw reply [flat|nested] 15+ messages in thread
* [U-Boot] Fw: Re: Re: [PATCH] add u-boot sja1000/can support
2009-10-26 13:29 ` miaofng
2009-10-26 14:44 ` Wolfgang Grandegger
@ 2009-10-26 22:03 ` Wolfgang Denk
1 sibling, 0 replies; 15+ messages in thread
From: Wolfgang Denk @ 2009-10-26 22:03 UTC (permalink / raw)
To: u-boot
Dear miaofng,
In message <4AE5A449.7040300@gmail.com> you wrote:
>
> what i want to do is something like a protocol gateway. It converts the
> data from one type to another.
Use an OS for this purpose. U-Boot is just a boot loader.
> u-boot has support so many cpu/board/...., i thinks it can do much more
> tasks than just for testing purposes.
> It could be a non-OS based software plaform :)
Yes, it can do that. You can also use a microscope to drive a nail
into a board. But neither U-Boot nor the microscope would be the
adequate tool for the respective purposes.
> > You have that working?
> >
> not yet. i have finished usb and can part.
Don't waste your time. Use an OS. Use Linux, where all this is
available abre ready for use now, without additional efforts.
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
Just because your doctor has a name for your condition doesn't mean
he knows what it is.
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2009-10-26 22:03 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-10-24 4:17 [U-Boot] [PATCH] add u-boot sja1000/can support miaofng
2009-10-24 6:35 ` Mike Frysinger
[not found] ` <200910261248270312273@gmail.com>
2009-10-26 7:02 ` Mike Frysinger
[not found] ` <200910261629132341038@gmail.com>
2009-10-26 8:41 ` Mike Frysinger
2009-10-26 13:01 ` miaofng
2009-10-26 8:47 ` [U-Boot] Fw: Re: " miaofng
2009-10-26 12:32 ` Wolfgang Grandegger
2009-10-26 13:29 ` miaofng
2009-10-26 14:44 ` Wolfgang Grandegger
2009-10-26 22:03 ` Wolfgang Denk
2009-10-26 22:00 ` Wolfgang Denk
2009-10-26 8:18 ` [U-Boot] " Matthias Fuchs
2009-10-26 12:14 ` Wolfgang Grandegger
2009-10-26 21:56 ` Wolfgang Denk
-- strict thread matches above, loose matches on Subject: below --
2009-10-26 5:39 miaofng
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox