]> rtime.felk.cvut.cz Git - socketcan-devel.git/commitdiff
Prelimary quilt patch stack for including the device drivers interface
authorwolf <wolf@030b6a49-0b11-0410-94ab-b0dab22257f2>
Sun, 15 Feb 2009 10:38:25 +0000 (10:38 +0000)
committerwolf <wolf@030b6a49-0b11-0410-94ab-b0dab22257f2>
Sun, 15 Feb 2009 10:38:25 +0000 (10:38 +0000)
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.

Wolfgang.

git-svn-id: svn://svn.berlios.de//socketcan/trunk@947 030b6a49-0b11-0410-94ab-b0dab22257f2

patch-series/net-2.6.29/01-driver-documentation.patch [new file with mode: 0644]
patch-series/net-2.6.29/02-driver-maintainers.patch [new file with mode: 0644]
patch-series/net-2.6.29/03-dev-interface.patch [new file with mode: 0644]
patch-series/net-2.6.29/04-sysfs-interface.patch [new file with mode: 0644]
patch-series/net-2.6.29/05-sja1000-driver.patch [new file with mode: 0644]
patch-series/net-2.6.29/06-sja1000-platform-driver.patch [new file with mode: 0644]
patch-series/net-2.6.29/07-sja1000-ems-pci-driver.patch [new file with mode: 0644]
patch-series/net-2.6.29/08-sja1000-kvaser-pci-driver.patch [new file with mode: 0644]
patch-series/net-2.6.29/09-mscan-mpc5200-driver.patch [new file with mode: 0644]
patch-series/net-2.6.29/README [new file with mode: 0644]
patch-series/net-2.6.29/series [new file with mode: 0644]

diff --git a/patch-series/net-2.6.29/01-driver-documentation.patch b/patch-series/net-2.6.29/01-driver-documentation.patch
new file mode 100644 (file)
index 0000000..dd9850a
--- /dev/null
@@ -0,0 +1,240 @@
+[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
diff --git a/patch-series/net-2.6.29/02-driver-maintainers.patch b/patch-series/net-2.6.29/02-driver-maintainers.patch
new file mode 100644 (file)
index 0000000..4826a46
--- /dev/null
@@ -0,0 +1,51 @@
+[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
diff --git a/patch-series/net-2.6.29/03-dev-interface.patch b/patch-series/net-2.6.29/03-dev-interface.patch
new file mode 100644 (file)
index 0000000..8eef171
--- /dev/null
@@ -0,0 +1,740 @@
+[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
diff --git a/patch-series/net-2.6.29/04-sysfs-interface.patch b/patch-series/net-2.6.29/04-sysfs-interface.patch
new file mode 100644 (file)
index 0000000..fc72591
--- /dev/null
@@ -0,0 +1,607 @@
+[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
diff --git a/patch-series/net-2.6.29/05-sja1000-driver.patch b/patch-series/net-2.6.29/05-sja1000-driver.patch
new file mode 100644 (file)
index 0000000..7a65dff
--- /dev/null
@@ -0,0 +1,927 @@
+[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
diff --git a/patch-series/net-2.6.29/06-sja1000-platform-driver.patch b/patch-series/net-2.6.29/06-sja1000-platform-driver.patch
new file mode 100644 (file)
index 0000000..a824c79
--- /dev/null
@@ -0,0 +1,257 @@
+[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
diff --git a/patch-series/net-2.6.29/07-sja1000-ems-pci-driver.patch b/patch-series/net-2.6.29/07-sja1000-ems-pci-driver.patch
new file mode 100644 (file)
index 0000000..04f62fd
--- /dev/null
@@ -0,0 +1,374 @@
+[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);
++
diff --git a/patch-series/net-2.6.29/08-sja1000-kvaser-pci-driver.patch b/patch-series/net-2.6.29/08-sja1000-kvaser-pci-driver.patch
new file mode 100644 (file)
index 0000000..3414351
--- /dev/null
@@ -0,0 +1,460 @@
+[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
diff --git a/patch-series/net-2.6.29/09-mscan-mpc5200-driver.patch b/patch-series/net-2.6.29/09-mscan-mpc5200-driver.patch
new file mode 100644 (file)
index 0000000..0276628
--- /dev/null
@@ -0,0 +1,1297 @@
+[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(&regs->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(&regs->cantier, 0);
++                      out_8(&regs->cantarq, priv->tx_active);
++                      out_8(&regs->cantier, priv->tx_active);
++              }
++
++              canctl1 = in_8(&regs->canctl1);
++              if ((mode & MSCAN_SLPRQ) && (canctl1 & MSCAN_SLPAK) == 0) {
++                      out_8(&regs->canctl0,
++                            in_8(&regs->canctl0) | MSCAN_SLPRQ);
++                      for (i = 0; i < MSCAN_SET_MODE_RETRIES; i++) {
++                              if (in_8(&regs->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(&regs->canctl0,
++                            in_8(&regs->canctl0) | MSCAN_INITRQ);
++                      for (i = 0; i < MSCAN_SET_MODE_RETRIES; i++) {
++                              if (in_8(&regs->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(&regs->canctl0,
++                            in_8(&regs->canctl0) | MSCAN_CSWAI);
++
++      } else {
++              canctl1 = in_8(&regs->canctl1);
++              if (canctl1 & (MSCAN_SLPAK | MSCAN_INITAK)) {
++                      out_8(&regs->canctl0, in_8(&regs->canctl0) &
++                            ~(MSCAN_SLPRQ | MSCAN_INITRQ));
++                      for (i = 0; i < MSCAN_SET_MODE_RETRIES; i++) {
++                              canctl1 = in_8(&regs->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(&regs->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(&regs->canrflg);
++      priv->shadow_statflg = canrflg & MSCAN_STAT_MSK;
++      priv->can.state = state_map[max(MSCAN_STATE_RX(canrflg),
++                                  MSCAN_STATE_TX(canrflg))];
++      out_8(&regs->cantier, 0);
++
++      /* Enable receive interrupts. */
++      out_8(&regs->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(&regs->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(&regs->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(&regs->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(&regs->tx.idr1_0, can_id);
++
++      if (!rtr) {
++              void __iomem *data = &regs->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(&regs->tx.dlr, frame->can_dlc);
++      out_8(&regs->tx.tbpr, priv->cur_pri);
++
++      /* Start transmission. */
++      out_8(&regs->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(&regs->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(&regs->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(&regs->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(&regs->rx.idr1_0);
++                      if (can_id & (1 << 3)) {
++                              frame->can_id = CAN_EFF_FLAG;
++                              can_id = ((can_id << 16) |
++                                        in_be16(&regs->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(&regs->rx.dlr) & 0xf;
++
++                      if (!(frame->can_id & CAN_RTR_FLAG)) {
++                              void __iomem *data = &regs->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(&regs->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(&regs->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(&regs->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(&regs->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(&regs->cantier) & MSCAN_TXE;
++      cantflg = in_8(&regs->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(&regs->cantbsel, mask);
++                      stats->tx_bytes += in_8(&regs->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(&regs->cantier, priv->tx_active);
++              ret = IRQ_HANDLED;
++      }
++
++      canrflg = in_8(&regs->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(&regs->canrier);
++                      out_8(&regs->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(&regs->canbtr0, btr0);
++      out_8(&regs->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(&regs->canctl1, in_8(&regs->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(&regs->cantier, 0);
++      out_8(&regs->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(&regs->canctl1);
++      if (clock_src)
++              ctl1 |= MSCAN_CLKSRC;
++      else
++              ctl1 &= ~MSCAN_CLKSRC;
++
++      ctl1 |= MSCAN_CANE;
++      out_8(&regs->canctl1, ctl1);
++      udelay(100);
++
++      /* acceptance mask/acceptance code (accept everything) */
++      out_be16(&regs->canidar1_0, 0);
++      out_be16(&regs->canidar3_2, 0);
++      out_be16(&regs->canidar5_4, 0);
++      out_be16(&regs->canidar7_6, 0);
++
++      out_be16(&regs->canidmr1_0, 0xffff);
++      out_be16(&regs->canidmr3_2, 0xffff);
++      out_be16(&regs->canidmr5_4, 0xffff);
++      out_be16(&regs->canidmr7_6, 0xffff);
++      /* Two 32 bit Acceptance Filters */
++      out_8(&regs->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(&regs->canctl1, in_8(&regs->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
diff --git a/patch-series/net-2.6.29/README b/patch-series/net-2.6.29/README
new file mode 100644 (file)
index 0000000..9e96445
--- /dev/null
@@ -0,0 +1,7 @@
+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.
diff --git a/patch-series/net-2.6.29/series b/patch-series/net-2.6.29/series
new file mode 100644 (file)
index 0000000..82e820c
--- /dev/null
@@ -0,0 +1,9 @@
+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