--- /dev/null
+[PATCH 1/9] Socket-CAN: documentation for the device driver interface
+
+This patch documents the CAN netowrk device drivers interface, removes
+obsolete documentation and adds some useful links to CAN resources.
+
+Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
+---
+ Documentation/networking/can.txt | 194 ++++++++++++++++++++++++++++++++-------
+ 1 file changed, 160 insertions(+), 34 deletions(-)
+
+Index: net-next-2.6/Documentation/networking/can.txt
+===================================================================
+--- net-next-2.6.orig/Documentation/networking/can.txt
++++ net-next-2.6/Documentation/networking/can.txt
+@@ -36,10 +36,15 @@ This file contains
+ 6.2 local loopback of sent frames
+ 6.3 CAN controller hardware filters
+ 6.4 The virtual CAN driver (vcan)
+- 6.5 currently supported CAN hardware
+- 6.6 todo
++ 6.5 The CAN network device driver interface
++ 6.5.1 SYSFS files to set and get devices properties
++ 6.5.2 Setting the CAN bit-timing
++ 6.5.3 Starting and stopping the CAN network device
++ 6.6 supported CAN hardware
+
+- 7 Credits
++ 7 Socket CAN resources
++
++ 8 Credits
+
+ ============================================================================
+
+@@ -234,6 +239,8 @@ solution for a couple of reasons:
+ the user application using the common CAN filter mechanisms. Inside
+ this filter definition the (interested) type of errors may be
+ selected. The reception of error frames is disabled by default.
++ The format of the CAN error frame is briefly decribed in the Linux
++ header file "include/linux/can/error.h".
+
+ 4. How to use Socket CAN
+ ------------------------
+@@ -613,43 +620,160 @@ solution for a couple of reasons:
+ - Remove a (virtual CAN) network interface 'vcan42':
+ ip link del vcan42
+
+- The tool 'vcan' from the SocketCAN SVN repository on BerliOS is obsolete.
+-
+- Virtual CAN network device creation in older Kernels:
+- In Linux Kernel versions < 2.6.24 the vcan driver creates 4 vcan
+- netdevices at module load time by default. This value can be changed
+- with the module parameter 'numdev'. E.g. 'modprobe vcan numdev=8'
+-
+- 6.5 currently supported CAN hardware
+-
+- On the project website http://developer.berlios.de/projects/socketcan
+- there are different drivers available:
++ 6.5 The CAN network device driver interface
+
+- vcan: Virtual CAN interface driver (if no real hardware is available)
+- sja1000: Philips SJA1000 CAN controller (recommended)
+- i82527: Intel i82527 CAN controller
+- mscan: Motorola/Freescale CAN controller (e.g. inside SOC MPC5200)
+- ccan: CCAN controller core (e.g. inside SOC h7202)
+- slcan: For a bunch of CAN adaptors that are attached via a
+- serial line ASCII protocol (for serial / USB adaptors)
++ The CAN network device driver interface provides a generic interface
++ to setup, configure and monitor CAN network devices. The user can then
++ configure CAN devices, like setting the bit-timing parameters, through
++ SYSFS files. They are described in the following chapter. Furthermore,
++ the interface uses a common data structure and exports a set of common
++ functions, which all real CAN network device drivers should use.
++ Please have a look to the SJA1000 or MSCAN driver to understand how to
++ use them. The name of the module is can-dev.ko.
++
++ 6.5.1 SYSFS files to set and get devices properties
++
++ When the CAN device is registered, a set of SYSFS files is created in
++ "/sys/class/net/canX/". These files allow to set and get device
++ properties. Here is a list of the files and a brief explanation for
++ what they are good for:
++
++ can_state:
++ Returns the current state of the CAN controller: "active",
++ "stopped" or "sleeping" or the bus error states "bus-warn",
++ "bus-pass" or "bus-off". Please do not read it frequently.
++ State changes are also reported via CAN error frames and the
++ application should monitor and handle them instead (see also
++ chapter 3.4).
++
++ can_ctrlmode:
++ Allows to set various CAN controller modes like loop-back (0x1),
++ listen-only (0x2) or triple-sampling (0x4) by writing the
++ corresponding bit mask to this file.
++
++ can_echo:
++ Allows to read and toggle the local loop-back functionality of
++ the device. See chapter 6.2 for further information.
++
++ can_restart:
++ Writing to this file allows to manually trigger a restart of the
++ CAN controller in case of a bus-off condition.
++
++ can_restart_ms:
++ If greater than 0, a restart of the CAN controller will
++ automatically be triggered in case of a bus-off condition after
++ the specified delay in milliseconds. By default it's off.
++
++ can_bittiming:
++ Sub-directory with files to set and get CAN bit-timing
++ parameters.
++
++ can_bittiming/bitrate
++ can_bittiming/sample_point:
++ If calculation of CAN bit-timing parameters is enabled in the
++ kernel (CONFIG_CAN_CALC_BITTIMING=y), the bit-timing can be
++ defined by writing the bit-rate in bits/sec to "bitrate".
++ Otherwise the file is read-only and returns the actual bit-rate.
++ Accordingly the sample-point in one-tenth of a percent can be
++ set or read. By default it's set to 0 using CIA-recommended
++ sample-points.
++
++ can_bittiming/tq
++ can_bittiming/prop_seg
++ can_bittiming/phase_seg1
++ can_bittiming/phase_seg2
++ can_bittiming/sjw:
++ These files allow to define the CAN bit-timing in a hardware
++ independent format as proposed by the Bosch CAN 2.0
++ specification.
++
++ can_bittiming/hw_clock
++ can_bittiming/hw_brp_inc
++ can_bittiming/hw_brp_max
++ can_bittiming/hw_brp_min
++ can_bittiming/hw_sjw_max
++ can_bittiming/hw_tseg1_max
++ can_bittiming/hw_tseg1_min
++ can_bittiming/hw_tseg2_max
++ can_bittiming/hw_tseg2_min:
++ These read-only files list the bit-timing constants for this
++ device. They are provided by the CAN controller driver and are
++ used to calculate and check CAN bit-timing parameters.
++ Furthermore, these values can be used for user-defined
++ (non-standard) bit-timing calculation algorithms in userspace.
++
++ can_statistics
++ can_statistics/arbitration_lost
++ can_statistics/bus_error
++ can_statistics/data_overrun
++ can_statistics/error_passive
++ can_statistics/error_warning
++ can_statistics/restarts
++ can_statistics/wakeup:
++ These read-only files list CAN specific statistics values.
++
++ 6.5.2 Setting the CAN bit-timing
++
++ The CAN bit-timing parameters can always be specified in a hardware
++ independent format as proposed in the Bosch CAN 2.0 specification
++ using the SYSFS files "tq", "prop_seg", "phase_seg1", "phase_seg2"
++ and "sjw". The SYSFS files are described in the previous chapter.
++
++ If the kernel option CONFIG_CAN_CALC_BITTIMING is enabled, CIA
++ recommended CAN bit-timing parameters will be calculated for the bit-
++ rate written to the SYSFS file "bitrate" when the device gets started.
++ Note that this works fine for the most common CAN controllers with
++ standard bit-rates but may *fail* for exotic bit-rates or CAN source
++ clock frequencies. Disabling CONFIG_CAN_CALC_BITTIMING saves some
++ space and allows user space tools to solely determine and set the
++ bit-timing parameters. The CAN controller specific bit-timing
++ constants can be used for that purpose. They are available in the
++ SYSFS directory "can_bittiming" as well with the name prefix "hw_".
++
++ 6.5.3 Starting and stopping the CAN network device
++
++ A CAN network device is started and stopped as usual with the command
++ "ifconfig canX up" and "ifconfig canX down". Be aware that you *must*
++ define proper bit-timing parameters for real CAN devices before you
++ can start it to avoid error-prune default settings:
++
++ # echo 125000 > /sys/class/net/can0/can_bittiming/bitrate
++ # ifconfig can0 up
++
++ A device may enter "bus-off" state if too much errors occurred on the
++ CAN bus. Then no more messages can be received or sent. The SYSFS file
++ "/sys/class/net/can0/can_state" then reports "bus-off". An automatic
++ bus-off recovery can be enabled by writing the desired restart delay
++ in milliseconds to "/sys/class/net/canX/can_restart_ms".
++ Alternatively, the application may realize the "bus-off" condition
++ by monitoring CAN error frames and do a restart when appropriate by
++ writing to the SYSFS file /sys/class/net/canX/can_restart. Note that
++ a restart will also create a CAN error frame (see also chapter 3.4).
++
++ 6.6 Supported CAN hardware
++
++ Please check the "Kconfig" file in "drivers/net/can" to get an actual
++ list of the support CAN hardware. On the Socket CAN project website
++ (see chapter 7) there might be further drivers available, also for
++ older kernel versions.
++
++7. Socket CAN resources
++-----------------------
++
++ You can find further resources for Socket CAN like user space tools,
++ support for old kernel versions, more drivers, mailing lists, etc.
++ at the BerliOS OSS project website for Socket CAN:
+
+- Additionally the different CAN adaptors (ISA/PCI/PCMCIA/USB/Parport)
+- from PEAK Systemtechnik support the CAN netdevice driver model
+- since Linux driver v6.0: http://www.peak-system.com/linux/index.htm
++ http://developer.berlios.de/projects/socketcan
+
+- Please check the Mailing Lists on the berlios OSS project website.
++ If you have questions, bug fixes, etc., don't hesitate to post them to
++ the Socketcan-Users mailing list. But please search the archives first.
+
+- 6.6 todo
+-
+- The configuration interface for CAN network drivers is still an open
+- issue that has not been finalized in the socketcan project. Also the
+- idea of having a library module (candev.ko) that holds functions
+- that are needed by all CAN netdevices is not ready to ship.
+- Your contribution is welcome.
+-
+-7. Credits
++8. Credits
+ ----------
+
++ (?) More credits, of course!?
++
+ Oliver Hartkopp (PF_CAN core, filters, drivers, bcm)
+ Urs Thuermann (PF_CAN core, kernel integration, socket interfaces, raw, vcan)
+ Jan Kizka (RT-SocketCAN core, Socket-API reconciliation)
+@@ -663,3 +787,5 @@ solution for a couple of reasons:
+ Klaus Hitschler (PEAK driver integration)
+ Uwe Koppe (CAN netdevices with PF_PACKET approach)
+ Michael Schulze (driver layer loopback requirement, RT CAN drivers review)
++
++123456789012345678901234567890123456789012345678901234567890123456789012
--- /dev/null
+[PATCH 2/9] Socket-CAN: update MAINTAINERS and CREDITS file
+
+Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
+---
+ CREDITS | 5 +++++
+ MAINTAINERS | 9 +++++++++
+ 2 files changed, 14 insertions(+)
+
+Index: net-next-2.6/MAINTAINERS
+===================================================================
+--- net-next-2.6.orig/MAINTAINERS
++++ net-next-2.6/MAINTAINERS
+@@ -1055,6 +1055,15 @@ L: socketcan-core@lists.berlios.de (subs
+ W: http://developer.berlios.de/projects/socketcan/
+ S: Maintained
+
++CAN NETWORK DRIVERS
++P: Wolfgang Grandegger (preliminary!!!)
++M: wg@grandegger.com
++P: Oliver Hartkopp (preliminary!!!)
++M: oliver.hartkopp@volkswagen.de
++L: socketcan-core@lists.berlios.de (subscribers-only)
++W: http://developer.berlios.de/projects/socketcan/
++S: Maintained
++
+ CELL BROADBAND ENGINE ARCHITECTURE
+ P: Arnd Bergmann
+ M: arnd@arndb.de
+Index: net-next-2.6/CREDITS
+===================================================================
+--- net-next-2.6.orig/CREDITS
++++ net-next-2.6/CREDITS
+@@ -1248,6 +1248,10 @@ S: 8124 Constitution Apt. 7
+ S: Sterling Heights, Michigan 48313
+ S: USA
+
++N: Wolfgang Grandegger (preliminary!!!)
++E: wg@grandegger.com
++D: Controller Area Network (device drivers)
++
+ N: William Greathouse
+ E: wgreathouse@smva.com
+ E: wgreathouse@myfavoritei.com
+@@ -1376,6 +1380,7 @@ N: Oliver Hartkopp
+ E: oliver.hartkopp@volkswagen.de
+ W: http://www.volkswagen.de
+ D: Controller Area Network (network layer core)
++D: Controller Area Network (device drivers) (preliminary!!!)
+ S: Brieffach 1776
+ S: 38436 Wolfsburg
+ S: Germany
--- /dev/null
+[PATCH 3/9] Socket-CAN: add network device driver interface
+
+The CAN network device driver interface provides a generic interface to
+setup, configure and monitor CAN network devices. It exports a set of
+common data structures and functions, which all real CAN network device
+drivers should use. Please have a look to the SJA1000 or MSCAN driver
+to understand how to use them. The name of the module is can-dev.ko.
+
+For further information please check "Documentation/networking/can.txt"
+provided by the first patch of this series.
+
+Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
+---
+ drivers/net/can/Kconfig | 27 +-
+ drivers/net/can/Makefile | 5
+ drivers/net/can/dev.c | 523 +++++++++++++++++++++++++++++++++++++++++++++++
+ include/linux/can/dev.h | 136 ++++++++++++
+ 4 files changed, 684 insertions(+), 7 deletions(-)
+
+Index: net-next-2.6/drivers/net/can/Makefile
+===================================================================
+--- net-next-2.6.orig/drivers/net/can/Makefile
++++ net-next-2.6/drivers/net/can/Makefile
+@@ -3,3 +3,8 @@
+ #
+
+ obj-$(CONFIG_CAN_VCAN) += vcan.o
++
++obj-$(CONFIG_CAN_DEV) += can-dev.o
++can-dev-y := dev.o
++
++ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
+Index: net-next-2.6/drivers/net/can/dev.c
+===================================================================
+--- /dev/null
++++ net-next-2.6/drivers/net/can/dev.c
+@@ -0,0 +1,523 @@
++/*
++ * Copyright (C) 2005 Marc Kleine-Budde, Pengutronix
++ * Copyright (C) 2006 Andrey Volkov, Varma Electronics
++ * Copyright (C) 2008 Wolfgang Grandegger <wg@grandegger.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 <linux/module.h>
++#include <linux/netdevice.h>
++#include <linux/if_arp.h>
++#include <linux/can.h>
++#include <linux/can/dev.h>
++#include <net/rtnetlink.h>
++
++#define MOD_DESC "CAN device driver interface"
++
++MODULE_DESCRIPTION(MOD_DESC);
++MODULE_LICENSE("GPL v2");
++MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
++
++#ifdef CONFIG_CAN_CALC_BITTIMING
++#define CAN_CALC_MAX_ERROR 50 /* in one-tenth of a percent */
++
++/*
++ * Bit-timing calculation derived from:
++ *
++ * Code based on LinCAN sources and H8S2638 project
++ * Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz
++ * Copyright 2005 Stanislav Marek
++ * email: pisa@cmp.felk.cvut.cz
++ */
++static int can_update_spt(const struct can_bittiming_const *btc,
++ int sampl_pt, int tseg, int *tseg1, int *tseg2)
++{
++ *tseg2 = tseg + 1 - (sampl_pt * (tseg + 1)) / 1000;
++ if (*tseg2 < btc->tseg2_min)
++ *tseg2 = btc->tseg2_min;
++ if (*tseg2 > btc->tseg2_max)
++ *tseg2 = btc->tseg2_max;
++ *tseg1 = tseg - *tseg2;
++ if (*tseg1 > btc->tseg1_max) {
++ *tseg1 = btc->tseg1_max;
++ *tseg2 = tseg - *tseg1;
++ }
++ return 1000 * (tseg + 1 - *tseg2) / (tseg + 1);
++}
++
++static int can_calc_bittiming(struct net_device *dev)
++{
++ struct can_priv *priv = netdev_priv(dev);
++ struct can_bittiming *bt = &priv->bittiming;
++ const struct can_bittiming_const *btc = priv->bittiming_const;
++ long rate, best_rate = 0;
++ long best_error = 1000000000, error = 0;
++ int best_tseg = 0, best_brp = 0, brp = 0;
++ int tsegall, tseg = 0, tseg1 = 0, tseg2 = 0;
++ int spt_error = 1000, spt = 0, sampl_pt;
++ uint64_t v64;
++
++ if (!priv->bittiming_const)
++ return -ENOTSUPP;
++
++ /* Use CIA recommended sample points */
++ if (bt->sample_point) {
++ sampl_pt = bt->sample_point;
++ } else {
++ if (bt->bitrate > 800000)
++ sampl_pt = 750;
++ else if (bt->bitrate > 500000)
++ sampl_pt = 800;
++ else
++ sampl_pt = 875;
++ }
++
++ /* tseg even = round down, odd = round up */
++ for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1;
++ tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--) {
++ tsegall = 1 + tseg / 2;
++ /* Compute all possible tseg choices (tseg=tseg1+tseg2) */
++ brp = bt->clock / (tsegall * bt->bitrate) + tseg % 2;
++ /* chose brp step which is possible in system */
++ brp = (brp / btc->brp_inc) * btc->brp_inc;
++ if ((brp < btc->brp_min) || (brp > btc->brp_max))
++ continue;
++ rate = bt->clock / (brp * tsegall);
++ error = bt->bitrate - rate;
++ /* tseg brp biterror */
++ if (error < 0)
++ error = -error;
++ if (error > best_error)
++ continue;
++ best_error = error;
++ if (error == 0) {
++ spt = can_update_spt(btc, sampl_pt, tseg / 2,
++ &tseg1, &tseg2);
++ error = sampl_pt - spt;
++ if (error < 0)
++ error = -error;
++ if (error > spt_error)
++ continue;
++ spt_error = error;
++ }
++ best_tseg = tseg / 2;
++ best_brp = brp;
++ best_rate = rate;
++ if (error == 0)
++ break;
++ }
++
++ if (best_error) {
++ /* Error in one-tenth of a percent */
++ error = (best_error * 1000) / bt->bitrate;
++ if (error > CAN_CALC_MAX_ERROR) {
++ dev_err(ND2D(dev), "bitrate error %ld.%ld%% too high\n",
++ error / 10, error % 10);
++ return -EDOM;
++ } else {
++ dev_warn(ND2D(dev), "bitrate error %ld.%ld%%\n",
++ error / 10, error % 10);
++ }
++ }
++
++ spt = can_update_spt(btc, sampl_pt, best_tseg, &tseg1, &tseg2);
++
++ v64 = (u64)best_brp * 1000000000UL;
++ do_div(v64, bt->clock);
++ bt->tq = (u32)v64;
++ bt->prop_seg = tseg1 / 2;
++ bt->phase_seg1 = tseg1 - bt->prop_seg;
++ bt->phase_seg2 = tseg2;
++ bt->sjw = 1;
++ bt->brp = best_brp;
++
++ return 0;
++}
++#else /* !CONFIG_CAN_CALC_BITTIMING */
++static int can_calc_bittiming(struct net_device *dev)
++{
++ dev_err(ND2D(dev), "bit-timing calculation not available\n");
++ return -EINVAL;
++}
++#endif /* CONFIG_CAN_CALC_BITTIMING */
++
++int can_sample_point(struct can_bittiming *bt)
++{
++ return ((bt->prop_seg + bt->phase_seg1 + 1) * 1000) /
++ (bt->prop_seg + bt->phase_seg1 + bt->phase_seg2 + 1);
++}
++
++int can_fixup_bittiming(struct net_device *dev)
++{
++ struct can_priv *priv = netdev_priv(dev);
++ struct can_bittiming *bt = &priv->bittiming;
++ const struct can_bittiming_const *btc = priv->bittiming_const;
++ int tseg1, alltseg;
++ u32 bitrate;
++ u64 brp64;
++
++ if (!priv->bittiming_const)
++ return -ENOTSUPP;
++
++ tseg1 = bt->prop_seg + bt->phase_seg1;
++ if (bt->sjw > btc->sjw_max ||
++ tseg1 < btc->tseg1_min || tseg1 > btc->tseg1_max ||
++ bt->phase_seg2 < btc->tseg2_min || bt->phase_seg2 > btc->tseg2_max)
++ return -EINVAL;
++
++ brp64 = (u64)bt->clock * (u64)bt->tq;
++ if (btc->brp_inc > 1)
++ do_div(brp64, btc->brp_inc);
++ brp64 += 500000000UL - 1;
++ do_div(brp64, 1000000000UL); /* the practicable BRP */
++ if (btc->brp_inc > 1)
++ brp64 *= btc->brp_inc;
++ bt->brp = (u32)brp64;
++
++ if (bt->brp < btc->brp_min || bt->brp > btc->brp_max)
++ return -EINVAL;
++
++ alltseg = bt->prop_seg + bt->phase_seg1 + bt->phase_seg2 + 1;
++ bitrate = bt->clock / (bt->brp * alltseg);
++ bt->bitrate = bitrate;
++
++ return 0;
++}
++
++/*
++ * Set CAN bit-timing for the device
++ *
++ * This functions should be called in the open function of the device
++ * driver to determine, check and set appropriate bit-timing parameters.
++ */
++int can_set_bittiming(struct net_device *dev)
++{
++ struct can_priv *priv = netdev_priv(dev);
++ int err;
++
++ /* Check if bit-timing parameters have been pre-defined */
++ if (!priv->bittiming.tq && !priv->bittiming.bitrate) {
++ dev_err(ND2D(dev), "bit-timing not yet defined\n");
++ return -EINVAL;
++ }
++
++ /* Check if the CAN device has bit-timing parameters */
++ if (priv->bittiming_const) {
++
++ /* Check if bit-timing parameters have already been set */
++ if (priv->bittiming.tq && priv->bittiming.bitrate)
++ return 0;
++
++ /* Non-expert mode? Check if the bitrate has been pre-defined */
++ if (!priv->bittiming.tq)
++ /* Determine bit-timing parameters */
++ err = can_calc_bittiming(dev);
++ else
++ /* Check bit-timing params and calculate proper brp */
++ err = can_fixup_bittiming(dev);
++ if (err)
++ return err;
++ }
++
++ if (priv->do_set_bittiming) {
++ /* Finally, set the bit-timing registers */
++ err = priv->do_set_bittiming(dev);
++ if (err)
++ return err;
++ }
++
++ return 0;
++}
++EXPORT_SYMBOL(can_set_bittiming);
++
++static void can_setup(struct net_device *dev)
++{
++ dev->type = ARPHRD_CAN;
++ dev->mtu = sizeof(struct can_frame);
++ dev->hard_header_len = 0;
++ dev->addr_len = 0;
++ dev->tx_queue_len = 10;
++
++ /* New-style flags. */
++ dev->flags = IFF_NOARP;
++ dev->features = NETIF_F_NO_CSUM;
++}
++
++/*
++ * Allocate and setup space for the CAN network device
++ */
++struct net_device *alloc_candev(int sizeof_priv)
++{
++ struct net_device *dev;
++ struct can_priv *priv;
++
++ dev = alloc_netdev(sizeof_priv, "can%d", can_setup);
++ if (!dev)
++ return NULL;
++
++ priv = netdev_priv(dev);
++
++ priv->state = CAN_STATE_STOPPED;
++ spin_lock_init(&priv->irq_lock);
++
++ init_timer(&priv->timer);
++ priv->timer.expires = 0;
++
++ return dev;
++}
++EXPORT_SYMBOL(alloc_candev);
++
++/*
++ * Allocate space of the CAN network device
++ */
++void free_candev(struct net_device *dev)
++{
++ free_netdev(dev);
++}
++EXPORT_SYMBOL(free_candev);
++
++/*
++ * Register the CAN network device
++ */
++int register_candev(struct net_device *dev)
++{
++ int err;
++
++ err = register_netdev(dev);
++ if (err)
++ return err;
++
++ return 0;
++}
++EXPORT_SYMBOL(register_candev);
++
++/*
++ * Unregister the CAN network device
++ */
++void unregister_candev(struct net_device *dev)
++{
++ unregister_netdev(dev);
++}
++EXPORT_SYMBOL(unregister_candev);
++
++/*
++ * Local echo of CAN messages
++ *
++ * CAN network devices *should* support a local echo functionality
++ * (see Documentation/networking/can.txt). To test the handling of CAN
++ * interfaces that do not support the local echo both driver types are
++ * implemented. In the case that the driver does not support the echo
++ * the IFF_ECHO remains clear in dev->flags. This causes the PF_CAN core
++ * to perform the echo as a fallback solution.
++ */
++
++void can_flush_echo_skb(struct net_device *dev)
++{
++ struct can_priv *priv = netdev_priv(dev);
++ struct net_device_stats *stats = &dev->stats;
++ int i;
++
++ for (i = 0; i < CAN_ECHO_SKB_MAX; i++) {
++ if (priv->echo_skb[i]) {
++ kfree_skb(priv->echo_skb[i]);
++ priv->echo_skb[i] = NULL;
++ stats->tx_dropped++;
++ stats->tx_aborted_errors++;
++ }
++ }
++}
++
++/*
++ * Put the skb on the stack to be looped backed locally lateron
++ *
++ * The function is typically called in the start_xmit function
++ * of the device driver.
++ */
++void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, int idx)
++{
++ struct can_priv *priv = netdev_priv(dev);
++
++ /* set flag whether this packet has to be looped back */
++ if (!(dev->flags & IFF_ECHO) || skb->pkt_type != PACKET_LOOPBACK) {
++ kfree_skb(skb);
++ return;
++ }
++
++ if (!priv->echo_skb[idx]) {
++ struct sock *srcsk = skb->sk;
++
++ if (atomic_read(&skb->users) != 1) {
++ struct sk_buff *old_skb = skb;
++
++ skb = skb_clone(old_skb, GFP_ATOMIC);
++ kfree_skb(old_skb);
++ if (!skb)
++ return;
++ } else
++ skb_orphan(skb);
++
++ skb->sk = srcsk;
++
++ /* make settings for echo to reduce code in irq context */
++ skb->protocol = htons(ETH_P_CAN);
++ skb->pkt_type = PACKET_BROADCAST;
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
++ skb->dev = dev;
++
++ /* save this skb for tx interrupt echo handling */
++ priv->echo_skb[idx] = skb;
++ } else {
++ /* locking problem with netif_stop_queue() ?? */
++ printk(KERN_ERR "%s: %s: BUG! echo_skb is occupied!\n",
++ dev->name, __func__);
++ kfree_skb(skb);
++ }
++}
++EXPORT_SYMBOL(can_put_echo_skb);
++
++/*
++ * Get the skb from the stack and loop it back locally
++ *
++ * The function is typically called when the TX done interrupt
++ * is handled in the device driver.
++ */
++void can_get_echo_skb(struct net_device *dev, int idx)
++{
++ struct can_priv *priv = netdev_priv(dev);
++
++ if ((dev->flags & IFF_ECHO) && priv->echo_skb[idx]) {
++ netif_rx(priv->echo_skb[idx]);
++ priv->echo_skb[idx] = NULL;
++ }
++}
++EXPORT_SYMBOL(can_get_echo_skb);
++
++/*
++ * CAN device restart for bus-off recovery
++ */
++int can_restart_now(struct net_device *dev)
++{
++ struct can_priv *priv = netdev_priv(dev);
++ struct net_device_stats *stats = &dev->stats;
++ struct sk_buff *skb;
++ struct can_frame *cf;
++ int err;
++
++ if (netif_carrier_ok(dev))
++ netif_carrier_off(dev);
++
++ /* Cancel restart in progress */
++ if (priv->timer.expires) {
++ del_timer(&priv->timer);
++ priv->timer.expires = 0; /* mark inactive timer */
++ }
++
++ can_flush_echo_skb(dev);
++
++ err = priv->do_set_mode(dev, CAN_MODE_START);
++ if (err)
++ return err;
++
++ netif_carrier_on(dev);
++
++ dev_dbg(ND2D(dev), "restarted\n");
++ priv->can_stats.restarts++;
++
++ /* send restart message upstream */
++ skb = dev_alloc_skb(sizeof(struct can_frame));
++ if (skb == NULL)
++ return -ENOMEM;
++ skb->dev = dev;
++ skb->protocol = htons(ETH_P_CAN);
++ cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
++ memset(cf, 0, sizeof(struct can_frame));
++ cf->can_id = CAN_ERR_FLAG | CAN_ERR_RESTARTED;
++ cf->can_dlc = CAN_ERR_DLC;
++
++ netif_rx(skb);
++
++ dev->last_rx = jiffies;
++ stats->rx_packets++;
++ stats->rx_bytes += cf->can_dlc;
++
++ return 0;
++}
++
++static void can_restart_after(unsigned long data)
++{
++ struct net_device *dev = (struct net_device *)data;
++ struct can_priv *priv = netdev_priv(dev);
++
++ priv->timer.expires = 0; /* mark inactive timer */
++ can_restart_now(dev);
++}
++
++/*
++ * CAN bus-off
++ *
++ * This functions should be called when the device goes bus-off to
++ * tell the netif layer that no more packets can be sent or received.
++ * If enabled, a timer is started to trigger bus-off recovery.
++ */
++void can_bus_off(struct net_device *dev)
++{
++ struct can_priv *priv = netdev_priv(dev);
++
++ dev_dbg(ND2D(dev), "bus-off\n");
++
++ netif_carrier_off(dev);
++
++ if (priv->restart_ms > 0 && !priv->timer.expires) {
++
++ priv->timer.function = can_restart_after;
++ priv->timer.data = (unsigned long)dev;
++ priv->timer.expires =
++ jiffies + (priv->restart_ms * HZ) / 1000;
++ add_timer(&priv->timer);
++ }
++}
++EXPORT_SYMBOL(can_bus_off);
++
++/*
++ * Cleanup function before the device gets closed.
++ *
++ * This functions should be called in the close function of the device
++ * driver.
++ */
++void can_close_cleanup(struct net_device *dev)
++{
++ struct can_priv *priv = netdev_priv(dev);
++
++ if (priv->timer.expires) {
++ del_timer(&priv->timer);
++ priv->timer.expires = 0;
++ }
++
++ can_flush_echo_skb(dev);
++}
++EXPORT_SYMBOL(can_close_cleanup);
++
++static __init int can_dev_init(void)
++{
++ printk(KERN_INFO MOD_DESC "\n");
++
++ return 0;
++}
++module_init(can_dev_init);
++
++static __exit void can_dev_exit(void)
++{
++}
++module_exit(can_dev_exit);
+Index: net-next-2.6/include/linux/can/dev.h
+===================================================================
+--- /dev/null
++++ net-next-2.6/include/linux/can/dev.h
+@@ -0,0 +1,136 @@
++/*
++ * linux/can/dev.h
++ *
++ * Definitions for the CAN network device driver interface
++ *
++ * Copyright (C) 2006 Andrey Volkov <avolkov@varma-el.com>
++ * Varma Electronics Oy
++ *
++ * Copyright (C) 2008 Wolfgang Grandegger <wg@grandegger.com>
++ *
++ * Send feedback to <socketcan-users@lists.berlios.de>
++ */
++
++#ifndef CAN_DEV_H
++#define CAN_DEV_H
++
++#include <linux/can/error.h>
++
++/*
++ * CAN bitrate and bit-timing
++ */
++struct can_bittiming {
++ u32 bitrate;
++ u32 sample_point;
++ u32 tq;
++ u32 prop_seg;
++ u32 phase_seg1;
++ u32 phase_seg2;
++ u32 sjw;
++ u32 clock;
++ u32 brp;
++};
++
++struct can_bittiming_const {
++ u32 tseg1_min;
++ u32 tseg1_max;
++ u32 tseg2_min;
++ u32 tseg2_max;
++ u32 sjw_max;
++ u32 brp_min;
++ u32 brp_max;
++ u32 brp_inc;
++};
++
++/*
++ * CAN mode
++ */
++enum can_mode {
++ CAN_MODE_STOP = 0,
++ CAN_MODE_START,
++ CAN_MODE_SLEEP
++};
++
++/*
++ * CAN controller mode
++ */
++#define CAN_CTRLMODE_LOOPBACK 0x1
++#define CAN_CTRLMODE_LISTENONLY 0x2
++#define CAN_CTRLMODE_3_SAMPLES 0x4 /* Triple sampling mode */
++
++/*
++ * CAN operational and error states
++ */
++enum can_state {
++ CAN_STATE_ACTIVE = 0,
++ CAN_STATE_BUS_WARNING,
++ CAN_STATE_BUS_PASSIVE,
++ CAN_STATE_BUS_OFF,
++ CAN_STATE_STOPPED,
++ CAN_STATE_SLEEPING
++};
++
++/*
++ * CAN device statistics
++ */
++struct can_device_stats {
++ unsigned long error_warning;
++ unsigned long data_overrun;
++ unsigned long wakeup;
++ unsigned long bus_error;
++ unsigned long error_passive;
++ unsigned long arbitration_lost;
++ unsigned long restarts;
++ unsigned long bus_error_at_init;
++};
++
++/*
++ * CAN common private data
++ */
++#define CAN_ECHO_SKB_MAX 4
++
++struct can_priv {
++ struct can_device_stats can_stats;
++
++ struct can_bittiming bittiming;
++ struct can_bittiming_const *bittiming_const;
++
++ spinlock_t irq_lock;
++
++ enum can_state state;
++ u32 ctrlmode;
++
++ int restart_ms;
++ struct timer_list timer;
++
++ struct sk_buff *echo_skb[CAN_ECHO_SKB_MAX];
++
++ int (*do_set_bittiming)(struct net_device *dev);
++ int (*do_get_state)(struct net_device *dev, enum can_state *state);
++ int (*do_set_mode)(struct net_device *dev, enum can_mode mode);
++ int (*do_set_ctrlmode)(struct net_device *dev, u32 ctrlmode);
++ int (*do_get_ctrlmode)(struct net_device *dev, u32 *ctrlmode);
++};
++
++#define ND2D(_ndev) (_ndev->dev.parent)
++
++
++struct net_device *alloc_candev(int sizeof_priv);
++void free_candev(struct net_device *dev);
++int register_candev(struct net_device *dev);
++void unregister_candev(struct net_device *dev);
++
++int can_set_bittiming(struct net_device *dev);
++
++int can_restart_now(struct net_device *dev);
++
++void can_bus_off(struct net_device *dev);
++
++void can_close_cleanup(struct net_device *dev);
++
++void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, int idx);
++void can_get_echo_skb(struct net_device *dev, int idx);
++
++int can_sample_point(struct can_bittiming *bt);
++
++#endif /* CAN_DEV_H */
+Index: net-next-2.6/drivers/net/can/Kconfig
+===================================================================
+--- net-next-2.6.orig/drivers/net/can/Kconfig
++++ net-next-2.6/drivers/net/can/Kconfig
+@@ -12,14 +12,27 @@ config CAN_VCAN
+ This driver can also be built as a module. If so, the module
+ will be called vcan.
+
+-config CAN_DEBUG_DEVICES
+- bool "CAN devices debugging messages"
++config CAN_DEV
++ tristate "Platform CAN drivers with SYSFS support"
+ depends on CAN
+- default N
++ default Y
+ ---help---
+- Say Y here if you want the CAN device drivers to produce a bunch of
+- debug messages to the system log. Select this if you are having
+- a problem with CAN support and want to see more of what is going
+- on.
++ Enables the common framework for platform CAN drivers with SYSFS
++ support. This is the standard library for CAN drivers.
++ If unsure, say Y.
++
++config CAN_CALC_BITTIMING
++ bool "CAN bit-timing calculation"
++ depends on CAN_DEV
++ default Y
++ ---help---
++ If enabled, CAN bit-timing parameters will be calculated for the
++ bit-rate specified via SYSFS file "bitrate" when the device gets
++ started. This works fine for the most common CAN controllers
++ with standard bit-rates but may fail for exotic bit-rates or CAN
++ source clock frequencies. Disabling saves some space, but then the
++ bit-timing parameters must be specified directly using the SYSFS
++ files "tq", "prop_seg", "phase_seg1", "phase_seg2" and "sjw".
++ If unsure, say Y.
+
+ endmenu
--- /dev/null
+[PATCH 4/9] Socket-CAN: SYSFS interface to set and get device properties
+
+This patch adds SYSFS support to the CAN network device driver interface.
+When the CAN device is registered, a set of SYSFS files is created in
+"/sys/class/net/canX/". These files allow to set and get device
+properties like bit-timing parameters, state, controller mode and CAN
+statistics.
+
+For further information please check "Documentation/networking/can.txt"
+provided by the first patch of this series.
+
+Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
+---
+ drivers/net/can/Makefile | 2
+ drivers/net/can/dev.c | 8
+ drivers/net/can/sysfs.c | 509 +++++++++++++++++++++++++++++++++++++++++++++++
+ drivers/net/can/sysfs.h | 24 ++
+ 4 files changed, 542 insertions(+), 1 deletion(-)
+
+Index: net-next-2.6/drivers/net/can/dev.c
+===================================================================
+--- net-next-2.6.orig/drivers/net/can/dev.c
++++ net-next-2.6/drivers/net/can/dev.c
+@@ -24,6 +24,8 @@
+ #include <linux/can/dev.h>
+ #include <net/rtnetlink.h>
+
++#include "sysfs.h"
++
+ #define MOD_DESC "CAN device driver interface"
+
+ MODULE_DESCRIPTION(MOD_DESC);
+@@ -299,6 +301,9 @@ int register_candev(struct net_device *d
+ if (err)
+ return err;
+
++#ifdef CONFIG_SYSFS
++ can_create_sysfs(dev);
++#endif
+ return 0;
+ }
+ EXPORT_SYMBOL(register_candev);
+@@ -308,6 +313,9 @@ EXPORT_SYMBOL(register_candev);
+ */
+ void unregister_candev(struct net_device *dev)
+ {
++#ifdef CONFIG_SYSFS
++ can_remove_sysfs(dev);
++#endif
+ unregister_netdev(dev);
+ }
+ EXPORT_SYMBOL(unregister_candev);
+Index: net-next-2.6/drivers/net/can/sysfs.c
+===================================================================
+--- /dev/null
++++ net-next-2.6/drivers/net/can/sysfs.c
+@@ -0,0 +1,509 @@
++/*
++ * Copyright (C) 2007-2008 Wolfgang Grandegger <wg@grandegger.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 <linux/capability.h>
++#include <linux/kernel.h>
++#include <linux/netdevice.h>
++#include <linux/if_arp.h>
++#include <net/sock.h>
++#include <linux/rtnetlink.h>
++
++#include <linux/can.h>
++#include <linux/can/dev.h>
++
++#include "sysfs.h"
++
++#ifdef CONFIG_SYSFS
++
++/*
++ * SYSFS access functions and attributes. Use same locking as
++ * net/core/net-sysfs.c does.
++ */
++static inline int dev_isalive(const struct net_device *dev)
++{
++ return dev->reg_state <= NETREG_REGISTERED;
++}
++
++/* use same locking rules as GIF* ioctl's */
++static ssize_t can_dev_show(struct device *d,
++ struct device_attribute *attr, char *buf,
++ ssize_t (*fmt)(struct net_device *, char *))
++{
++ struct net_device *dev = to_net_dev(d);
++ ssize_t ret = -EINVAL;
++
++ read_lock(&dev_base_lock);
++ if (dev_isalive(dev))
++ ret = (*fmt)(dev, buf);
++ read_unlock(&dev_base_lock);
++
++ return ret;
++}
++
++/* generate a show function for simple field */
++#define CAN_DEV_SHOW(field, fmt_string) \
++static ssize_t fmt_can_##field(struct net_device *dev, char *buf) \
++{ \
++ struct can_priv *priv = netdev_priv(dev); \
++ return sprintf(buf, fmt_string, priv->field); \
++} \
++static ssize_t show_can_##field(struct device *d, \
++ struct device_attribute *attr, \
++ char *buf) \
++{ \
++ return can_dev_show(d, attr, buf, fmt_can_##field); \
++}
++
++/* use same locking and permission rules as SIF* ioctl's */
++static ssize_t can_dev_store(struct device *d, struct device_attribute *attr,
++ const char *buf, size_t len,
++ int (*set)(struct net_device *, unsigned long))
++{
++ struct net_device *dev = to_net_dev(d);
++ unsigned long new;
++ int ret = -EINVAL;
++
++ if (!capable(CAP_NET_ADMIN))
++ return -EPERM;
++
++ ret = strict_strtoul(buf, 0, &new);
++ if (ret)
++ goto out;
++
++ rtnl_lock();
++ if (dev_isalive(dev)) {
++ ret = (*set)(dev, new);
++ if (!ret)
++ ret = len;
++ }
++ rtnl_unlock();
++out:
++ return ret;
++}
++
++#define CAN_CREATE_FILE(_dev, _name) \
++ if (device_create_file(&_dev->dev, &dev_attr_##_name)) \
++ dev_err(ND2D(_dev), \
++ "Couldn't create device file for ##_name\n")
++
++#define CAN_REMOVE_FILE(_dev, _name) \
++ device_remove_file(&_dev->dev, &dev_attr_##_name) \
++
++CAN_DEV_SHOW(ctrlmode, "0x%x\n");
++
++static int change_can_ctrlmode(struct net_device *dev, unsigned long ctrlmode)
++{
++ struct can_priv *priv = netdev_priv(dev);
++ int err = 0;
++
++ if (priv->state != CAN_STATE_STOPPED)
++ return -EBUSY;
++
++ if (priv->do_set_ctrlmode)
++ err = priv->do_set_ctrlmode(dev, ctrlmode);
++
++ if (!err)
++ priv->ctrlmode = ctrlmode;
++
++ return err;
++}
++
++static ssize_t store_can_ctrlmode(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t len)
++{
++ return can_dev_store(dev, attr, buf, len, change_can_ctrlmode);
++}
++
++static DEVICE_ATTR(can_ctrlmode, S_IRUGO | S_IWUSR,
++ show_can_ctrlmode, store_can_ctrlmode);
++
++static const char *can_state_names[] = {
++ "active", "bus-warn", "bus-pass" , "bus-off",
++ "stopped", "sleeping", "unkown"
++};
++
++static ssize_t printf_can_state(struct net_device *dev, char *buf)
++{
++ struct can_priv *priv = netdev_priv(dev);
++ enum can_state state;
++ int err = 0;
++
++ if (priv->do_get_state) {
++ err = priv->do_get_state(dev, &state);
++ if (err)
++ goto out;
++ priv->state = state;
++ } else
++ state = priv->state;
++
++ if (state >= ARRAY_SIZE(can_state_names))
++ state = ARRAY_SIZE(can_state_names) - 1;
++ err = sprintf(buf, "%s\n", can_state_names[state]);
++out:
++ return err;
++}
++
++static ssize_t show_can_state(struct device *d,
++ struct device_attribute *attr, char *buf)
++{
++ return can_dev_show(d, attr, buf, printf_can_state);
++}
++
++static DEVICE_ATTR(can_state, S_IRUGO, show_can_state, NULL);
++
++CAN_DEV_SHOW(restart_ms, "%d\n");
++
++static int change_can_restart_ms(struct net_device *dev, unsigned long ms)
++{
++ struct can_priv *priv = netdev_priv(dev);
++
++ if (priv->restart_ms < 0)
++ return -EOPNOTSUPP;
++ priv->restart_ms = ms;
++ return 0;
++}
++
++static ssize_t store_can_restart_ms(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t len)
++{
++ return can_dev_store(dev, attr, buf, len, change_can_restart_ms);
++}
++
++static DEVICE_ATTR(can_restart_ms, S_IRUGO | S_IWUSR,
++ show_can_restart_ms, store_can_restart_ms);
++
++static ssize_t printf_can_echo(struct net_device *dev, char *buf)
++{
++ return sprintf(buf, "%d\n", dev->flags & IFF_ECHO ? 1 : 0);
++}
++
++static ssize_t show_can_echo(struct device *d,
++ struct device_attribute *attr, char *buf)
++{
++ return can_dev_show(d, attr, buf, printf_can_echo);
++}
++
++static int change_can_echo(struct net_device *dev, unsigned long on)
++{
++ if (on)
++ dev->flags |= IFF_ECHO;
++ else
++ dev->flags &= ~IFF_ECHO;
++ return 0;
++}
++
++static ssize_t store_can_echo(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t len)
++{
++ return can_dev_store(dev, attr, buf, len, change_can_echo);
++}
++
++static DEVICE_ATTR(can_echo, S_IRUGO | S_IWUSR, show_can_echo, store_can_echo);
++
++static int change_can_restart(struct net_device *dev, unsigned long on)
++{
++ return can_restart_now(dev);
++}
++
++static ssize_t store_can_restart(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t len)
++{
++ return can_dev_store(dev, attr, buf, len, change_can_restart);
++}
++
++static DEVICE_ATTR(can_restart, S_IWUSR, NULL, store_can_restart);
++
++/* Show a given attribute if the CAN bittiming group */
++static ssize_t can_btc_show(const struct device *d,
++ struct device_attribute *attr, char *buf,
++ unsigned long offset)
++{
++ struct net_device *dev = to_net_dev(d);
++ struct can_priv *priv = netdev_priv(dev);
++ struct can_bittiming_const *btc = priv->bittiming_const;
++ ssize_t ret = -EINVAL;
++
++ WARN_ON(offset >= sizeof(struct can_bittiming_const) ||
++ offset % sizeof(u32) != 0);
++
++ read_lock(&dev_base_lock);
++ if (dev_isalive(dev) && btc)
++ ret = sprintf(buf, "%d\n",
++ *(u32 *)(((u8 *)btc) + offset));
++
++ read_unlock(&dev_base_lock);
++ return ret;
++}
++
++/* Generate a read-only bittiming const attribute */
++#define CAN_BT_CONST_ENTRY(name) \
++static ssize_t show_##name(struct device *d, \
++ struct device_attribute *attr, char *buf) \
++{ \
++ return can_btc_show(d, attr, buf, \
++ offsetof(struct can_bittiming_const, name));\
++} \
++static DEVICE_ATTR(hw_##name, S_IRUGO, show_##name, NULL)
++
++CAN_BT_CONST_ENTRY(tseg1_min);
++CAN_BT_CONST_ENTRY(tseg1_max);
++CAN_BT_CONST_ENTRY(tseg2_min);
++CAN_BT_CONST_ENTRY(tseg2_max);
++CAN_BT_CONST_ENTRY(sjw_max);
++CAN_BT_CONST_ENTRY(brp_min);
++CAN_BT_CONST_ENTRY(brp_max);
++CAN_BT_CONST_ENTRY(brp_inc);
++
++static ssize_t can_bt_show(const struct device *d,
++ struct device_attribute *attr, char *buf,
++ unsigned long offset)
++{
++ struct net_device *dev = to_net_dev(d);
++ struct can_priv *priv = netdev_priv(dev);
++ struct can_bittiming *bt = &priv->bittiming;
++ ssize_t ret = -EINVAL;
++ u32 *ptr, val;
++
++ WARN_ON(offset >= sizeof(struct can_bittiming) ||
++ offset % sizeof(u32) != 0);
++
++ read_lock(&dev_base_lock);
++ if (dev_isalive(dev)) {
++ ptr = (u32 *)(((u8 *)bt) + offset);
++ if (ptr == &bt->sample_point &&
++ priv->state != CAN_STATE_STOPPED)
++ val = can_sample_point(bt);
++ else
++ val = *ptr;
++ ret = sprintf(buf, "%d\n", val);
++ }
++ read_unlock(&dev_base_lock);
++ return ret;
++}
++
++static ssize_t can_bt_store(const struct device *d,
++ struct device_attribute *attr,
++ const char *buf, size_t count,
++ unsigned long offset)
++{
++ struct net_device *dev = to_net_dev(d);
++ struct can_priv *priv = netdev_priv(dev);
++ struct can_bittiming *bt = &priv->bittiming;
++ unsigned long new;
++ ssize_t ret = -EINVAL;
++ u32 *ptr;
++
++ if (priv->state != CAN_STATE_STOPPED)
++ return -EBUSY;
++
++ WARN_ON(offset >= sizeof(struct can_bittiming) ||
++ offset % sizeof(u32) != 0);
++
++ ret = strict_strtoul(buf, 0, &new);
++ if (ret)
++ goto out;
++
++ ptr = (u32 *)(((u8 *)bt) + offset);
++ rtnl_lock();
++ if (dev_isalive(dev)) {
++ *ptr = (u32)new;
++
++ if ((ptr == &bt->bitrate) || (ptr == &bt->sample_point)) {
++ bt->tq = 0;
++ bt->brp = 0;
++ bt->sjw = 0;
++ bt->prop_seg = 0;
++ bt->phase_seg1 = 0;
++ bt->phase_seg2 = 0;
++ } else {
++ bt->bitrate = 0;
++ bt->sample_point = 0;
++ }
++ ret = count;
++ }
++ rtnl_unlock();
++out:
++ return ret;
++}
++
++#define CAN_BT_ENTRY_RO(name) \
++static ssize_t show_##name(struct device *d, \
++ struct device_attribute *attr, char *buf) \
++{ \
++ return can_bt_show(d, attr, buf, \
++ offsetof(struct can_bittiming, name)); \
++} \
++static DEVICE_ATTR(hw_##name, S_IRUGO, show_##name, NULL)
++
++CAN_BT_ENTRY_RO(clock);
++
++#define CAN_BT_ENTRY(name) \
++static ssize_t show_##name(struct device *d, \
++ struct device_attribute *attr, char *buf) \
++{ \
++ return can_bt_show(d, attr, buf, \
++ offsetof(struct can_bittiming, name)); \
++} \
++static ssize_t store_##name(struct device *d, \
++ struct device_attribute *attr, \
++ const char *buf, size_t count) \
++{ \
++ return can_bt_store(d, attr, buf, count, \
++ offsetof(struct can_bittiming, name)); \
++} \
++static DEVICE_ATTR(name, S_IRUGO | S_IWUSR, show_##name, store_##name)
++
++CAN_BT_ENTRY(bitrate);
++CAN_BT_ENTRY(sample_point);
++CAN_BT_ENTRY(tq);
++CAN_BT_ENTRY(prop_seg);
++CAN_BT_ENTRY(phase_seg1);
++CAN_BT_ENTRY(phase_seg2);
++CAN_BT_ENTRY(sjw);
++
++static struct attribute *can_bittiming_attrs[] = {
++ &dev_attr_hw_tseg1_min.attr,
++ &dev_attr_hw_tseg1_max.attr,
++ &dev_attr_hw_tseg2_max.attr,
++ &dev_attr_hw_tseg2_min.attr,
++ &dev_attr_hw_sjw_max.attr,
++ &dev_attr_hw_brp_min.attr,
++ &dev_attr_hw_brp_max.attr,
++ &dev_attr_hw_brp_inc.attr,
++ &dev_attr_hw_clock.attr,
++ &dev_attr_bitrate.attr,
++ &dev_attr_sample_point.attr,
++ &dev_attr_tq.attr,
++ &dev_attr_prop_seg.attr,
++ &dev_attr_phase_seg1.attr,
++ &dev_attr_phase_seg2.attr,
++ &dev_attr_sjw.attr,
++ NULL
++};
++
++static struct attribute_group can_bittiming_group = {
++ .name = "can_bittiming",
++ .attrs = can_bittiming_attrs,
++};
++
++/* Show a given attribute in the CAN statistics group */
++static ssize_t can_stat_show(const struct device *d,
++ struct device_attribute *attr, char *buf,
++ unsigned long offset)
++{
++ struct net_device *dev = to_net_dev(d);
++ struct can_priv *priv = netdev_priv(dev);
++ struct can_device_stats *stats = &priv->can_stats;
++ ssize_t ret = -EINVAL;
++
++ WARN_ON(offset >= sizeof(struct can_device_stats) ||
++ offset % sizeof(unsigned long) != 0);
++
++ read_lock(&dev_base_lock);
++ if (dev_isalive(dev))
++ ret = sprintf(buf, "%ld\n",
++ *(unsigned long *)(((u8 *)stats) + offset));
++
++ read_unlock(&dev_base_lock);
++ return ret;
++}
++
++/* Generate a read-only CAN statistics attribute */
++#define CAN_STAT_ENTRY(name) \
++static ssize_t show_##name(struct device *d, \
++ struct device_attribute *attr, char *buf) \
++{ \
++ return can_stat_show(d, attr, buf, \
++ offsetof(struct can_device_stats, name)); \
++} \
++static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
++
++CAN_STAT_ENTRY(error_warning);
++CAN_STAT_ENTRY(error_passive);
++CAN_STAT_ENTRY(bus_error);
++CAN_STAT_ENTRY(arbitration_lost);
++CAN_STAT_ENTRY(data_overrun);
++CAN_STAT_ENTRY(wakeup);
++CAN_STAT_ENTRY(restarts);
++
++static struct attribute *can_statistics_attrs[] = {
++ &dev_attr_error_warning.attr,
++ &dev_attr_error_passive.attr,
++ &dev_attr_bus_error.attr,
++ &dev_attr_arbitration_lost.attr,
++ &dev_attr_data_overrun.attr,
++ &dev_attr_wakeup.attr,
++ &dev_attr_restarts.attr,
++ NULL
++};
++
++static struct attribute_group can_statistics_group = {
++ .name = "can_statistics",
++ .attrs = can_statistics_attrs,
++};
++
++void can_create_sysfs(struct net_device *dev)
++{
++ struct can_priv *priv = netdev_priv(dev);
++ int err;
++
++ CAN_CREATE_FILE(dev, can_ctrlmode);
++ CAN_CREATE_FILE(dev, can_echo);
++ CAN_CREATE_FILE(dev, can_restart);
++ CAN_CREATE_FILE(dev, can_state);
++ CAN_CREATE_FILE(dev, can_restart_ms);
++
++ err = sysfs_create_group(&(dev->dev.kobj),
++ &can_statistics_group);
++ if (err) {
++ printk(KERN_EMERG
++ "couldn't create sysfs group for CAN statistics\n");
++ }
++
++ if (priv->bittiming_const) {
++ err = sysfs_create_group(&(dev->dev.kobj),
++ &can_bittiming_group);
++ if (err) {
++ printk(KERN_EMERG "couldn't create sysfs "
++ "group for CAN bittiming\n");
++ }
++ }
++}
++
++void can_remove_sysfs(struct net_device *dev)
++{
++ struct can_priv *priv = netdev_priv(dev);
++
++ CAN_REMOVE_FILE(dev, can_ctrlmode);
++ CAN_REMOVE_FILE(dev, can_echo);
++ CAN_REMOVE_FILE(dev, can_state);
++ CAN_REMOVE_FILE(dev, can_restart);
++ CAN_REMOVE_FILE(dev, can_restart_ms);
++
++ sysfs_remove_group(&(dev->dev.kobj), &can_statistics_group);
++ if (priv->bittiming_const)
++ sysfs_remove_group(&(dev->dev.kobj), &can_bittiming_group);
++}
++
++#endif /* CONFIG_SYSFS */
++
++
++
+Index: net-next-2.6/drivers/net/can/sysfs.h
+===================================================================
+--- /dev/null
++++ net-next-2.6/drivers/net/can/sysfs.h
+@@ -0,0 +1,24 @@
++/*
++ * Copyright (C) 2007 Wolfgang Grandegger <wg@grandegger.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
++ */
++
++#ifndef CAN_SYSFS_H
++#define CAN_SYSFS_H
++
++void can_create_sysfs(struct net_device *dev);
++void can_remove_sysfs(struct net_device *dev);
++
++#endif /* CAN_SYSFS_H */
+Index: net-next-2.6/drivers/net/can/Makefile
+===================================================================
+--- net-next-2.6.orig/drivers/net/can/Makefile
++++ net-next-2.6/drivers/net/can/Makefile
+@@ -5,6 +5,6 @@
+ obj-$(CONFIG_CAN_VCAN) += vcan.o
+
+ obj-$(CONFIG_CAN_DEV) += can-dev.o
+-can-dev-y := dev.o
++can-dev-y := dev.o sysfs.o
+
+ ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
--- /dev/null
+[PATCH 5/9] Socket-CAN: driver for the SJA1000 CAN controller
+
+This patch adds the generic Socket-CAN driver for the Philips SJA1000
+full CAN controller.
+
+Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
+---
+ drivers/net/can/Kconfig | 11
+ drivers/net/can/Makefile | 2
+ drivers/net/can/sja1000/Makefile | 7
+ drivers/net/can/sja1000/sja1000.c | 678 ++++++++++++++++++++++++++++++++++++++
+ drivers/net/can/sja1000/sja1000.h | 182 ++++++++++
+ 5 files changed, 880 insertions(+)
+
+Index: net-next-2.6/drivers/net/can/sja1000/sja1000.c
+===================================================================
+--- /dev/null
++++ net-next-2.6/drivers/net/can/sja1000/sja1000.c
+@@ -0,0 +1,678 @@
++/*
++ * sja1000.c - Philips SJA1000 network device driver
++ *
++ * 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 <linux/module.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/types.h>
++#include <linux/fcntl.h>
++#include <linux/interrupt.h>
++#include <linux/ptrace.h>
++#include <linux/string.h>
++#include <linux/errno.h>
++#include <linux/netdevice.h>
++#include <linux/if_arp.h>
++#include <linux/if_ether.h>
++#include <linux/skbuff.h>
++#include <linux/delay.h>
++
++#include <linux/can.h>
++#include <linux/can/dev.h>
++#include <linux/can/error.h>
++#include <linux/can/dev.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");
++
++static struct can_bittiming_const sja1000_bittiming_const = {
++ .tseg1_min = 1,
++ .tseg1_max = 16,
++ .tseg2_min = 1,
++ .tseg2_max = 8,
++ .sjw_max = 4,
++ .brp_min = 1,
++ .brp_max = 64,
++ .brp_inc = 1,
++};
++
++static int sja1000_probe_chip(struct net_device *dev)
++{
++ struct sja1000_priv *priv = netdev_priv(dev);
++
++ if (dev->base_addr && (priv->read_reg(dev, 0) == 0xFF)) {
++ printk(KERN_INFO "%s: probing @0x%lX failed\n",
++ DRV_NAME, dev->base_addr);
++ return 0;
++ }
++ return 1;
++}
++
++int set_reset_mode(struct net_device *dev)
++{
++ struct sja1000_priv *priv = netdev_priv(dev);
++ unsigned char status = priv->read_reg(dev, REG_MOD);
++ int i;
++
++ /* disable interrupts */
++ priv->write_reg(dev, 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(dev, REG_MOD, MOD_RM); /* reset chip */
++ status = priv->read_reg(dev, REG_MOD);
++ udelay(10);
++ }
++
++ dev_err(ND2D(dev), "setting SJA1000 into reset mode failed!\n");
++ return 1;
++
++}
++
++static int set_normal_mode(struct net_device *dev)
++{
++ struct sja1000_priv *priv = netdev_priv(dev);
++ unsigned char status = priv->read_reg(dev, REG_MOD);
++ int i;
++
++ for (i = 0; i < 100; i++) {
++ /* check reset bit */
++ if ((status & MOD_RM) == 0) {
++ priv->can.state = CAN_STATE_ACTIVE;
++ /* enable all interrupts */
++ priv->write_reg(dev, REG_IER, IRQ_ALL);
++
++ return 0;
++ }
++
++ /* set chip to normal mode */
++ priv->write_reg(dev, REG_MOD, 0x00);
++ status = priv->read_reg(dev, REG_MOD);
++ udelay(10);
++ }
++
++ dev_err(ND2D(dev), "setting SJA1000 into normal mode failed!\n");
++ return 1;
++
++}
++
++static void sja1000_start(struct net_device *dev)
++{
++ struct sja1000_priv *priv = netdev_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(dev, REG_TXERR, 0x0);
++ priv->write_reg(dev, REG_RXERR, 0x0);
++ priv->read_reg(dev, REG_ECC);
++
++ /* leave reset mode */
++ set_normal_mode(dev);
++}
++
++static int sja1000_set_mode(struct net_device *dev, enum can_mode mode)
++{
++ struct sja1000_priv *priv = netdev_priv(dev);
++
++ switch (mode) {
++ case CAN_MODE_START:
++ if (!priv->open_time)
++ return -EINVAL;
++
++ sja1000_start(dev);
++ if (netif_queue_stopped(dev))
++ netif_wake_queue(dev);
++ break;
++
++ default:
++ return -EOPNOTSUPP;
++ }
++
++ return 0;
++}
++
++static int sja1000_get_state(struct net_device *dev, enum can_state *state)
++{
++ struct sja1000_priv *priv = netdev_priv(dev);
++ u8 status;
++
++ /* FIXME: inspecting the status register to get the current state
++ * is not really necessary, because state changes are handled by
++ * in the ISR and the variable priv->can.state gets updated. The
++ * CAN devicde interface needs fixing!
++ */
++
++ spin_lock_irq(&priv->can.irq_lock);
++
++ if (priv->can.state == CAN_STATE_STOPPED) {
++ *state = CAN_STATE_STOPPED;
++ } else {
++ status = priv->read_reg(dev, REG_SR);
++ if (status & SR_BS)
++ *state = CAN_STATE_BUS_OFF;
++ else if (status & SR_ES) {
++ if (priv->read_reg(dev, REG_TXERR) > 127 ||
++ priv->read_reg(dev, REG_RXERR) > 127)
++ *state = CAN_STATE_BUS_PASSIVE;
++ else
++ *state = CAN_STATE_BUS_WARNING;
++ } else
++ *state = CAN_STATE_ACTIVE;
++ }
++ /* Check state */
++ if (*state != priv->can.state)
++ dev_err(ND2D(dev),
++ "Oops, state mismatch: hard %d != soft %d\n",
++ *state, priv->can.state);
++ spin_unlock_irq(&priv->can.irq_lock);
++ return 0;
++}
++
++static int sja1000_set_bittiming(struct net_device *dev)
++{
++ struct sja1000_priv *priv = netdev_priv(dev);
++ struct can_bittiming *bt = &priv->can.bittiming;
++ u8 btr0, btr1;
++
++ btr0 = ((bt->brp - 1) & 0x3f) | (((bt->sjw - 1) & 0x3) << 6);
++ btr1 = ((bt->prop_seg + bt->phase_seg1 - 1) & 0xf) |
++ (((bt->phase_seg2 - 1) & 0x7) << 4) |
++ ((priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) << 7);
++
++ dev_info(ND2D(dev), "setting BTR0=0x%02x BTR1=0x%02x\n", btr0, btr1);
++
++ priv->write_reg(dev, REG_BTR0, btr0);
++ priv->write_reg(dev, 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 net_device *dev)
++{
++ struct sja1000_priv *priv = netdev_priv(dev);
++
++ /* set clock divider and output control register */
++ priv->write_reg(dev, REG_CDR, priv->cdr | CDR_PELICAN);
++
++ /* set acceptance filter (accept all) */
++ priv->write_reg(dev, REG_ACCC0, 0x00);
++ priv->write_reg(dev, REG_ACCC1, 0x00);
++ priv->write_reg(dev, REG_ACCC2, 0x00);
++ priv->write_reg(dev, REG_ACCC3, 0x00);
++
++ priv->write_reg(dev, REG_ACCM0, 0xFF);
++ priv->write_reg(dev, REG_ACCM1, 0xFF);
++ priv->write_reg(dev, REG_ACCM2, 0xFF);
++ priv->write_reg(dev, REG_ACCM3, 0xFF);
++
++ priv->write_reg(dev, REG_OCR, priv->ocr | OCR_MODE_NORMAL);
++}
++
++/*
++ * transmit a CAN message
++ * message layout in the sk_buff should be like this:
++ * xx xx xx xx ff ll 00 11 22 33 44 55 66 77
++ * [ can-id ] [flags] [len] [can data (up to 8 bytes]
++ */
++static int sja1000_start_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++ struct sja1000_priv *priv = netdev_priv(dev);
++ struct net_device_stats *stats = &dev->stats;
++ struct can_frame *cf = (struct can_frame *)skb->data;
++ uint8_t fi;
++ uint8_t dlc;
++ canid_t id;
++ uint8_t dreg;
++ int i;
++
++ netif_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(dev, REG_FI, fi);
++ priv->write_reg(dev, REG_ID1, (id & 0x1fe00000) >> (5 + 16));
++ priv->write_reg(dev, REG_ID2, (id & 0x001fe000) >> (5 + 8));
++ priv->write_reg(dev, REG_ID3, (id & 0x00001fe0) >> 5);
++ priv->write_reg(dev, REG_ID4, (id & 0x0000001f) << 3);
++ } else {
++ dreg = SFF_BUF;
++ priv->write_reg(dev, REG_FI, fi);
++ priv->write_reg(dev, REG_ID1, (id & 0x000007f8) >> 3);
++ priv->write_reg(dev, REG_ID2, (id & 0x00000007) << 5);
++ }
++
++ for (i = 0; i < dlc; i++)
++ priv->write_reg(dev, dreg++, cf->data[i]);
++
++ stats->tx_bytes += dlc;
++ dev->trans_start = jiffies;
++
++ can_put_echo_skb(skb, dev, 0);
++
++ priv->write_reg(dev, REG_CMR, CMD_TR);
++
++ return 0;
++}
++
++static void sja1000_rx(struct net_device *dev)
++{
++ struct sja1000_priv *priv = netdev_priv(dev);
++ struct net_device_stats *stats = &dev->stats;
++ struct can_frame *cf;
++ struct sk_buff *skb;
++ uint8_t fi;
++ uint8_t dreg;
++ canid_t id;
++ uint8_t dlc;
++ int i;
++
++ skb = dev_alloc_skb(sizeof(struct can_frame));
++ if (skb == NULL)
++ return;
++ skb->dev = dev;
++ skb->protocol = htons(ETH_P_CAN);
++
++ fi = priv->read_reg(dev, REG_FI);
++ dlc = fi & 0x0F;
++
++ if (fi & FI_FF) {
++ /* extended frame format (EFF) */
++ dreg = EFF_BUF;
++ id = (priv->read_reg(dev, REG_ID1) << (5 + 16))
++ | (priv->read_reg(dev, REG_ID2) << (5 + 8))
++ | (priv->read_reg(dev, REG_ID3) << 5)
++ | (priv->read_reg(dev, REG_ID4) >> 3);
++ id |= CAN_EFF_FLAG;
++ } else {
++ /* standard frame format (SFF) */
++ dreg = SFF_BUF;
++ id = (priv->read_reg(dev, REG_ID1) << 3)
++ | (priv->read_reg(dev, REG_ID2) >> 5);
++ }
++
++ if (fi & FI_RTR)
++ id |= CAN_RTR_FLAG;
++
++ cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
++ 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(dev, dreg++);
++
++ while (i < 8)
++ cf->data[i++] = 0;
++
++ /* release receive buffer */
++ priv->write_reg(dev, REG_CMR, CMD_RRB);
++
++ netif_rx(skb);
++
++ dev->last_rx = jiffies;
++ stats->rx_packets++;
++ stats->rx_bytes += dlc;
++}
++
++static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
++{
++ struct sja1000_priv *priv = netdev_priv(dev);
++ struct net_device_stats *stats = &dev->stats;
++ struct can_frame *cf;
++ struct sk_buff *skb;
++ enum can_state state = priv->can.state;
++ uint8_t ecc, alc;
++
++ skb = dev_alloc_skb(sizeof(struct can_frame));
++ if (skb == NULL)
++ return -ENOMEM;
++ skb->dev = dev;
++ skb->protocol = htons(ETH_P_CAN);
++ cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
++ 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 */
++ dev_dbg(ND2D(dev), "data overrun interrupt\n");
++ cf->can_id |= CAN_ERR_CRTL;
++ cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
++ priv->can.can_stats.data_overrun++;
++ priv->write_reg(dev, REG_CMR, CMD_CDO); /* clear bit */
++ }
++
++ if (isrc & IRQ_EI) {
++ /* error warning interrupt */
++ priv->can.can_stats.error_warning++;
++ dev_dbg(ND2D(dev), "error warning interrupt\n");
++
++ 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_BUS_WARNING;
++ } else
++ state = CAN_STATE_ACTIVE;
++ }
++ if (isrc & IRQ_BEI) {
++ /* bus error interrupt */
++ priv->can.can_stats.bus_error++;
++ ecc = priv->read_reg(dev, 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 */
++ dev_dbg(ND2D(dev), "error passive interrupt\n");
++ priv->can.can_stats.error_passive++;
++ if (status & SR_ES)
++ state = CAN_STATE_BUS_PASSIVE;
++ else
++ state = CAN_STATE_ACTIVE;
++ }
++ if (isrc & IRQ_ALI) {
++ /* arbitration lost interrupt */
++ dev_dbg(ND2D(dev), "arbitration lost interrupt\n");
++ alc = priv->read_reg(dev, REG_ALC);
++ priv->can.can_stats.arbitration_lost++;
++ cf->can_id |= CAN_ERR_LOSTARB;
++ cf->data[0] = alc & 0x1f;
++ }
++
++ if (state != priv->can.state && (state == CAN_STATE_BUS_WARNING ||
++ state == CAN_STATE_BUS_PASSIVE)) {
++ uint8_t rxerr = priv->read_reg(dev, REG_RXERR);
++ uint8_t txerr = priv->read_reg(dev, REG_TXERR);
++ cf->can_id |= CAN_ERR_CRTL;
++ if (state == CAN_STATE_BUS_WARNING)
++ cf->data[1] = (txerr > rxerr) ?
++ CAN_ERR_CRTL_TX_WARNING :
++ CAN_ERR_CRTL_RX_WARNING;
++ else
++ cf->data[1] = (txerr > rxerr) ?
++ CAN_ERR_CRTL_TX_PASSIVE :
++ CAN_ERR_CRTL_RX_PASSIVE;
++ }
++
++ priv->can.state = state;
++
++ netif_rx(skb);
++
++ dev->last_rx = jiffies;
++ stats->rx_packets++;
++ stats->rx_bytes += cf->can_dlc;
++
++ return 0;
++}
++
++irqreturn_t sja1000_interrupt(int irq, void *dev_id)
++{
++ struct net_device *dev = (struct net_device *)dev_id;
++ struct sja1000_priv *priv = netdev_priv(dev);
++ struct net_device_stats *stats = &dev->stats;
++ uint8_t isrc, status;
++ int n = 0;
++
++ /* Shared interrupts and IRQ off? */
++ if (priv->read_reg(dev, REG_IER) == IRQ_OFF)
++ return IRQ_NONE;
++
++ if (priv->pre_irq)
++ priv->pre_irq(dev);
++
++ while ((isrc = priv->read_reg(dev, REG_IR)) && (n < SJA1000_MAX_IRQ)) {
++ n++;
++ status = priv->read_reg(dev, REG_SR);
++
++ if (isrc & IRQ_WUI) {
++ /* wake-up interrupt */
++ priv->can.can_stats.wakeup++;
++ }
++ if (isrc & IRQ_TI) {
++ /* transmission complete interrupt */
++ stats->tx_packets++;
++ can_get_echo_skb(dev, 0);
++ netif_wake_queue(dev);
++ }
++ if (isrc & IRQ_RI) {
++ /* receive interrupt */
++ while (status & SR_RBS) {
++ sja1000_rx(dev);
++ status = priv->read_reg(dev, REG_SR);
++ }
++ }
++ if (isrc & (IRQ_DOI | IRQ_EI | IRQ_BEI | IRQ_EPI | IRQ_ALI)) {
++ /* error interrupt */
++ if (sja1000_err(dev, isrc, status))
++ break;
++ }
++ }
++
++ if (priv->post_irq)
++ priv->post_irq(dev);
++
++ if (n >= SJA1000_MAX_IRQ)
++ dev_dbg(ND2D(dev), "%d messages handled in ISR", n);
++
++ return (n) ? IRQ_HANDLED : IRQ_NONE;
++}
++EXPORT_SYMBOL_GPL(sja1000_interrupt);
++
++static int sja1000_open(struct net_device *dev)
++{
++ struct sja1000_priv *priv = netdev_priv(dev);
++ int err;
++
++ /* set chip into reset mode */
++ set_reset_mode(dev);
++
++ /* determine and set bittime */
++ err = can_set_bittiming(dev);
++ if (err)
++ return err;
++
++ /* register interrupt handler, if not done by the device driver */
++ if (!(priv->flags & SJA1000_CUSTOM_IRQ_HANDLER)) {
++ err = request_irq(dev->irq, &sja1000_interrupt, IRQF_SHARED,
++ dev->name, (void *)dev);
++ if (err)
++ return -EAGAIN;
++ }
++
++ /* init and start chi */
++ sja1000_start(dev);
++ priv->open_time = jiffies;
++
++ netif_start_queue(dev);
++
++ return 0;
++}
++
++static int sja1000_close(struct net_device *dev)
++{
++ struct sja1000_priv *priv = netdev_priv(dev);
++
++ set_reset_mode(dev);
++ netif_stop_queue(dev);
++ priv->open_time = 0;
++ can_close_cleanup(dev);
++
++ if (!(priv->flags & SJA1000_CUSTOM_IRQ_HANDLER))
++ free_irq(dev->irq, (void *)dev);
++
++ return 0;
++}
++
++struct net_device *alloc_sja1000dev(int sizeof_priv)
++{
++ struct net_device *dev;
++ struct sja1000_priv *priv;
++
++ dev = alloc_candev(sizeof(struct sja1000_priv) + sizeof_priv);
++ if (!dev)
++ return NULL;
++
++ priv = netdev_priv(dev);
++ priv->dev = dev;
++
++ if (sizeof_priv)
++ priv->priv = (void *)priv + sizeof(struct sja1000_priv);
++
++ return dev;
++}
++EXPORT_SYMBOL_GPL(alloc_sja1000dev);
++
++void free_sja1000dev(struct net_device *dev)
++{
++ free_candev(dev);
++}
++EXPORT_SYMBOL(free_sja1000dev);
++
++int register_sja1000dev(struct net_device *dev)
++{
++ struct sja1000_priv *priv = netdev_priv(dev);
++ int err;
++
++ if (!sja1000_probe_chip(dev))
++ return -ENODEV;
++
++ dev->flags |= IFF_ECHO; /* we support local echo */
++
++ dev->open = sja1000_open;
++ dev->stop = sja1000_close;
++
++ dev->hard_start_xmit = sja1000_start_xmit;
++
++ priv->can.bittiming_const = &sja1000_bittiming_const;
++ priv->can.do_set_bittiming = sja1000_set_bittiming;
++ priv->can.do_get_state = sja1000_get_state;
++ priv->can.do_set_mode = sja1000_set_mode;
++ priv->dev = dev;
++
++ err = register_candev(dev);
++ if (err) {
++ printk(KERN_INFO
++ "%s: registering netdev failed\n", DRV_NAME);
++ free_netdev(dev);
++ return err;
++ }
++
++ set_reset_mode(dev);
++ chipset_init(dev);
++ return 0;
++}
++EXPORT_SYMBOL(register_sja1000dev);
++
++void unregister_sja1000dev(struct net_device *dev)
++{
++ set_reset_mode(dev);
++ unregister_candev(dev);
++}
++EXPORT_SYMBOL(unregister_sja1000dev);
++
++static __init int sja1000_init(void)
++{
++ printk(KERN_INFO "%s CAN netdevice driver\n", DRV_NAME);
++
++ return 0;
++}
++
++module_init(sja1000_init);
++
++static __exit void sja1000_exit(void)
++{
++ printk(KERN_INFO "%s: driver removed\n", DRV_NAME);
++}
++
++module_exit(sja1000_exit);
+Index: net-next-2.6/drivers/net/can/sja1000/sja1000.h
+===================================================================
+--- /dev/null
++++ net-next-2.6/drivers/net/can/sja1000/sja1000.h
+@@ -0,0 +1,182 @@
++/*
++ * sja1000.h - Philips SJA1000 network device driver
++ *
++ * 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
++
++#include <linux/can/dev.h>
++#include <linux/can/platform/sja1000.h>
++
++#define SJA1000_MAX_IRQ 20 /* max. number of interrupts handled in ISR */
++
++/* 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
++
++/*
++ * Flags for sja1000priv.flags
++ */
++#define SJA1000_CUSTOM_IRQ_HANDLER 0x1
++
++/*
++ * SJA1000 private data structure
++ */
++struct sja1000_priv {
++ struct can_priv can; /* must be the first member! */
++ long open_time;
++ struct sk_buff *echo_skb;
++
++ u8 (*read_reg) (struct net_device *dev, int reg);
++ void (*write_reg) (struct net_device *dev, int reg, u8 val);
++ void (*pre_irq) (struct net_device *dev);
++ void (*post_irq) (struct net_device *dev);
++
++ void *priv; /* for board-specific data */
++ struct net_device *dev;
++
++ u8 ocr;
++ u8 cdr;
++ u32 flags;
++};
++
++struct net_device *alloc_sja1000dev(int sizeof_priv);
++void free_sja1000dev(struct net_device *dev);
++int register_sja1000dev(struct net_device *dev);
++void unregister_sja1000dev(struct net_device *dev);
++
++irqreturn_t sja1000_interrupt(int irq, void *dev_id);
++
++#if 0
++void can_proc_create(const char *drv_name);
++void can_proc_remove(const char *drv_name);
++#endif
++
++#endif /* SJA1000_DEV_H */
+Index: net-next-2.6/drivers/net/can/Kconfig
+===================================================================
+--- net-next-2.6.orig/drivers/net/can/Kconfig
++++ net-next-2.6/drivers/net/can/Kconfig
+@@ -35,4 +35,15 @@ config CAN_CALC_BITTIMING
+ files "tq", "prop_seg", "phase_seg1", "phase_seg2" and "sjw".
+ If unsure, say Y.
+
++config CAN_SJA1000
++ depends on CAN_DEV
++ tristate "Philips SJA1000"
++ ---help---
++ The SJA1000 is one of the top CAN controllers out there. As it
++ has a multiplexed interface it fits directly to 8051
++ microcontrollers or into the PC I/O port space. The SJA1000
++ is a full CAN controller, with shadow registers for RX and TX.
++ It can send and receive any kinds of CAN frames (SFF/EFF/RTR)
++ with a single (simple) filter setup.
++
+ endmenu
+Index: net-next-2.6/drivers/net/can/Makefile
+===================================================================
+--- net-next-2.6.orig/drivers/net/can/Makefile
++++ net-next-2.6/drivers/net/can/Makefile
+@@ -7,4 +7,6 @@ obj-$(CONFIG_CAN_VCAN) += vcan.o
+ obj-$(CONFIG_CAN_DEV) += can-dev.o
+ can-dev-y := dev.o sysfs.o
+
++obj-$(CONFIG_CAN_SJA1000) += sja1000/
++
+ ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
+Index: net-next-2.6/drivers/net/can/sja1000/Makefile
+===================================================================
+--- /dev/null
++++ net-next-2.6/drivers/net/can/sja1000/Makefile
+@@ -0,0 +1,7 @@
++#
++# Makefile for the SJA1000 CAN controller drivers.
++#
++
++obj-$(CONFIG_CAN_SJA1000) += sja1000.o
++
++ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
--- /dev/null
+[PATCH 6/9] Socket-CAN: SJA1000: generic platform bus driver
+
+This driver adds support for the SJA1000 chips connected to the
+"platform bus", which can be found on various embedded systems.
+
+Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
+Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
+Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
+Signed-off-by: Oliver Hartkopp <oliver.hartkopp@volkswagen.de>
+---
+ drivers/net/can/Kconfig | 10 +
+ drivers/net/can/sja1000/Makefile | 1
+ drivers/net/can/sja1000/sja1000_platform.c | 169 +++++++++++++++++++++++++++++
+ include/linux/can/platform/sja1000.h | 32 +++++
+ 4 files changed, 212 insertions(+)
+
+Index: net-next-2.6/drivers/net/can/sja1000/sja1000_platform.c
+===================================================================
+--- /dev/null
++++ net-next-2.6/drivers/net/can/sja1000/sja1000_platform.c
+@@ -0,0 +1,169 @@
++/*
++ * Copyright (C) 2005 Sascha Hauer, Pengutronix
++ * Copyright (C) 2007 Wolfgang Grandegger <wg@grandegger.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 <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/interrupt.h>
++#include <linux/netdevice.h>
++#include <linux/delay.h>
++#include <linux/pci.h>
++#include <linux/platform_device.h>
++#include <linux/irq.h>
++#include <linux/can.h>
++#include <linux/can/dev.h>
++#include <linux/can/platform/sja1000.h>
++#include <linux/io.h>
++
++#include "sja1000.h"
++
++#define DRV_NAME "sja1000_platform"
++
++MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
++MODULE_DESCRIPTION("Socket-CAN driver for SJA1000 on the platform bus");
++MODULE_LICENSE("GPL v2");
++
++static u8 sp_read_reg(struct net_device *dev, int reg)
++{
++ return ioread8((void __iomem *)(dev->base_addr + reg));
++}
++
++static void sp_write_reg(struct net_device *dev, int reg, u8 val)
++{
++ iowrite8(val, (void __iomem *)(dev->base_addr + reg));
++}
++
++static int sp_probe(struct platform_device *pdev)
++{
++ int err, irq;
++ void __iomem *addr;
++ struct net_device *dev;
++ struct sja1000_priv *priv;
++ struct resource *res_mem, *res_irq;
++ struct sja1000_platform_data *pdata;
++
++ pdata = pdev->dev.platform_data;
++ if (!pdata) {
++ dev_err(&pdev->dev, "No platform data provided!\n");
++ err = -ENODEV;
++ goto exit;
++ }
++
++ res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
++ if (!res_mem || !res_irq) {
++ err = -ENODEV;
++ goto exit;
++ }
++
++ if (!request_mem_region(res_mem->start,
++ res_mem->end - res_mem->start + 1,
++ DRV_NAME)) {
++ err = -EBUSY;
++ goto exit;
++ }
++
++ addr = ioremap_nocache(res_mem->start,
++ res_mem->end - res_mem->start + 1);
++ if (!addr) {
++ err = -ENOMEM;
++ goto exit_release;
++ }
++
++ irq = res_irq->start;
++ if (res_irq->flags & IRQF_TRIGGER_MASK)
++ set_irq_type(irq, res_irq->flags & IRQF_TRIGGER_MASK);
++
++ dev = alloc_sja1000dev(0);
++ if (!dev) {
++ err = -ENOMEM;
++ goto exit_iounmap;
++ }
++ priv = netdev_priv(dev);
++
++ priv->read_reg = sp_read_reg;
++ priv->write_reg = sp_write_reg;
++ priv->can.bittiming.clock = pdata->clock;
++ priv->ocr = pdata->ocr;
++ priv->cdr = pdata->cdr;
++
++ dev->irq = irq;
++ dev->base_addr = (unsigned long)addr;
++
++ dev_set_drvdata(&pdev->dev, dev);
++ SET_NETDEV_DEV(dev, &pdev->dev);
++
++ err = register_sja1000dev(dev);
++ if (err) {
++ dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
++ DRV_NAME, err);
++ goto exit_free;
++ }
++
++ dev_info(&pdev->dev, "%s device registered (base_addr=%#lx, irq=%d)\n",
++ DRV_NAME, dev->base_addr, dev->irq);
++ return 0;
++
++ exit_free:
++ free_sja1000dev(dev);
++ exit_iounmap:
++ iounmap(addr);
++ exit_release:
++ release_mem_region(res_mem->start, res_mem->end - res_mem->start + 1);
++ exit:
++ return err;
++}
++
++static int sp_remove(struct platform_device *pdev)
++{
++ struct net_device *dev = dev_get_drvdata(&pdev->dev);
++ struct resource *res;
++
++ unregister_sja1000dev(dev);
++ dev_set_drvdata(&pdev->dev, NULL);
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ release_mem_region(res->start, res->end - res->start + 1);
++
++ if (dev->base_addr)
++ iounmap((void __iomem *)dev->base_addr);
++
++ free_sja1000dev(dev);
++
++ return 0;
++}
++
++static struct platform_driver sp_driver = {
++ .probe = sp_probe,
++ .remove = sp_remove,
++ .driver = {
++ .name = DRV_NAME,
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init sp_init(void)
++{
++ return platform_driver_register(&sp_driver);
++}
++
++static void __exit sp_exit(void)
++{
++ platform_driver_unregister(&sp_driver);
++}
++
++module_init(sp_init);
++module_exit(sp_exit);
+Index: net-next-2.6/include/linux/can/platform/sja1000.h
+===================================================================
+--- /dev/null
++++ net-next-2.6/include/linux/can/platform/sja1000.h
+@@ -0,0 +1,32 @@
++#ifndef _CAN_PLATFORM_SJA1000_H_
++#define _CAN_PLATFORM_SJA1000_H_
++
++/* 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
++
++struct sja1000_platform_data {
++ u32 clock; /* CAN bus oscillator frequency in Hz */
++
++ u8 ocr; /* output control register */
++ u8 cdr; /* clock divider register */
++};
++
++#endif /* !_CAN_PLATFORM_SJA1000_H_ */
+Index: net-next-2.6/drivers/net/can/Kconfig
+===================================================================
+--- net-next-2.6.orig/drivers/net/can/Kconfig
++++ net-next-2.6/drivers/net/can/Kconfig
+@@ -46,4 +46,14 @@ config CAN_SJA1000
+ It can send and receive any kinds of CAN frames (SFF/EFF/RTR)
+ with a single (simple) filter setup.
+
++config CAN_SJA1000_PLATFORM
++ depends on CAN_SJA1000
++ tristate "Generic Platform Bus based SJA1000 driver"
++ ---help---
++ This driver adds support for the SJA1000 chips connected to
++ the "platform bus" (Linux abstraction for directly to the
++ processor attached devices). Which can be found on various
++ boards from Phytec (http://www.phytec.de) like the PCM027,
++ PCM038.
++
+ endmenu
+Index: net-next-2.6/drivers/net/can/sja1000/Makefile
+===================================================================
+--- net-next-2.6.orig/drivers/net/can/sja1000/Makefile
++++ net-next-2.6/drivers/net/can/sja1000/Makefile
+@@ -3,5 +3,6 @@
+ #
+
+ obj-$(CONFIG_CAN_SJA1000) += sja1000.o
++obj-$(CONFIG_CAN_SJA1000_PLATFORM) += sja1000_platform.o
+
+ ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
--- /dev/null
+[PATCH 7/9] Socket-CAN: SJA1000: driver for EMS PCI cards
+
+The patch adds support for the one or two channel CPC-PCI and CPC-PCIe
+cards from EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de).
+
+Signed-off-by: Sebastian Haas <haas@ems-wuensche.com>
+Signed-off-by: Markus Plessing <plessing@ems-wuensche.com>
+Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
+---
+ drivers/net/can/Kconfig | 7
+ drivers/net/can/sja1000/Makefile | 1
+ drivers/net/can/sja1000/ems_pci.c | 328 ++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 336 insertions(+)
+
+Index: net-next-2.6/drivers/net/can/Kconfig
+===================================================================
+--- net-next-2.6.orig/drivers/net/can/Kconfig
++++ net-next-2.6/drivers/net/can/Kconfig
+@@ -56,4 +56,11 @@ config CAN_SJA1000_PLATFORM
+ boards from Phytec (http://www.phytec.de) like the PCM027,
+ PCM038.
+
++config CAN_EMS_PCI
++ tristate "EMS CPC-PCI and CPC-PCIe Card"
++ depends on PCI && CAN_SJA1000
++ ---help---
++ This driver is for the one or two channel CPC-PCI and CPC-PCIe
++ cards from EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de).
++
+ endmenu
+Index: net-next-2.6/drivers/net/can/sja1000/Makefile
+===================================================================
+--- net-next-2.6.orig/drivers/net/can/sja1000/Makefile
++++ net-next-2.6/drivers/net/can/sja1000/Makefile
+@@ -4,5 +4,6 @@
+
+ obj-$(CONFIG_CAN_SJA1000) += sja1000.o
+ obj-$(CONFIG_CAN_SJA1000_PLATFORM) += sja1000_platform.o
++obj-$(CONFIG_CAN_EMS_PCI) += ems_pci.o
+
+ ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
+Index: net-next-2.6/drivers/net/can/sja1000/ems_pci.c
+===================================================================
+--- /dev/null
++++ net-next-2.6/drivers/net/can/sja1000/ems_pci.c
+@@ -0,0 +1,328 @@
++/*
++ * Copyright (C) 2007 Wolfgang Grandegger <wg@grandegger.com>
++ * Copyright (C) 2008 Markus Plessing <plessing@ems-wuensche.com>
++ * Copyright (C) 2008 Sebastian Haas <haas@ems-wuensche.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 <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/interrupt.h>
++#include <linux/netdevice.h>
++#include <linux/delay.h>
++#include <linux/pci.h>
++#include <linux/can.h>
++#include <linux/can/dev.h>
++#include <linux/io.h>
++
++#include "sja1000.h"
++
++#define DRV_NAME "ems_pci"
++
++MODULE_AUTHOR("Sebastian Haas <haas@ems-wuenche.com>");
++MODULE_DESCRIPTION("Socket-CAN driver for EMS CPC-PCI/PCIe CAN cards");
++MODULE_SUPPORTED_DEVICE("EMS CPC-PCI/PCIe CAN card");
++MODULE_LICENSE("GPL v2");
++
++#define EMS_PCI_MAX_CHAN 2
++
++struct ems_pci_card {
++ int channels;
++
++ struct pci_dev *pci_dev;
++ struct net_device *net_dev[EMS_PCI_MAX_CHAN];
++
++ void __iomem *conf_addr;
++ void __iomem *base_addr;
++};
++
++#define EMS_PCI_CAN_CLOCK (16000000 / 2)
++
++/*
++ * Register definitions and descriptions are from LinCAN 0.3.3.
++ *
++ * PSB4610 PITA-2 bridge control registers
++ */
++#define PITA2_ICR 0x00 /* Interrupt Control Register */
++#define PITA2_ICR_INT0 0x00000002 /* [RC] INT0 Active/Clear */
++#define PITA2_ICR_INT0_EN 0x00020000 /* [RW] Enable INT0 */
++
++#define PITA2_MISC 0x1c /* Miscellaneous Register */
++#define PITA2_MISC_CONFIG 0x04000000 /* Multiplexed parallel interface */
++
++/*
++ * The board configuration is probably following:
++ * RX1 is connected to ground.
++ * TX1 is not connected.
++ * CLKO is not connected.
++ * Setting the OCR register to 0xDA is a good idea.
++ * This means normal output mode , push-pull and the correct polarity.
++ */
++#define EMS_PCI_OCR (OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL)
++
++/*
++ * In the CDR register, you should set CBP to 1.
++ * You will probably also want to set the clock divider value to 7
++ * (meaning direct oscillator output) because the second SJA1000 chip
++ * is driven by the first one CLKOUT output.
++ */
++#define EMS_PCI_CDR (CDR_CBP | CDR_CLKOUT_MASK)
++#define EMS_PCI_MEM_SIZE 4096 /* Size of the remapped io-memory */
++#define EMS_PCI_CAN_BASE_OFFSET 0x400 /* offset where the controllers starts */
++#define EMS_PCI_CAN_CTRL_SIZE 0x200 /* memory size for each controller */
++
++#define EMS_PCI_PORT_BYTES 0x4 /* Each register occupies 4 bytes */
++
++#define EMS_PCI_VENDOR_ID 0x110a /* PCI device and vendor ID */
++#define EMS_PCI_DEVICE_ID 0x2104
++
++static struct pci_device_id ems_pci_tbl[] = {
++ {EMS_PCI_VENDOR_ID, EMS_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
++ {0,}
++};
++MODULE_DEVICE_TABLE(pci, ems_pci_tbl);
++
++/*
++ * Helper to read internal registers from card logic (not CAN)
++ */
++static u8 ems_pci_readb(struct ems_pci_card *card, unsigned int port)
++{
++ return readb((void __iomem *)card->base_addr
++ + (port * EMS_PCI_PORT_BYTES));
++}
++
++static u8 ems_pci_read_reg(struct net_device *dev, int port)
++{
++ return readb((void __iomem *)dev->base_addr
++ + (port * EMS_PCI_PORT_BYTES));
++}
++
++static void ems_pci_write_reg(struct net_device *dev, int port, u8 val)
++{
++ writeb(val, (void __iomem *)dev->base_addr
++ + (port * EMS_PCI_PORT_BYTES));
++}
++
++static void ems_pci_post_irq(struct net_device *dev)
++{
++ struct sja1000_priv *priv = netdev_priv(dev);
++ struct ems_pci_card *card = (struct ems_pci_card *)priv->priv;
++
++ /* reset int flag of pita */
++ writel(PITA2_ICR_INT0_EN | PITA2_ICR_INT0, card->conf_addr
++ + PITA2_ICR);
++}
++
++/*
++ * Check if a CAN controller is present at the specified location
++ * by trying to set 'em into the PeliCAN mode
++ */
++static inline int ems_pci_check_chan(struct net_device *dev)
++{
++ unsigned char res;
++
++ /* Make sure SJA1000 is in reset mode */
++ ems_pci_write_reg(dev, REG_MOD, 1);
++
++ ems_pci_write_reg(dev, REG_CDR, CDR_PELICAN);
++
++ /* read reset-values */
++ res = ems_pci_read_reg(dev, REG_CDR);
++
++ if (res == CDR_PELICAN)
++ return 1;
++
++ return 0;
++}
++
++static void ems_pci_del_card(struct pci_dev *pdev)
++{
++ struct ems_pci_card *card = pci_get_drvdata(pdev);
++ struct net_device *dev;
++ int i = 0;
++
++ for (i = 0; i < card->channels; i++) {
++ dev = card->net_dev[i];
++
++ if (!dev)
++ continue;
++
++ dev_info(&pdev->dev, "Removing %s.\n", dev->name);
++ unregister_sja1000dev(dev);
++ free_sja1000dev(dev);
++ }
++
++ if (card->base_addr != NULL)
++ pci_iounmap(card->pci_dev, card->base_addr);
++
++ if (card->conf_addr != NULL)
++ pci_iounmap(card->pci_dev, card->conf_addr);
++
++ kfree(card);
++
++ pci_disable_device(pdev);
++ pci_set_drvdata(pdev, NULL);
++}
++
++static void ems_pci_card_reset(struct ems_pci_card *card)
++{
++ /* Request board reset */
++ writeb(0, card->base_addr);
++}
++
++/*
++ * Probe PCI device for EMS CAN signature and register each available
++ * CAN channel to SJA1000 Socket-CAN subsystem.
++ */
++static int __devinit ems_pci_add_card(struct pci_dev *pdev,
++ const struct pci_device_id *ent)
++{
++ struct sja1000_priv *priv;
++ struct net_device *dev;
++ struct ems_pci_card *card;
++ int err, i;
++
++ /* Enabling PCI device */
++ if (pci_enable_device(pdev) < 0) {
++ dev_err(&pdev->dev, "Enabling PCI device failed\n");
++ return -ENODEV;
++ }
++
++ /* Allocating card structures to hold addresses, ... */
++ card = kzalloc(sizeof(struct ems_pci_card), GFP_KERNEL);
++ if (card == NULL) {
++ dev_err(&pdev->dev, "Unable to allocate memory\n");
++ pci_disable_device(pdev);
++ return -ENOMEM;
++ }
++
++ pci_set_drvdata(pdev, card);
++
++ card->pci_dev = pdev;
++
++ card->channels = 0;
++
++ /* Remap PITA configuration space, and controller memory area */
++ card->conf_addr = pci_iomap(pdev, 0, EMS_PCI_MEM_SIZE);
++ if (card->conf_addr == NULL) {
++ err = -ENOMEM;
++
++ goto failure_cleanup;
++ }
++
++ card->base_addr = pci_iomap(pdev, 1, EMS_PCI_MEM_SIZE);
++ if (card->base_addr == NULL) {
++ err = -ENOMEM;
++
++ goto failure_cleanup;
++ }
++
++ /* Configure PITA-2 parallel interface (enable MUX) */
++ writel(PITA2_MISC_CONFIG, card->conf_addr + PITA2_MISC);
++
++ /* Check for unique EMS CAN signature */
++ if (ems_pci_readb(card, 0) != 0x55 ||
++ ems_pci_readb(card, 1) != 0xAA ||
++ ems_pci_readb(card, 2) != 0x01 ||
++ ems_pci_readb(card, 3) != 0xCB ||
++ ems_pci_readb(card, 4) != 0x11) {
++ dev_err(&pdev->dev, "Not EMS Dr. Thomas Wuensche interface\n");
++
++ err = -ENODEV;
++ goto failure_cleanup;
++ }
++
++ ems_pci_card_reset(card);
++
++ /* Detect available channels */
++ for (i = 0; i < EMS_PCI_MAX_CHAN; i++) {
++ dev = alloc_sja1000dev(0);
++ if (dev == NULL) {
++ err = -ENOMEM;
++ goto failure_cleanup;
++ }
++
++ card->net_dev[i] = dev;
++ priv = netdev_priv(dev);
++ priv->priv = card;
++
++ dev->irq = pdev->irq;
++ dev->base_addr = (unsigned long)(card->base_addr
++ + EMS_PCI_CAN_BASE_OFFSET
++ + (i * EMS_PCI_CAN_CTRL_SIZE));
++
++ /* Check if channel is present */
++ if (ems_pci_check_chan(dev)) {
++ priv->read_reg = ems_pci_read_reg;
++ priv->write_reg = ems_pci_write_reg;
++ priv->post_irq = ems_pci_post_irq;
++ priv->can.bittiming.clock = EMS_PCI_CAN_CLOCK;
++ priv->ocr = EMS_PCI_OCR;
++ priv->cdr = EMS_PCI_CDR;
++
++ SET_NETDEV_DEV(dev, &pdev->dev);
++
++ /* Enable interrupts from card */
++ writel(PITA2_ICR_INT0_EN, card->conf_addr + PITA2_ICR);
++
++ /* Register SJA1000 device */
++ err = register_sja1000dev(dev);
++ if (err) {
++ dev_err(&pdev->dev, "Registering device failed "
++ "(err=%d)\n", err);
++ free_sja1000dev(dev);
++ goto failure_cleanup;
++ }
++
++ card->channels++;
++
++ dev_info(&pdev->dev, "Channel #%d at %lX, irq %d\n",
++ i + 1, dev->base_addr,
++ dev->irq);
++ } else {
++ free_sja1000dev(dev);
++ }
++ }
++
++ return 0;
++
++failure_cleanup:
++ dev_err(&pdev->dev, "Error: %d. Cleaning Up.\n", err);
++
++ ems_pci_del_card(pdev);
++
++ return err;
++}
++
++static struct pci_driver ems_pci_driver = {
++ .name = DRV_NAME,
++ .id_table = ems_pci_tbl,
++ .probe = ems_pci_add_card,
++ .remove = ems_pci_del_card,
++};
++
++static int __init ems_pci_init(void)
++{
++ return pci_register_driver(&ems_pci_driver);
++}
++
++static void __exit ems_pci_exit(void)
++{
++ pci_unregister_driver(&ems_pci_driver);
++}
++
++module_init(ems_pci_init);
++module_exit(ems_pci_exit);
++
--- /dev/null
+[PATCH 8/9] Socket-CAN: SJA1000: driver for Kvaser PCI cards
+
+The patch adds support for the PCI cards: PCIcan and PCIcanx
+(1, 2 or 4 channel) from Kvaser (http://www.kvaser.com).
+
+Signed-off-by: Per Dalén <per.dalen@cnw.se>
+Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
+---
+ drivers/net/can/Kconfig | 7
+ drivers/net/can/sja1000/Makefile | 1
+ drivers/net/can/sja1000/kvaser_pci.c | 415 +++++++++++++++++++++++++++++++++++
+ 3 files changed, 423 insertions(+)
+
+Index: net-next-2.6/drivers/net/can/Kconfig
+===================================================================
+--- net-next-2.6.orig/drivers/net/can/Kconfig
++++ net-next-2.6/drivers/net/can/Kconfig
+@@ -63,4 +63,11 @@ config CAN_EMS_PCI
+ This driver is for the one or two channel CPC-PCI and CPC-PCIe
+ cards from EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de).
+
++config CAN_KVASER_PCI
++ tristate "Kvaser PCIcanx and Kvaser PCIcan PCI Cards"
++ depends on PCI && CAN_SJA1000
++ ---help---
++ This driver is for the the PCIcanx and PCIcan cards (1, 2 or
++ 4 channel) from Kvaser (http://www.kvaser.com).
++
+ endmenu
+Index: net-next-2.6/drivers/net/can/sja1000/kvaser_pci.c
+===================================================================
+--- /dev/null
++++ net-next-2.6/drivers/net/can/sja1000/kvaser_pci.c
+@@ -0,0 +1,415 @@
++/*
++ * Copyright (C) 2008 Per Dalen <per.dalen@cnw.se>
++ *
++ * Parts of this software are based on (derived) the following:
++ *
++ * - Kvaser linux driver, version 4.72 BETA
++ * Copyright (C) 2002-2007 KVASER AB
++ *
++ * - Lincan driver, version 0.3.3, OCERA project
++ * Copyright (C) 2004 Pavel Pisa
++ * Copyright (C) 2001 Arnaud Westenberg
++ *
++ * - Socketcan SJA1000 drivers
++ * Copyright (C) 2007 Wolfgang Grandegger <wg@grandegger.com>
++ * Copyright (c) 2002-2007 Volkswagen Group Electronic Research
++ * Copyright (c) 2003 Matthias Brukner, Trajet Gmbh, Rebenring 33,
++ * 38106 Braunschweig, GERMANY
++ *
++ * 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 <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/interrupt.h>
++#include <linux/netdevice.h>
++#include <linux/delay.h>
++#include <linux/pci.h>
++#include <linux/can.h>
++#include <linux/can/dev.h>
++#include <linux/io.h>
++
++#include "sja1000.h"
++
++#define DRV_NAME "kvaser_pci"
++
++MODULE_AUTHOR("Per Dalen <per.dalen@cnw.se>");
++MODULE_DESCRIPTION("Socket-CAN driver for KVASER PCAN PCI cards");
++MODULE_SUPPORTED_DEVICE("KVASER PCAN PCI CAN card");
++MODULE_LICENSE("GPL v2");
++
++#define MAX_NO_OF_CHANNELS 4 /* max no of channels on
++ a single card */
++
++struct kvaser_pci {
++ int channel;
++ struct pci_dev *pci_dev;
++ struct net_device *slave_dev[MAX_NO_OF_CHANNELS-1];
++ void __iomem *conf_addr;
++ void __iomem *res_addr;
++ int no_channels;
++ u8 xilinx_ver;
++};
++
++#define KVASER_PCI_CAN_CLOCK (16000000 / 2)
++
++/*
++ * The board configuration is probably following:
++ * RX1 is connected to ground.
++ * TX1 is not connected.
++ * CLKO is not connected.
++ * Setting the OCR register to 0xDA is a good idea.
++ * This means normal output mode , push-pull and the correct polarity.
++ */
++#define KVASER_PCI_OCR (OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL)
++
++/*
++ * In the CDR register, you should set CBP to 1.
++ * You will probably also want to set the clock divider value to 0
++ * (meaning divide-by-2), the Pelican bit, and the clock-off bit
++ * (you will have no need for CLKOUT anyway).
++ */
++#define KVASER_PCI_CDR (CDR_CBP | CDR_CLKOUT_MASK)
++
++/*
++ * These register values are valid for revision 14 of the Xilinx logic.
++ */
++#define XILINX_VERINT 7 /* Lower nibble simulate interrupts,
++ high nibble version number. */
++
++#define XILINX_PRESUMED_VERSION 14
++
++/*
++ * Important S5920 registers
++ */
++#define S5920_INTCSR 0x38
++#define S5920_PTCR 0x60
++#define INTCSR_ADDON_INTENABLE_M 0x2000
++
++
++#define KVASER_PCI_PORT_BYTES 0x20
++
++#define PCI_CONFIG_PORT_SIZE 0x80 /* size of the config io-memory */
++#define PCI_PORT_SIZE 0x80 /* size of a channel io-memory */
++#define PCI_PORT_XILINX_SIZE 0x08 /* size of a xilinx io-memory */
++
++#define KVASER_PCI_VENDOR_ID1 0x10e8 /* the PCI device and vendor IDs */
++#define KVASER_PCI_DEVICE_ID1 0x8406
++
++#define KVASER_PCI_VENDOR_ID2 0x1a07 /* the PCI device and vendor IDs */
++#define KVASER_PCI_DEVICE_ID2 0x0008
++
++static struct pci_device_id kvaser_pci_tbl[] = {
++ {KVASER_PCI_VENDOR_ID1, KVASER_PCI_DEVICE_ID1, PCI_ANY_ID, PCI_ANY_ID,},
++ {KVASER_PCI_VENDOR_ID2, KVASER_PCI_DEVICE_ID2, PCI_ANY_ID, PCI_ANY_ID,},
++ { 0,}
++};
++
++MODULE_DEVICE_TABLE(pci, kvaser_pci_tbl);
++
++static u8 kvaser_pci_read_reg(struct net_device *dev, int port)
++{
++ return ioread8((void __iomem *)(dev->base_addr + port));
++}
++
++static void kvaser_pci_write_reg(struct net_device *dev, int port, u8 val)
++{
++ iowrite8(val, (void __iomem *)(dev->base_addr + port));
++}
++
++static void kvaser_pci_disable_irq(struct net_device *dev)
++{
++ struct sja1000_priv *priv = netdev_priv(dev);
++ struct kvaser_pci *board = priv->priv;
++ u32 tmp;
++
++ /* Disable interrupts from card */
++ tmp = ioread32(board->conf_addr + S5920_INTCSR);
++ tmp &= ~INTCSR_ADDON_INTENABLE_M;
++ iowrite32(tmp, board->conf_addr + S5920_INTCSR);
++}
++
++static void kvaser_pci_enable_irq(struct net_device *dev)
++{
++ struct sja1000_priv *priv = netdev_priv(dev);
++ struct kvaser_pci *board = priv->priv;
++ u32 tmp;
++
++ /* Enable interrupts from card */
++ tmp = ioread32(board->conf_addr + S5920_INTCSR);
++ tmp |= INTCSR_ADDON_INTENABLE_M;
++ iowrite32(tmp, board->conf_addr + S5920_INTCSR);
++}
++
++static int number_of_sja1000_chip(void __iomem *base_addr)
++{
++ u8 status;
++ int i;
++
++ for (i = 0; i < MAX_NO_OF_CHANNELS; i++) {
++ /* reset chip */
++ iowrite8(MOD_RM, base_addr +
++ (i * KVASER_PCI_PORT_BYTES) + REG_MOD);
++ status = ioread8(base_addr +
++ (i * KVASER_PCI_PORT_BYTES) + REG_MOD);
++ udelay(10);
++ /* check reset bit */
++ if (!(status & MOD_RM))
++ break;
++ }
++
++ return i;
++}
++
++static void kvaser_pci_del_chan(struct net_device *dev)
++{
++ struct sja1000_priv *priv;
++ struct kvaser_pci *board;
++ int i;
++
++ if (!dev)
++ return;
++ priv = netdev_priv(dev);
++ if (!priv)
++ return;
++ board = priv->priv;
++ if (!board)
++ return;
++
++ dev_info(&board->pci_dev->dev, "Removing device %s\n",
++ dev->name);
++
++ for (i = 0; i < board->no_channels - 1; i++) {
++ if (board->slave_dev[i]) {
++ dev_info(&board->pci_dev->dev, "Removing device %s\n",
++ board->slave_dev[i]->name);
++ unregister_sja1000dev(board->slave_dev[i]);
++ free_sja1000dev(board->slave_dev[i]);
++ }
++ }
++ unregister_sja1000dev(dev);
++
++ /* Disable PCI interrupts */
++ kvaser_pci_disable_irq(dev);
++
++ pci_iounmap(board->pci_dev, (void __iomem *)dev->base_addr);
++ pci_iounmap(board->pci_dev, board->conf_addr);
++ pci_iounmap(board->pci_dev, board->res_addr);
++
++ free_sja1000dev(dev);
++}
++
++static int kvaser_pci_add_chan(struct pci_dev *pdev, int channel,
++ struct net_device **master_dev,
++ void __iomem *conf_addr,
++ void __iomem *res_addr,
++ unsigned long base_addr)
++{
++ struct net_device *dev;
++ struct sja1000_priv *priv;
++ struct kvaser_pci *board;
++ int err, init_step;
++
++ dev = alloc_sja1000dev(sizeof(struct kvaser_pci));
++ if (dev == NULL)
++ return -ENOMEM;
++
++ priv = netdev_priv(dev);
++ board = priv->priv;
++
++ board->pci_dev = pdev;
++ board->channel = channel;
++
++ /*S5920*/
++ board->conf_addr = conf_addr;
++
++ /*XILINX board wide address*/
++ board->res_addr = res_addr;
++
++ if (channel == 0) {
++ board->xilinx_ver =
++ ioread8(board->res_addr + XILINX_VERINT) >> 4;
++ init_step = 2;
++
++ /* Assert PTADR# - we're in passive mode so the other bits are
++ not important */
++ iowrite32(0x80808080UL, board->conf_addr + S5920_PTCR);
++
++ /* Disable interrupts from card */
++ kvaser_pci_disable_irq(dev);
++ /* Enable interrupts from card */
++ kvaser_pci_enable_irq(dev);
++ } else {
++ struct sja1000_priv *master_priv = netdev_priv(*master_dev);
++ struct kvaser_pci *master_board = master_priv->priv;
++ master_board->slave_dev[channel - 1] = dev;
++ master_board->no_channels = channel + 1;
++ board->xilinx_ver = master_board->xilinx_ver;
++ }
++
++ dev->base_addr = base_addr + channel * KVASER_PCI_PORT_BYTES;
++
++ priv->read_reg = kvaser_pci_read_reg;
++ priv->write_reg = kvaser_pci_write_reg;
++
++ priv->can.bittiming.clock = KVASER_PCI_CAN_CLOCK;
++
++ priv->ocr = KVASER_PCI_OCR;
++ priv->cdr = KVASER_PCI_CDR;
++
++ /* Register and setup interrupt handling */
++ dev->irq = pdev->irq;
++ init_step = 4;
++
++ dev_info(&pdev->dev, "base_addr=%#lx conf_addr=%p irq=%d\n",
++ dev->base_addr, board->conf_addr, dev->irq);
++
++ SET_NETDEV_DEV(dev, &pdev->dev);
++
++ /* Register SJA1000 device */
++ err = register_sja1000dev(dev);
++ if (err) {
++ dev_err(&pdev->dev, "Registering device failed (err=%d)\n",
++ err);
++ goto failure;
++ }
++
++ if (channel == 0)
++ *master_dev = dev;
++
++ return 0;
++
++failure:
++ kvaser_pci_del_chan(dev);
++ return err;
++}
++
++static int __devinit kvaser_pci_init_one(struct pci_dev *pdev,
++ const struct pci_device_id *ent)
++{
++ int err;
++ struct net_device *master_dev = NULL;
++ struct sja1000_priv *priv;
++ struct kvaser_pci *board;
++ int no_channels;
++ void __iomem *base_addr = NULL;
++ void __iomem *conf_addr = NULL;
++ void __iomem *res_addr = NULL;
++ int i;
++
++ dev_info(&pdev->dev, "initializing device %04x:%04x\n",
++ pdev->vendor, pdev->device);
++
++ err = pci_enable_device(pdev);
++ if (err)
++ goto failure;
++
++ err = pci_request_regions(pdev, DRV_NAME);
++ if (err)
++ goto failure_release_pci;
++
++ /*S5920*/
++ conf_addr = pci_iomap(pdev, 0, PCI_CONFIG_PORT_SIZE);
++ if (conf_addr == 0) {
++ err = -ENODEV;
++ goto failure_iounmap;
++ }
++
++ /*XILINX board wide address*/
++ res_addr = pci_iomap(pdev, 2, PCI_PORT_XILINX_SIZE);
++ if (res_addr == 0) {
++ err = -ENOMEM;
++ goto failure_iounmap;
++ }
++
++ base_addr = pci_iomap(pdev, 1, PCI_PORT_SIZE);
++ if (base_addr == 0) {
++ err = -ENOMEM;
++ goto failure_iounmap;
++ }
++
++ no_channels = number_of_sja1000_chip(base_addr);
++ if (no_channels == 0) {
++ err = -ENOMEM;
++ goto failure_iounmap;
++ }
++
++ for (i = 0; i < no_channels; i++) {
++ err = kvaser_pci_add_chan(pdev, i, &master_dev,
++ conf_addr, res_addr,
++ (unsigned long)base_addr);
++ if (err)
++ goto failure_cleanup;
++ }
++
++ priv = netdev_priv(master_dev);
++ board = priv->priv;
++
++ dev_info(&pdev->dev, "xilinx version=%d number of channels=%d\n",
++ board->xilinx_ver, board->no_channels);
++
++ pci_set_drvdata(pdev, master_dev);
++ return 0;
++
++failure_cleanup:
++ kvaser_pci_del_chan(master_dev);
++
++failure_iounmap:
++ if (conf_addr == 0)
++ pci_iounmap(pdev, conf_addr);
++ if (res_addr == 0)
++ pci_iounmap(pdev, res_addr);
++ if (base_addr == 0)
++ pci_iounmap(pdev, base_addr);
++
++ pci_release_regions(pdev);
++
++failure_release_pci:
++ pci_disable_device(pdev);
++
++failure:
++ return err;
++
++}
++
++static void __devexit kvaser_pci_remove_one(struct pci_dev *pdev)
++{
++ struct net_device *dev = pci_get_drvdata(pdev);
++
++ kvaser_pci_del_chan(dev);
++
++ pci_release_regions(pdev);
++ pci_disable_device(pdev);
++ pci_set_drvdata(pdev, NULL);
++}
++
++static struct pci_driver kvaser_pci_driver = {
++ .name = DRV_NAME,
++ .id_table = kvaser_pci_tbl,
++ .probe = kvaser_pci_init_one,
++ .remove = __devexit_p(kvaser_pci_remove_one),
++};
++
++static int __init kvaser_pci_init(void)
++{
++ return pci_register_driver(&kvaser_pci_driver);
++}
++
++static void __exit kvaser_pci_exit(void)
++{
++ pci_unregister_driver(&kvaser_pci_driver);
++}
++
++module_init(kvaser_pci_init);
++module_exit(kvaser_pci_exit);
+Index: net-next-2.6/drivers/net/can/sja1000/Makefile
+===================================================================
+--- net-next-2.6.orig/drivers/net/can/sja1000/Makefile
++++ net-next-2.6/drivers/net/can/sja1000/Makefile
+@@ -5,5 +5,6 @@
+ obj-$(CONFIG_CAN_SJA1000) += sja1000.o
+ obj-$(CONFIG_CAN_SJA1000_PLATFORM) += sja1000_platform.o
+ obj-$(CONFIG_CAN_EMS_PCI) += ems_pci.o
++obj-$(CONFIG_CAN_KVASER_PCI) += kvaser_pci.o
+
+ ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
--- /dev/null
+[PATCH 9/9] Socket-CAN: driver for the Freescale MSCAN controller
+
+This patch adds the generic Socket-CAN driver for the MSCAN controller
+available on some Freescale processor chips like the PowerPC MPC5200,
+MPC512x or the m86k MC68HC12. It also includes an OF platform driver
+for the MPC5200.
+
+Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
+---
+ drivers/net/can/Kconfig | 20 +
+ drivers/net/can/Makefile | 1
+ drivers/net/can/mscan/Makefile | 9
+ drivers/net/can/mscan/mpc52xx_can.c | 293 +++++++++++++++
+ drivers/net/can/mscan/mscan.c | 681 ++++++++++++++++++++++++++++++++++++
+ drivers/net/can/mscan/mscan.h | 237 ++++++++++++
+ 6 files changed, 1241 insertions(+)
+
+Index: net-next-2.6/drivers/net/can/Kconfig
+===================================================================
+--- net-next-2.6.orig/drivers/net/can/Kconfig
++++ net-next-2.6/drivers/net/can/Kconfig
+@@ -70,4 +70,24 @@ config CAN_KVASER_PCI
+ This driver is for the the PCIcanx and PCIcan cards (1, 2 or
+ 4 channel) from Kvaser (http://www.kvaser.com).
+
++config CAN_MSCAN
++ depends on CAN_DEV && (PPC || M68K || M68KNOMMU)
++ tristate "Freescale MSCAN based chips"
++ ---help---
++ The Motorola Scalable Controller Area Network (MSCAN) definition
++ is based on the MSCAN12 definition which is the specific
++ implementation of the Motorola Scalable CAN concept targeted for
++ the Motorola MC68HC12 Microcontroller Family.
++
++config CAN_MPC52XX
++ tristate "Freescale MPC5200 onboard CAN controller"
++ depends on CAN_MSCAN && PPC_MPC52xx
++ default N
++ ---help---
++ If you say yes here you get support for Freescale MPC5200
++ onboard dualCAN controller.
++
++ This driver can also be built as a module. If so, the module
++ will be called mpc52xx_can.
++
+ endmenu
+Index: net-next-2.6/drivers/net/can/Makefile
+===================================================================
+--- net-next-2.6.orig/drivers/net/can/Makefile
++++ net-next-2.6/drivers/net/can/Makefile
+@@ -8,5 +8,6 @@ obj-$(CONFIG_CAN_DEV) += can-dev.o
+ can-dev-y := dev.o sysfs.o
+
+ obj-$(CONFIG_CAN_SJA1000) += sja1000/
++obj-$(CONFIG_CAN_MSCAN) += mscan/
+
+ ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
+Index: net-next-2.6/drivers/net/can/mscan/mpc52xx_can.c
+===================================================================
+--- /dev/null
++++ net-next-2.6/drivers/net/can/mscan/mpc52xx_can.c
+@@ -0,0 +1,293 @@
++/*
++ * CAN bus driver for the Freescale MPC52xx embedded CPU.
++ *
++ * Copyright (C) 2004-2005 Andrey Volkov <avolkov@varma-el.com>,
++ * Varma Electronics Oy
++ * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.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 <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include <linux/netdevice.h>
++#include <linux/can.h>
++#include <linux/can/dev.h>
++#include <linux/of_platform.h>
++#include <sysdev/fsl_soc.h>
++#include <linux/io.h>
++#include <asm/mpc52xx.h>
++
++#include "mscan.h"
++
++
++#define DRV_NAME "mpc52xx_can"
++
++static struct of_device_id mpc52xx_cdm_ids[] __devinitdata = {
++ { .compatible = "fsl,mpc5200-cdm", },
++ { .compatible = "fsl,mpc5200b-cdm", },
++ {}
++};
++
++/*
++ * Get the frequency of the external oscillator clock connected
++ * to the SYS_XTAL_IN pin, or retrun 0 if it cannot be determined.
++ */
++static unsigned int __devinit mpc52xx_can_xtal_freq(struct device_node *np)
++{
++ struct mpc52xx_cdm __iomem *cdm;
++ struct device_node *np_cdm;
++ unsigned int freq;
++ u32 val;
++
++ freq = mpc52xx_find_ipb_freq(np);
++ if (!freq)
++ return 0;
++
++ /*
++ * Detemine SYS_XTAL_IN frequency from the clock domain settings
++ */
++ np_cdm = of_find_matching_node(NULL, mpc52xx_cdm_ids);
++ cdm = of_iomap(np_cdm, 0);
++ of_node_put(np_cdm);
++ if (!np_cdm) {
++ printk(KERN_ERR "%s() failed abnormally\n", __func__);
++ return 0;
++ }
++
++ if (in_8(&cdm->ipb_clk_sel) & 0x1)
++ freq *= 2;
++ val = in_be32(&cdm->rstcfg);
++ if (val & (1 << 5))
++ freq *= 8;
++ else
++ freq *= 4;
++ if (val & (1 << 6))
++ freq /= 12;
++ else
++ freq /= 16;
++
++ iounmap(cdm);
++
++ return freq;
++}
++
++/*
++ * Get frequency of the MSCAN clock source
++ *
++ * Either the oscillator clock (SYS_XTAL_IN) or the IP bus clock (IP_CLK)
++ * can be selected. According to the MPC5200 user's manual, the oscillator
++ * clock is the better choice as it has less jitter but due to a hardware
++ * bug, it can not be selected for the old MPC5200 Rev. A chips.
++ */
++
++static unsigned int __devinit mpc52xx_can_clock_freq(struct device_node *np,
++ int clock_src)
++{
++ unsigned int pvr;
++
++ pvr = mfspr(SPRN_PVR);
++
++ if (clock_src == MSCAN_CLKSRC_BUS || pvr == 0x80822011)
++ return mpc52xx_find_ipb_freq(np);
++
++ return mpc52xx_can_xtal_freq(np);
++}
++
++static int __devinit mpc52xx_can_probe(struct of_device *ofdev,
++ const struct of_device_id *id)
++{
++ struct device_node *np = ofdev->node;
++ struct net_device *dev;
++ struct can_priv *priv;
++ struct resource res;
++ void __iomem *base;
++ int err, irq, res_size, clock_src;
++
++ err = of_address_to_resource(np, 0, &res);
++ if (err) {
++ dev_err(&ofdev->dev, "invalid address\n");
++ return err;
++ }
++
++ res_size = res.end - res.start + 1;
++
++ if (!request_mem_region(res.start, res_size, DRV_NAME)) {
++ dev_err(&ofdev->dev, "couldn't request %#x..%#x\n",
++ res.start, res.end);
++ return -EBUSY;
++ }
++
++ base = ioremap_nocache(res.start, res_size);
++ if (!base) {
++ dev_err(&ofdev->dev, "couldn't ioremap %#x..%#x\n",
++ res.start, res.end);
++ err = -ENOMEM;
++ goto exit_release_mem;
++ }
++
++ irq = irq_of_parse_and_map(np, 0);
++ if (irq == NO_IRQ) {
++ dev_err(&ofdev->dev, "no irq found\n");
++ err = -ENODEV;
++ goto exit_unmap_mem;
++ }
++
++ dev = alloc_mscandev();
++ if (!dev) {
++ err = -ENOMEM;
++ goto exit_dispose_irq;
++ }
++
++ dev->base_addr = (unsigned long)base;
++ dev->irq = irq;
++
++ priv = netdev_priv(dev);
++
++ /*
++ * Either the oscillator clock (SYS_XTAL_IN) or the IP bus clock
++ * (IP_CLK) can be selected as MSCAN clock source. According to
++ * the MPC5200 user's manual, the oscillator clock is the better
++ * choice as it has less jitter. For this reason, it is selected
++ * by default.
++ */
++ if (of_get_property(np, "clock-ipb", NULL))
++ clock_src = MSCAN_CLKSRC_BUS;
++ else
++ clock_src = MSCAN_CLKSRC_XTAL;
++ priv->bittiming.clock = mpc52xx_can_clock_freq(np, clock_src);
++ if (!priv->bittiming.clock) {
++ dev_err(&ofdev->dev, "couldn't get MSCAN clock frequency\n");
++ err = -ENODEV;
++ goto exit_free_mscan;
++ }
++
++ SET_NETDEV_DEV(dev, &ofdev->dev);
++
++ err = register_mscandev(dev, clock_src);
++ if (err) {
++ dev_err(&ofdev->dev, "registering %s failed (err=%d)\n",
++ DRV_NAME, err);
++ goto exit_free_mscan;
++ }
++
++ dev_set_drvdata(&ofdev->dev, dev);
++
++ dev_info(&ofdev->dev, "MSCAN at 0x%lx, irq %d, clock %dHZ\n",
++ dev->base_addr, dev->irq, priv->bittiming.clock);
++
++ return 0;
++
++exit_free_mscan:
++ free_candev(dev);
++exit_dispose_irq:
++ irq_dispose_mapping(irq);
++exit_unmap_mem:
++ iounmap(base);
++exit_release_mem:
++ release_mem_region(res.start, res_size);
++
++ return err;
++}
++
++static int __devexit mpc52xx_can_remove(struct of_device *ofdev)
++{
++ struct net_device *dev = dev_get_drvdata(&ofdev->dev);
++ struct device_node *np = ofdev->node;
++ struct resource res;
++
++ dev_set_drvdata(&ofdev->dev, NULL);
++
++ unregister_mscandev(dev);
++ iounmap((void __iomem *)dev->base_addr);
++ irq_dispose_mapping(dev->irq);
++ free_candev(dev);
++
++ of_address_to_resource(np, 0, &res);
++ release_mem_region(res.start, res.end - res.start + 1);
++
++ return 0;
++}
++
++static struct mscan_regs saved_regs;
++static int mpc52xx_can_suspend(struct of_device *ofdev, pm_message_t state)
++{
++ struct net_device *dev = dev_get_drvdata(&ofdev->dev);
++ struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
++
++ _memcpy_fromio(&saved_regs, regs, sizeof(*regs));
++
++ return 0;
++}
++
++static int mpc52xx_can_resume(struct of_device *ofdev)
++{
++ struct net_device *dev = dev_get_drvdata(&ofdev->dev);
++ struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
++
++ regs->canctl0 |= MSCAN_INITRQ;
++ while ((regs->canctl1 & MSCAN_INITAK) == 0)
++ udelay(10);
++
++ regs->canctl1 = saved_regs.canctl1;
++ regs->canbtr0 = saved_regs.canbtr0;
++ regs->canbtr1 = saved_regs.canbtr1;
++ regs->canidac = saved_regs.canidac;
++
++ /* restore masks, buffers etc. */
++ _memcpy_toio(®s->canidar1_0, (void *)&saved_regs.canidar1_0,
++ sizeof(*regs) - offsetof(struct mscan_regs, canidar1_0));
++
++ regs->canctl0 &= ~MSCAN_INITRQ;
++ regs->cantbsel = saved_regs.cantbsel;
++ regs->canrier = saved_regs.canrier;
++ regs->cantier = saved_regs.cantier;
++ regs->canctl0 = saved_regs.canctl0;
++
++ return 0;
++}
++
++static struct of_device_id __devinitdata mpc52xx_can_table[] = {
++ {.compatible = "fsl,mpc5200-mscan"},
++ {.compatible = "fsl,mpc5200b-mscan"},
++ {},
++};
++
++static struct of_platform_driver mpc52xx_can_driver = {
++ .owner = THIS_MODULE,
++ .name = "mpc52xx_can",
++ .probe = mpc52xx_can_probe,
++ .remove = __devexit_p(mpc52xx_can_remove),
++ .suspend = mpc52xx_can_suspend,
++ .resume = mpc52xx_can_resume,
++ .match_table = mpc52xx_can_table,
++};
++
++static int __init mpc52xx_can_init(void)
++{
++ return of_register_platform_driver(&mpc52xx_can_driver);
++}
++module_init(mpc52xx_can_init);
++
++static void __exit mpc52xx_can_exit(void)
++{
++ return of_unregister_platform_driver(&mpc52xx_can_driver);
++};
++module_exit(mpc52xx_can_exit);
++
++MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
++MODULE_DESCRIPTION("Freescale MPC5200 CAN driver");
++MODULE_LICENSE("GPL v2");
+Index: net-next-2.6/drivers/net/can/mscan/mscan.c
+===================================================================
+--- /dev/null
++++ net-next-2.6/drivers/net/can/mscan/mscan.c
+@@ -0,0 +1,681 @@
++/*
++ * CAN bus driver for the alone generic (as possible as) MSCAN controller.
++ *
++ * Copyright (C) 2005-2006 Andrey Volkov <avolkov@varma-el.com>,
++ * Varma Electronics Oy
++ * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.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 <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++#include <linux/netdevice.h>
++#include <linux/if_arp.h>
++#include <linux/if_ether.h>
++#include <linux/list.h>
++#include <linux/can.h>
++#include <linux/can/dev.h>
++#include <linux/can/error.h>
++#include <linux/io.h>
++
++#include "mscan.h"
++
++#define MSCAN_NORMAL_MODE 0
++#define MSCAN_SLEEP_MODE MSCAN_SLPRQ
++#define MSCAN_INIT_MODE (MSCAN_INITRQ | MSCAN_SLPRQ)
++#define MSCAN_POWEROFF_MODE (MSCAN_CSWAI | MSCAN_SLPRQ)
++#define MSCAN_SET_MODE_RETRIES 255
++
++#define BTR0_BRP_MASK 0x3f
++#define BTR0_SJW_SHIFT 6
++#define BTR0_SJW_MASK (0x3 << BTR0_SJW_SHIFT)
++
++#define BTR1_TSEG1_MASK 0xf
++#define BTR1_TSEG2_SHIFT 4
++#define BTR1_TSEG2_MASK (0x7 << BTR1_TSEG2_SHIFT)
++#define BTR1_SAM_SHIFT 7
++
++#define BTR0_SET_BRP(brp) (((brp) - 1) & BTR0_BRP_MASK)
++#define BTR0_SET_SJW(sjw) ((((sjw) - 1) << BTR0_SJW_SHIFT) & \
++ BTR0_SJW_MASK)
++
++#define BTR1_SET_TSEG1(tseg1) (((tseg1) - 1) & BTR1_TSEG1_MASK)
++#define BTR1_SET_TSEG2(tseg2) ((((tseg2) - 1) << BTR1_TSEG2_SHIFT) & \
++ BTR1_TSEG2_MASK)
++#define BTR1_SET_SAM(sam) (((sam) & 1) << BTR1_SAM_SHIFT)
++
++static struct can_bittiming_const mscan_bittiming_const = {
++ .tseg1_min = 4,
++ .tseg1_max = 16,
++ .tseg2_min = 2,
++ .tseg2_max = 8,
++ .sjw_max = 4,
++ .brp_min = 1,
++ .brp_max = 64,
++ .brp_inc = 1,
++};
++
++struct mscan_state {
++ u8 mode;
++ u8 canrier;
++ u8 cantier;
++};
++
++#define TX_QUEUE_SIZE 3
++
++struct tx_queue_entry {
++ struct list_head list;
++ u8 mask;
++ u8 id;
++};
++
++struct mscan_priv {
++ struct can_priv can;
++ long open_time;
++ unsigned long flags;
++ u8 shadow_statflg;
++ u8 shadow_canrier;
++ u8 cur_pri;
++ u8 tx_active;
++
++ struct list_head tx_head;
++ struct tx_queue_entry tx_queue[TX_QUEUE_SIZE];
++ struct napi_struct napi;
++};
++
++#define F_RX_PROGRESS 0
++#define F_TX_PROGRESS 1
++#define F_TX_WAIT_ALL 2
++
++static enum can_state state_map[] = {
++ CAN_STATE_ACTIVE,
++ CAN_STATE_BUS_WARNING,
++ CAN_STATE_BUS_PASSIVE,
++ CAN_STATE_BUS_OFF
++};
++
++static int mscan_set_mode(struct net_device *dev, u8 mode)
++{
++ struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
++ struct mscan_priv *priv = netdev_priv(dev);
++ int ret = 0;
++ int i;
++ u8 canctl1;
++
++ if (mode != MSCAN_NORMAL_MODE) {
++
++ if (priv->tx_active) {
++ /* Abort transfers before going to sleep */
++ out_8(®s->cantier, 0);
++ out_8(®s->cantarq, priv->tx_active);
++ out_8(®s->cantier, priv->tx_active);
++ }
++
++ canctl1 = in_8(®s->canctl1);
++ if ((mode & MSCAN_SLPRQ) && (canctl1 & MSCAN_SLPAK) == 0) {
++ out_8(®s->canctl0,
++ in_8(®s->canctl0) | MSCAN_SLPRQ);
++ for (i = 0; i < MSCAN_SET_MODE_RETRIES; i++) {
++ if (in_8(®s->canctl1) & MSCAN_SLPAK)
++ break;
++ udelay(100);
++ }
++ if (i >= MSCAN_SET_MODE_RETRIES)
++ ret = -ENODEV;
++ }
++ if (!ret)
++ priv->can.state = CAN_STATE_SLEEPING;
++
++ if (!ret && (mode & MSCAN_INITRQ)
++ && (canctl1 & MSCAN_INITAK) == 0) {
++ out_8(®s->canctl0,
++ in_8(®s->canctl0) | MSCAN_INITRQ);
++ for (i = 0; i < MSCAN_SET_MODE_RETRIES; i++) {
++ if (in_8(®s->canctl1) & MSCAN_INITAK)
++ break;
++ }
++ if (i >= MSCAN_SET_MODE_RETRIES)
++ ret = -ENODEV;
++ }
++ if (!ret)
++ priv->can.state = CAN_STATE_STOPPED;
++
++ if (!ret && (mode & MSCAN_CSWAI))
++ out_8(®s->canctl0,
++ in_8(®s->canctl0) | MSCAN_CSWAI);
++
++ } else {
++ canctl1 = in_8(®s->canctl1);
++ if (canctl1 & (MSCAN_SLPAK | MSCAN_INITAK)) {
++ out_8(®s->canctl0, in_8(®s->canctl0) &
++ ~(MSCAN_SLPRQ | MSCAN_INITRQ));
++ for (i = 0; i < MSCAN_SET_MODE_RETRIES; i++) {
++ canctl1 = in_8(®s->canctl1);
++ if (!(canctl1 & (MSCAN_INITAK | MSCAN_SLPAK)))
++ break;
++ }
++ if (i >= MSCAN_SET_MODE_RETRIES)
++ ret = -ENODEV;
++ else
++ priv->can.state = CAN_STATE_ACTIVE;
++ }
++ }
++ return ret;
++}
++
++static int mscan_start(struct net_device *dev)
++{
++ struct mscan_priv *priv = netdev_priv(dev);
++ struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
++ u8 canrflg;
++ int err;
++
++ out_8(®s->canrier, 0);
++
++ INIT_LIST_HEAD(&priv->tx_head);
++ priv->cur_pri = 0;
++ priv->tx_active = 0;
++ priv->shadow_canrier = 0;
++ priv->flags = 0;
++
++ err = mscan_set_mode(dev, MSCAN_NORMAL_MODE);
++ if (err)
++ return err;
++
++ canrflg = in_8(®s->canrflg);
++ priv->shadow_statflg = canrflg & MSCAN_STAT_MSK;
++ priv->can.state = state_map[max(MSCAN_STATE_RX(canrflg),
++ MSCAN_STATE_TX(canrflg))];
++ out_8(®s->cantier, 0);
++
++ /* Enable receive interrupts. */
++ out_8(®s->canrier, MSCAN_OVRIE | MSCAN_RXFIE | MSCAN_CSCIE |
++ MSCAN_RSTATE1 | MSCAN_RSTATE0 | MSCAN_TSTATE1 | MSCAN_TSTATE0);
++
++ return 0;
++}
++
++static int mscan_start_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++ struct can_frame *frame = (struct can_frame *)skb->data;
++ struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
++ struct mscan_priv *priv = netdev_priv(dev);
++ int i, rtr, buf_id;
++ u32 can_id;
++
++ if (frame->can_dlc > 8)
++ return -EINVAL;
++
++ out_8(®s->cantier, 0);
++
++ i = ~priv->tx_active & MSCAN_TXE;
++ buf_id = ffs(i) - 1;
++ switch (hweight8(i)) {
++ case 0:
++ netif_stop_queue(dev);
++ dev_err(ND2D(dev), "BUG! Tx Ring full when queue awake!\n");
++ return NETDEV_TX_BUSY;
++ case 1:
++ /* if buf_id < 3, then current frame will be send out of order,
++ since buffer with lower id have higher priority (hell..) */
++ if (buf_id < 3)
++ priv->cur_pri++;
++ if (priv->cur_pri == 0xff)
++ set_bit(F_TX_WAIT_ALL, &priv->flags);
++ netif_stop_queue(dev);
++ case 2:
++ set_bit(F_TX_PROGRESS, &priv->flags);
++ }
++ out_8(®s->cantbsel, i);
++
++ rtr = frame->can_id & CAN_RTR_FLAG;
++
++ if (frame->can_id & CAN_EFF_FLAG) {
++ can_id = (frame->can_id & CAN_EFF_MASK) << 1;
++ if (rtr)
++ can_id |= 1;
++ out_be16(®s->tx.idr3_2, can_id);
++
++ can_id >>= 16;
++ can_id = (can_id & 0x7) | ((can_id << 2) & 0xffe0) | (3 << 3);
++ } else {
++ can_id = (frame->can_id & CAN_SFF_MASK) << 5;
++ if (rtr)
++ can_id |= 1 << 4;
++ }
++ out_be16(®s->tx.idr1_0, can_id);
++
++ if (!rtr) {
++ void __iomem *data = ®s->tx.dsr1_0;
++ u16 *payload = (u16 *) frame->data;
++ /*Its safe to write into dsr[dlc+1] */
++ for (i = 0; i < (frame->can_dlc + 1) / 2; i++) {
++ out_be16(data, *payload++);
++ data += 2 + _MSCAN_RESERVED_DSR_SIZE;
++ }
++ }
++
++ out_8(®s->tx.dlr, frame->can_dlc);
++ out_8(®s->tx.tbpr, priv->cur_pri);
++
++ /* Start transmission. */
++ out_8(®s->cantflg, 1 << buf_id);
++
++ if (!test_bit(F_TX_PROGRESS, &priv->flags))
++ dev->trans_start = jiffies;
++
++ list_add_tail(&priv->tx_queue[buf_id].list, &priv->tx_head);
++
++ can_put_echo_skb(skb, dev, buf_id);
++
++ /* Enable interrupt. */
++ priv->tx_active |= 1 << buf_id;
++ out_8(®s->cantier, priv->tx_active);
++
++ return NETDEV_TX_OK;
++}
++
++static inline int check_set_state(struct net_device *dev, u8 canrflg)
++{
++ struct mscan_priv *priv = netdev_priv(dev);
++ enum can_state state;
++ int ret = 0;
++
++ if (!(canrflg & MSCAN_CSCIF) || priv->can.state > CAN_STATE_BUS_OFF)
++ return 0;
++
++ state = state_map[max(MSCAN_STATE_RX(canrflg),
++ MSCAN_STATE_TX(canrflg))];
++ if (priv->can.state < state)
++ ret = 1;
++ if (state == CAN_STATE_BUS_OFF)
++ can_bus_off(dev);
++ priv->can.state = state;
++ return ret;
++}
++
++static int mscan_rx_poll(struct napi_struct *napi, int quota)
++{
++ struct mscan_priv *priv = container_of(napi, struct mscan_priv, napi);
++ struct net_device *dev = napi->dev;
++ struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
++ struct net_device_stats *stats = &dev->stats;
++ int npackets = 0;
++ int ret = 1;
++ struct sk_buff *skb;
++ struct can_frame *frame;
++ u32 can_id;
++ u8 canrflg;
++ int i;
++
++ while (npackets < quota && ((canrflg = in_8(®s->canrflg)) &
++ (MSCAN_RXF | MSCAN_ERR_IF))) {
++
++ skb = dev_alloc_skb(sizeof(struct can_frame));
++ if (!skb) {
++ if (printk_ratelimit())
++ dev_notice(ND2D(dev), "packet dropped\n");
++ stats->rx_dropped++;
++ out_8(®s->canrflg, canrflg);
++ continue;
++ }
++
++ frame = (struct can_frame *)skb_put(skb, sizeof(*frame));
++ memset(frame, 0, sizeof(*frame));
++
++ if (canrflg & MSCAN_RXF) {
++ can_id = in_be16(®s->rx.idr1_0);
++ if (can_id & (1 << 3)) {
++ frame->can_id = CAN_EFF_FLAG;
++ can_id = ((can_id << 16) |
++ in_be16(®s->rx.idr3_2));
++ can_id = ((can_id & 0xffe00000) |
++ ((can_id & 0x7ffff) << 2)) >> 2;
++ } else {
++ can_id >>= 4;
++ frame->can_id = 0;
++ }
++
++ frame->can_id |= can_id >> 1;
++ if (can_id & 1)
++ frame->can_id |= CAN_RTR_FLAG;
++ frame->can_dlc = in_8(®s->rx.dlr) & 0xf;
++
++ if (!(frame->can_id & CAN_RTR_FLAG)) {
++ void __iomem *data = ®s->rx.dsr1_0;
++ u16 *payload = (u16 *) frame->data;
++ for (i = 0; i < (frame->can_dlc + 1) / 2; i++) {
++ *payload++ = in_be16(data);
++ data += 2 + _MSCAN_RESERVED_DSR_SIZE;
++ }
++ }
++
++ out_8(®s->canrflg, MSCAN_RXF);
++ dev->last_rx = jiffies;
++ stats->rx_packets++;
++ stats->rx_bytes += frame->can_dlc;
++ } else if (canrflg & MSCAN_ERR_IF) {
++ dev_dbg(ND2D(dev), "error interrupt (canrflg=%#x)\n",
++ canrflg);
++ frame->can_id = CAN_ERR_FLAG;
++
++ if (canrflg & MSCAN_OVRIF) {
++ frame->can_id |= CAN_ERR_CRTL;
++ frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
++ stats->rx_over_errors++;
++ } else
++ frame->data[1] = 0;
++
++ if (check_set_state(dev, canrflg)) {
++ frame->can_id |= CAN_ERR_CRTL;
++ switch (priv->can.state) {
++ case CAN_STATE_BUS_WARNING:
++ if ((priv->shadow_statflg &
++ MSCAN_RSTAT_MSK) <
++ (canrflg & MSCAN_RSTAT_MSK))
++ frame->data[1] |=
++ CAN_ERR_CRTL_RX_WARNING;
++
++ if ((priv->shadow_statflg &
++ MSCAN_TSTAT_MSK) <
++ (canrflg & MSCAN_TSTAT_MSK))
++ frame->data[1] |=
++ CAN_ERR_CRTL_TX_WARNING;
++ break;
++ case CAN_STATE_BUS_PASSIVE:
++ frame->data[1] |=
++ CAN_ERR_CRTL_RX_PASSIVE;
++ break;
++ case CAN_STATE_BUS_OFF:
++ frame->can_id |= CAN_ERR_BUSOFF;
++ frame->can_id &= ~CAN_ERR_CRTL;
++ break;
++ default:
++ break;
++ }
++ }
++ priv->shadow_statflg = canrflg & MSCAN_STAT_MSK;
++ frame->can_dlc = CAN_ERR_DLC;
++ out_8(®s->canrflg, MSCAN_ERR_IF);
++ }
++
++ npackets++;
++ skb->dev = dev;
++ skb->protocol = __constant_htons(ETH_P_CAN);
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
++ netif_receive_skb(skb);
++ }
++
++ if (!(in_8(®s->canrflg) & (MSCAN_RXF | MSCAN_ERR_IF))) {
++ napi_complete(&priv->napi);
++ clear_bit(F_RX_PROGRESS, &priv->flags);
++ if (priv->can.state < CAN_STATE_BUS_OFF)
++ out_8(®s->canrier, priv->shadow_canrier);
++ ret = 0;
++ }
++ return ret;
++}
++
++static irqreturn_t mscan_isr(int irq, void *dev_id)
++{
++ struct net_device *dev = (struct net_device *)dev_id;
++ struct mscan_priv *priv = netdev_priv(dev);
++ struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
++ struct net_device_stats *stats = &dev->stats;
++ u8 cantier, cantflg, canrflg;
++ irqreturn_t ret = IRQ_NONE;
++
++ cantier = in_8(®s->cantier) & MSCAN_TXE;
++ cantflg = in_8(®s->cantflg) & cantier;
++
++ if (cantier && cantflg) {
++
++ struct list_head *tmp, *pos;
++
++ list_for_each_safe(pos, tmp, &priv->tx_head) {
++ struct tx_queue_entry *entry =
++ list_entry(pos, struct tx_queue_entry, list);
++ u8 mask = entry->mask;
++
++ if (!(cantflg & mask))
++ continue;
++
++ out_8(®s->cantbsel, mask);
++ stats->tx_bytes += in_8(®s->tx.dlr);
++ stats->tx_packets++;
++ can_get_echo_skb(dev, entry->id);
++ priv->tx_active &= ~mask;
++ list_del(pos);
++ }
++
++ if (list_empty(&priv->tx_head)) {
++ clear_bit(F_TX_WAIT_ALL, &priv->flags);
++ clear_bit(F_TX_PROGRESS, &priv->flags);
++ priv->cur_pri = 0;
++ } else
++ dev->trans_start = jiffies;
++
++ if (!test_bit(F_TX_WAIT_ALL, &priv->flags))
++ netif_wake_queue(dev);
++
++ out_8(®s->cantier, priv->tx_active);
++ ret = IRQ_HANDLED;
++ }
++
++ canrflg = in_8(®s->canrflg);
++ if ((canrflg & ~MSCAN_STAT_MSK) &&
++ !test_and_set_bit(F_RX_PROGRESS, &priv->flags)) {
++ if (canrflg & ~MSCAN_STAT_MSK) {
++ priv->shadow_canrier = in_8(®s->canrier);
++ out_8(®s->canrier, 0);
++ napi_schedule(&priv->napi);
++ ret = IRQ_HANDLED;
++ } else
++ clear_bit(F_RX_PROGRESS, &priv->flags);
++ }
++ return ret;
++}
++
++static int mscan_do_set_mode(struct net_device *dev, enum can_mode mode)
++{
++
++ struct mscan_priv *priv = netdev_priv(dev);
++ int ret = 0;
++
++ if (!priv->open_time)
++ return -EINVAL;
++
++ switch (mode) {
++ case CAN_MODE_SLEEP:
++ case CAN_MODE_STOP:
++ netif_stop_queue(dev);
++ mscan_set_mode(dev,
++ (mode ==
++ CAN_MODE_STOP) ? MSCAN_INIT_MODE :
++ MSCAN_SLEEP_MODE);
++ break;
++ case CAN_MODE_START:
++ if (priv->can.state <= CAN_STATE_BUS_OFF)
++ mscan_set_mode(dev, MSCAN_INIT_MODE);
++ ret = mscan_start(dev);
++ if (ret)
++ break;
++ if (netif_queue_stopped(dev))
++ netif_wake_queue(dev);
++ break;
++
++ default:
++ ret = -EOPNOTSUPP;
++ break;
++ }
++ return ret;
++}
++
++static int mscan_do_set_bittiming(struct net_device *dev)
++{
++ struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
++ struct mscan_priv *priv = netdev_priv(dev);
++ struct can_bittiming *bt = &priv->can.bittiming;
++ u8 btr0, btr1;
++
++ btr0 = BTR0_SET_BRP(bt->brp) | BTR0_SET_SJW(bt->sjw);
++ btr1 = (BTR1_SET_TSEG1(bt->prop_seg + bt->phase_seg1) |
++ BTR1_SET_TSEG2(bt->phase_seg2) |
++ BTR1_SET_SAM(priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES));
++
++ dev_info(ND2D(dev), "setting BTR0=0x%02x BTR1=0x%02x\n", btr0, btr1);
++
++ out_8(®s->canbtr0, btr0);
++ out_8(®s->canbtr1, btr1);
++
++ return 0;
++}
++
++static int mscan_open(struct net_device *dev)
++{
++ int ret;
++ struct mscan_priv *priv = netdev_priv(dev);
++ struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
++
++ /* determine and set bittime */
++ ret = can_set_bittiming(dev);
++ if (ret)
++ return ret;
++
++ napi_enable(&priv->napi);
++ ret = request_irq(dev->irq, mscan_isr, 0, dev->name, dev);
++
++ if (ret < 0) {
++ napi_disable(&priv->napi);
++ printk(KERN_ERR "%s - failed to attach interrupt\n",
++ dev->name);
++ return ret;
++ }
++
++ priv->open_time = jiffies;
++
++ out_8(®s->canctl1, in_8(®s->canctl1) & ~MSCAN_LISTEN);
++
++ ret = mscan_start(dev);
++ if (ret)
++ return ret;
++
++ netif_start_queue(dev);
++
++ return 0;
++}
++
++static int mscan_close(struct net_device *dev)
++{
++ struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
++ struct mscan_priv *priv = netdev_priv(dev);
++
++ napi_disable(&priv->napi);
++
++ out_8(®s->cantier, 0);
++ out_8(®s->canrier, 0);
++ free_irq(dev->irq, dev);
++ mscan_set_mode(dev, MSCAN_INIT_MODE);
++ can_close_cleanup(dev);
++ netif_stop_queue(dev);
++ priv->open_time = 0;
++
++ return 0;
++}
++
++static const struct net_device_ops mscan_netdev_ops = {
++ .ndo_open = mscan_open,
++ .ndo_stop = mscan_close,
++ .ndo_start_xmit = mscan_start_xmit,
++};
++
++int register_mscandev(struct net_device *dev, int clock_src)
++{
++ struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
++ u8 ctl1;
++
++ ctl1 = in_8(®s->canctl1);
++ if (clock_src)
++ ctl1 |= MSCAN_CLKSRC;
++ else
++ ctl1 &= ~MSCAN_CLKSRC;
++
++ ctl1 |= MSCAN_CANE;
++ out_8(®s->canctl1, ctl1);
++ udelay(100);
++
++ /* acceptance mask/acceptance code (accept everything) */
++ out_be16(®s->canidar1_0, 0);
++ out_be16(®s->canidar3_2, 0);
++ out_be16(®s->canidar5_4, 0);
++ out_be16(®s->canidar7_6, 0);
++
++ out_be16(®s->canidmr1_0, 0xffff);
++ out_be16(®s->canidmr3_2, 0xffff);
++ out_be16(®s->canidmr5_4, 0xffff);
++ out_be16(®s->canidmr7_6, 0xffff);
++ /* Two 32 bit Acceptance Filters */
++ out_8(®s->canidac, MSCAN_AF_32BIT);
++
++ mscan_set_mode(dev, MSCAN_INIT_MODE);
++
++ return register_candev(dev);
++}
++EXPORT_SYMBOL(register_mscandev);
++
++void unregister_mscandev(struct net_device *dev)
++{
++ struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
++ mscan_set_mode(dev, MSCAN_INIT_MODE);
++ out_8(®s->canctl1, in_8(®s->canctl1) & ~MSCAN_CANE);
++ unregister_candev(dev);
++}
++EXPORT_SYMBOL(unregister_mscandev);
++
++struct net_device *alloc_mscandev(void)
++{
++ struct net_device *dev;
++ struct mscan_priv *priv;
++ int i;
++
++ dev = alloc_candev(sizeof(struct mscan_priv));
++ if (!dev)
++ return NULL;
++ priv = netdev_priv(dev);
++
++ dev->netdev_ops = &mscan_netdev_ops;
++
++ dev->flags |= IFF_ECHO; /* we support local echo */
++
++ netif_napi_add(dev, &priv->napi, mscan_rx_poll, 8);
++
++ priv->can.bittiming_const = &mscan_bittiming_const;
++ priv->can.do_set_bittiming = mscan_do_set_bittiming;
++ priv->can.do_set_mode = mscan_do_set_mode;
++
++ for (i = 0; i < TX_QUEUE_SIZE; i++) {
++ priv->tx_queue[i].id = i;
++ priv->tx_queue[i].mask = 1 << i;
++ }
++
++ return dev;
++}
++EXPORT_SYMBOL(alloc_mscandev);
++
++MODULE_AUTHOR("Andrey Volkov <avolkov@varma-el.com>");
++MODULE_LICENSE("GPL v2");
++MODULE_DESCRIPTION("CAN port driver for a MSCAN based chips");
+Index: net-next-2.6/drivers/net/can/mscan/mscan.h
+===================================================================
+--- /dev/null
++++ net-next-2.6/drivers/net/can/mscan/mscan.h
+@@ -0,0 +1,237 @@
++/*
++ * Definitions of consts/structs to drive the Freescale MSCAN.
++ *
++ * Copyright (C) 2005-2006 Andrey Volkov <avolkov@varma-el.com>,
++ * Varma Electronics Oy
++ *
++ * 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
++ */
++
++#ifndef __MSCAN_H__
++#define __MSCAN_H__
++
++#include <linux/types.h>
++
++/* MSCAN control register 0 (CANCTL0) bits */
++#define MSCAN_RXFRM 0x80
++#define MSCAN_RXACT 0x40
++#define MSCAN_CSWAI 0x20
++#define MSCAN_SYNCH 0x10
++#define MSCAN_TIME 0x08
++#define MSCAN_WUPE 0x04
++#define MSCAN_SLPRQ 0x02
++#define MSCAN_INITRQ 0x01
++
++/* MSCAN control register 1 (CANCTL1) bits */
++#define MSCAN_CANE 0x80
++#define MSCAN_CLKSRC 0x40
++#define MSCAN_LOOPB 0x20
++#define MSCAN_LISTEN 0x10
++#define MSCAN_WUPM 0x04
++#define MSCAN_SLPAK 0x02
++#define MSCAN_INITAK 0x01
++
++/* Use the MPC5200 MSCAN variant? */
++#ifdef CONFIG_PPC
++#define MSCAN_FOR_MPC5200
++#endif
++
++#ifdef MSCAN_FOR_MPC5200
++#define MSCAN_CLKSRC_BUS 0
++#define MSCAN_CLKSRC_XTAL MSCAN_CLKSRC
++#else
++#define MSCAN_CLKSRC_BUS MSCAN_CLKSRC
++#define MSCAN_CLKSRC_XTAL 0
++#endif
++
++/* MSCAN receiver flag register (CANRFLG) bits */
++#define MSCAN_WUPIF 0x80
++#define MSCAN_CSCIF 0x40
++#define MSCAN_RSTAT1 0x20
++#define MSCAN_RSTAT0 0x10
++#define MSCAN_TSTAT1 0x08
++#define MSCAN_TSTAT0 0x04
++#define MSCAN_OVRIF 0x02
++#define MSCAN_RXF 0x01
++#define MSCAN_ERR_IF (MSCAN_OVRIF | MSCAN_CSCIF)
++#define MSCAN_RSTAT_MSK (MSCAN_RSTAT1 | MSCAN_RSTAT0)
++#define MSCAN_TSTAT_MSK (MSCAN_TSTAT1 | MSCAN_TSTAT0)
++#define MSCAN_STAT_MSK (MSCAN_RSTAT_MSK | MSCAN_TSTAT_MSK)
++
++#define MSCAN_STATE_BUS_OFF (MSCAN_RSTAT1 | MSCAN_RSTAT0 | \
++ MSCAN_TSTAT1 | MSCAN_TSTAT0)
++#define MSCAN_STATE_TX(canrflg) (((canrflg)&MSCAN_TSTAT_MSK)>>2)
++#define MSCAN_STATE_RX(canrflg) (((canrflg)&MSCAN_RSTAT_MSK)>>4)
++#define MSCAN_STATE_ACTIVE 0
++#define MSCAN_STATE_WARNING 1
++#define MSCAN_STATE_PASSIVE 2
++#define MSCAN_STATE_BUSOFF 3
++
++/* MSCAN receiver interrupt enable register (CANRIER) bits */
++#define MSCAN_WUPIE 0x80
++#define MSCAN_CSCIE 0x40
++#define MSCAN_RSTATE1 0x20
++#define MSCAN_RSTATE0 0x10
++#define MSCAN_TSTATE1 0x08
++#define MSCAN_TSTATE0 0x04
++#define MSCAN_OVRIE 0x02
++#define MSCAN_RXFIE 0x01
++
++/* MSCAN transmitter flag register (CANTFLG) bits */
++#define MSCAN_TXE2 0x04
++#define MSCAN_TXE1 0x02
++#define MSCAN_TXE0 0x01
++#define MSCAN_TXE (MSCAN_TXE2 | MSCAN_TXE1 | MSCAN_TXE0)
++
++/* MSCAN transmitter interrupt enable register (CANTIER) bits */
++#define MSCAN_TXIE2 0x04
++#define MSCAN_TXIE1 0x02
++#define MSCAN_TXIE0 0x01
++#define MSCAN_TXIE (MSCAN_TXIE2 | MSCAN_TXIE1 | MSCAN_TXIE0)
++
++/* MSCAN transmitter message abort request (CANTARQ) bits */
++#define MSCAN_ABTRQ2 0x04
++#define MSCAN_ABTRQ1 0x02
++#define MSCAN_ABTRQ0 0x01
++
++/* MSCAN transmitter message abort ack (CANTAAK) bits */
++#define MSCAN_ABTAK2 0x04
++#define MSCAN_ABTAK1 0x02
++#define MSCAN_ABTAK0 0x01
++
++/* MSCAN transmit buffer selection (CANTBSEL) bits */
++#define MSCAN_TX2 0x04
++#define MSCAN_TX1 0x02
++#define MSCAN_TX0 0x01
++
++/* MSCAN ID acceptance control register (CANIDAC) bits */
++#define MSCAN_IDAM1 0x20
++#define MSCAN_IDAM0 0x10
++#define MSCAN_IDHIT2 0x04
++#define MSCAN_IDHIT1 0x02
++#define MSCAN_IDHIT0 0x01
++
++#define MSCAN_AF_32BIT 0x00
++#define MSCAN_AF_16BIT MSCAN_IDAM0
++#define MSCAN_AF_8BIT MSCAN_IDAM1
++#define MSCAN_AF_CLOSED (MSCAN_IDAM0|MSCAN_IDAM1)
++#define MSCAN_AF_MASK (~(MSCAN_IDAM0|MSCAN_IDAM1))
++
++/* MSCAN Miscellaneous Register (CANMISC) bits */
++#define MSCAN_BOHOLD 0x01
++
++#ifdef MSCAN_FOR_MPC5200
++#define _MSCAN_RESERVED_(n, num) u8 _res##n[num]
++#define _MSCAN_RESERVED_DSR_SIZE 2
++#else
++#define _MSCAN_RESERVED_(n, num)
++#define _MSCAN_RESERVED_DSR_SIZE 0
++#endif
++
++/* Structure of the hardware registers */
++struct mscan_regs {
++ /* (see doco S12MSCANV3/D) MPC5200 MSCAN */
++ u8 canctl0; /* + 0x00 0x00 */
++ u8 canctl1; /* + 0x01 0x01 */
++ _MSCAN_RESERVED_(1, 2); /* + 0x02 */
++ u8 canbtr0; /* + 0x04 0x02 */
++ u8 canbtr1; /* + 0x05 0x03 */
++ _MSCAN_RESERVED_(2, 2); /* + 0x06 */
++ u8 canrflg; /* + 0x08 0x04 */
++ u8 canrier; /* + 0x09 0x05 */
++ _MSCAN_RESERVED_(3, 2); /* + 0x0a */
++ u8 cantflg; /* + 0x0c 0x06 */
++ u8 cantier; /* + 0x0d 0x07 */
++ _MSCAN_RESERVED_(4, 2); /* + 0x0e */
++ u8 cantarq; /* + 0x10 0x08 */
++ u8 cantaak; /* + 0x11 0x09 */
++ _MSCAN_RESERVED_(5, 2); /* + 0x12 */
++ u8 cantbsel; /* + 0x14 0x0a */
++ u8 canidac; /* + 0x15 0x0b */
++ u8 reserved; /* + 0x16 0x0c */
++ _MSCAN_RESERVED_(6, 5); /* + 0x17 */
++#ifndef MSCAN_FOR_MPC5200
++ u8 canmisc; /* 0x0d */
++#endif
++ u8 canrxerr; /* + 0x1c 0x0e */
++ u8 cantxerr; /* + 0x1d 0x0f */
++ _MSCAN_RESERVED_(7, 2); /* + 0x1e */
++ u16 canidar1_0; /* + 0x20 0x10 */
++ _MSCAN_RESERVED_(8, 2); /* + 0x22 */
++ u16 canidar3_2; /* + 0x24 0x12 */
++ _MSCAN_RESERVED_(9, 2); /* + 0x26 */
++ u16 canidmr1_0; /* + 0x28 0x14 */
++ _MSCAN_RESERVED_(10, 2); /* + 0x2a */
++ u16 canidmr3_2; /* + 0x2c 0x16 */
++ _MSCAN_RESERVED_(11, 2); /* + 0x2e */
++ u16 canidar5_4; /* + 0x30 0x18 */
++ _MSCAN_RESERVED_(12, 2); /* + 0x32 */
++ u16 canidar7_6; /* + 0x34 0x1a */
++ _MSCAN_RESERVED_(13, 2); /* + 0x36 */
++ u16 canidmr5_4; /* + 0x38 0x1c */
++ _MSCAN_RESERVED_(14, 2); /* + 0x3a */
++ u16 canidmr7_6; /* + 0x3c 0x1e */
++ _MSCAN_RESERVED_(15, 2); /* + 0x3e */
++ struct {
++ u16 idr1_0; /* + 0x40 0x20 */
++ _MSCAN_RESERVED_(16, 2); /* + 0x42 */
++ u16 idr3_2; /* + 0x44 0x22 */
++ _MSCAN_RESERVED_(17, 2); /* + 0x46 */
++ u16 dsr1_0; /* + 0x48 0x24 */
++ _MSCAN_RESERVED_(18, 2); /* + 0x4a */
++ u16 dsr3_2; /* + 0x4c 0x26 */
++ _MSCAN_RESERVED_(19, 2); /* + 0x4e */
++ u16 dsr5_4; /* + 0x50 0x28 */
++ _MSCAN_RESERVED_(20, 2); /* + 0x52 */
++ u16 dsr7_6; /* + 0x54 0x2a */
++ _MSCAN_RESERVED_(21, 2); /* + 0x56 */
++ u8 dlr; /* + 0x58 0x2c */
++ u8:8; /* + 0x59 0x2d */
++ _MSCAN_RESERVED_(22, 2); /* + 0x5a */
++ u16 time; /* + 0x5c 0x2e */
++ } rx;
++ _MSCAN_RESERVED_(23, 2); /* + 0x5e */
++ struct {
++ u16 idr1_0; /* + 0x60 0x30 */
++ _MSCAN_RESERVED_(24, 2); /* + 0x62 */
++ u16 idr3_2; /* + 0x64 0x32 */
++ _MSCAN_RESERVED_(25, 2); /* + 0x66 */
++ u16 dsr1_0; /* + 0x68 0x34 */
++ _MSCAN_RESERVED_(26, 2); /* + 0x6a */
++ u16 dsr3_2; /* + 0x6c 0x36 */
++ _MSCAN_RESERVED_(27, 2); /* + 0x6e */
++ u16 dsr5_4; /* + 0x70 0x38 */
++ _MSCAN_RESERVED_(28, 2); /* + 0x72 */
++ u16 dsr7_6; /* + 0x74 0x3a */
++ _MSCAN_RESERVED_(29, 2); /* + 0x76 */
++ u8 dlr; /* + 0x78 0x3c */
++ u8 tbpr; /* + 0x79 0x3d */
++ _MSCAN_RESERVED_(30, 2); /* + 0x7a */
++ u16 time; /* + 0x7c 0x3e */
++ } tx;
++ _MSCAN_RESERVED_(31, 2); /* + 0x7e */
++} __attribute__ ((packed));
++
++#undef _MSCAN_RESERVED_
++#define MSCAN_REGION sizeof(struct mscan)
++
++struct net_device *alloc_mscandev(void);
++/* clock_src:
++ * 1 = The MSCAN clock source is the onchip Bus Clock.
++ * 0 = The MSCAN clock source is the chip Oscillator Clock.
++ */
++extern int register_mscandev(struct net_device *dev, int clock_src);
++extern void unregister_mscandev(struct net_device *dev);
++
++#endif /* __MSCAN_H__ */
+Index: net-next-2.6/drivers/net/can/mscan/Makefile
+===================================================================
+--- /dev/null
++++ net-next-2.6/drivers/net/can/mscan/Makefile
+@@ -0,0 +1,9 @@
++#
++# Makefile for the MSCAN controller drivers.
++#
++
++obj-$(CONFIG_CAN_MPC52XX) += mscan-mpc52xx.o
++
++mscan-mpc52xx-objs := mscan.o mpc52xx_can.o
++
++ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
--- /dev/null
+This is a prelimary quilt patch stack to include the CAN network
+device driver interface and some drivers into Linux kernel. It is
+based on the netdev GIT tree currently at version 2.6.29-rcX:
+
+git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
+
+Please test and give feedback.
--- /dev/null
+01-driver-documentation.patch
+02-driver-maintainers.patch
+03-dev-interface.patch
+04-sysfs-interface.patch
+05-sja1000-driver.patch
+06-sja1000-platform-driver.patch
+07-sja1000-ems-pci-driver.patch
+08-sja1000-kvaser-pci-driver.patch
+09-mscan-mpc5200-driver.patch