Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
ffcb9738
Commit
ffcb9738
authored
Mar 04, 2012
by
David S. Miller
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
git://gitorious.org/linux-can/linux-can-next
parents
4c1dc80a
d8a19935
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
4490 additions
and
18 deletions
+4490
-18
drivers/net/can/cc770/cc770.c
drivers/net/can/cc770/cc770.c
+0
-1
drivers/net/can/sja1000/Kconfig
drivers/net/can/sja1000/Kconfig
+24
-3
drivers/net/can/sja1000/Makefile
drivers/net/can/sja1000/Makefile
+1
-0
drivers/net/can/sja1000/peak_pci.c
drivers/net/can/sja1000/peak_pci.c
+491
-14
drivers/net/can/sja1000/peak_pcmcia.c
drivers/net/can/sja1000/peak_pcmcia.c
+753
-0
drivers/net/can/usb/Kconfig
drivers/net/can/usb/Kconfig
+6
-0
drivers/net/can/usb/Makefile
drivers/net/can/usb/Makefile
+1
-0
drivers/net/can/usb/peak_usb/Makefile
drivers/net/can/usb/peak_usb/Makefile
+2
-0
drivers/net/can/usb/peak_usb/pcan_usb.c
drivers/net/can/usb/peak_usb/pcan_usb.c
+901
-0
drivers/net/can/usb/peak_usb/pcan_usb_core.c
drivers/net/can/usb/peak_usb/pcan_usb_core.c
+951
-0
drivers/net/can/usb/peak_usb/pcan_usb_core.h
drivers/net/can/usb/peak_usb/pcan_usb_core.h
+146
-0
drivers/net/can/usb/peak_usb/pcan_usb_pro.c
drivers/net/can/usb/peak_usb/pcan_usb_pro.c
+1036
-0
drivers/net/can/usb/peak_usb/pcan_usb_pro.h
drivers/net/can/usb/peak_usb/pcan_usb_pro.h
+178
-0
No files found.
drivers/net/can/cc770/cc770.c
View file @
ffcb9738
...
...
@@ -34,7 +34,6 @@
#include <linux/can.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>
#include <linux/can/dev.h>
#include <linux/can/platform/cc770.h>
#include "cc770.h"
...
...
drivers/net/can/sja1000/Kconfig
View file @
ffcb9738
...
...
@@ -43,12 +43,33 @@ config CAN_EMS_PCI
CPC-PCIe and CPC-104P cards from EMS Dr. Thomas Wuensche
(http://www.ems-wuensche.de).
config CAN_PEAK_PCMCIA
tristate "PEAK PCAN-PC Card"
depends on PCMCIA
---help---
This driver is for the PCAN-PC Card PCMCIA adapter (1 or 2 channels)
from PEAK-System (http://www.peak-system.com). To compile this
driver as a module, choose M here: the module will be called
peak_pcmcia.
config CAN_PEAK_PCI
tristate "PEAK PCAN
PCI/PCIe
Cards"
tristate "PEAK PCAN
-PCI/PCIe/miniPCI
Cards"
depends on PCI
---help---
This driver is for the PCAN PCI/PCIe cards (1, 2, 3 or 4 channels)
from PEAK Systems (http://www.peak-system.com).
This driver is for the PCAN-PCI/PCIe/miniPCI cards
(1, 2, 3 or 4 channels) from PEAK-System Technik
(http://www.peak-system.com).
config CAN_PEAK_PCIEC
bool "PEAK PCAN-ExpressCard Cards"
depends on CAN_PEAK_PCI
select I2C
select I2C_ALGOBIT
default y
---help---
Say Y here if you want to use a PCAN-ExpressCard from PEAK-System
Technik. This will also automatically select I2C and I2C_ALGO
configuration options.
config CAN_KVASER_PCI
tristate "Kvaser PCIcanx and Kvaser PCIcan PCI Cards"
...
...
drivers/net/can/sja1000/Makefile
View file @
ffcb9738
...
...
@@ -9,6 +9,7 @@ obj-$(CONFIG_CAN_SJA1000_OF_PLATFORM) += sja1000_of_platform.o
obj-$(CONFIG_CAN_EMS_PCMCIA)
+=
ems_pcmcia.o
obj-$(CONFIG_CAN_EMS_PCI)
+=
ems_pci.o
obj-$(CONFIG_CAN_KVASER_PCI)
+=
kvaser_pci.o
obj-$(CONFIG_CAN_PEAK_PCMCIA)
+=
peak_pcmcia.o
obj-$(CONFIG_CAN_PEAK_PCI)
+=
peak_pci.o
obj-$(CONFIG_CAN_PLX_PCI)
+=
plx_pci.o
obj-$(CONFIG_CAN_TSCAN1)
+=
tscan1.o
...
...
drivers/net/can/sja1000/peak_pci.c
View file @
ffcb9738
/*
* Copyright (C) 2007, 2011 Wolfgang Grandegger <wg@grandegger.com>
* Copyright (C) 2012 Stephane Grosjean <s.grosjean@peak-system.com>
*
* Derived from the PCAN project file driver/src/pcan_pci.c:
*
...
...
@@ -13,10 +14,6 @@
* 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>
...
...
@@ -26,22 +23,26 @@
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/io.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <linux/can.h>
#include <linux/can/dev.h>
#include "sja1000.h"
MODULE_AUTHOR
(
"Wolfgang Grandegger <wg@grandegger.com>"
);
MODULE_DESCRIPTION
(
"Socket-CAN driver for PEAK PCAN PCI
/PCIe
cards"
);
MODULE_SUPPORTED_DEVICE
(
"PEAK PCAN PCI/PCIe
CAN card
"
);
MODULE_DESCRIPTION
(
"Socket-CAN driver for PEAK PCAN PCI
family
cards"
);
MODULE_SUPPORTED_DEVICE
(
"PEAK PCAN PCI/PCIe
/PCIeC miniPCI CAN cards
"
);
MODULE_LICENSE
(
"GPL v2"
);
#define DRV_NAME "peak_pci"
struct
peak_pciec_card
;
struct
peak_pci_chan
{
void
__iomem
*
cfg_base
;
/* Common for all channels */
struct
net_device
*
prev_dev
;
/* Chain of network devices */
u16
icr_mask
;
/* Interrupt mask for fast ack */
struct
peak_pciec_card
*
pciec_card
;
/* only for PCIeC LEDs */
};
#define PEAK_PCI_CAN_CLOCK (16000000 / 2)
...
...
@@ -61,16 +62,464 @@ struct peak_pci_chan {
#define PEAK_PCI_VENDOR_ID 0x001C
/* The PCI device and vendor IDs */
#define PEAK_PCI_DEVICE_ID 0x0001
/* for PCI/PCIe slot cards */
#define PEAK_PCIEC_DEVICE_ID 0x0002
/* for ExpressCard slot cards */
#define PEAK_PCIE_DEVICE_ID 0x0003
/* for nextgen PCIe slot cards */
#define PEAK_MPCI_DEVICE_ID 0x0008
/* The miniPCI slot cards */
#define PEAK_PCI_CHAN_MAX 4
static
const
u16
peak_pci_icr_masks
[]
=
{
0x02
,
0x01
,
0x40
,
0x80
};
static
const
u16
peak_pci_icr_masks
[
PEAK_PCI_CHAN_MAX
]
=
{
0x02
,
0x01
,
0x40
,
0x80
};
static
DEFINE_PCI_DEVICE_TABLE
(
peak_pci_tbl
)
=
{
{
PEAK_PCI_VENDOR_ID
,
PEAK_PCI_DEVICE_ID
,
PCI_ANY_ID
,
PCI_ANY_ID
,},
{
PEAK_PCI_VENDOR_ID
,
PEAK_PCIE_DEVICE_ID
,
PCI_ANY_ID
,
PCI_ANY_ID
,},
{
PEAK_PCI_VENDOR_ID
,
PEAK_MPCI_DEVICE_ID
,
PCI_ANY_ID
,
PCI_ANY_ID
,},
#ifdef CONFIG_CAN_PEAK_PCIEC
{
PEAK_PCI_VENDOR_ID
,
PEAK_PCIEC_DEVICE_ID
,
PCI_ANY_ID
,
PCI_ANY_ID
,},
#endif
{
0
,}
};
MODULE_DEVICE_TABLE
(
pci
,
peak_pci_tbl
);
#ifdef CONFIG_CAN_PEAK_PCIEC
/*
* PCAN-ExpressCard needs I2C bit-banging configuration option.
*/
/* GPIOICR byte access offsets */
#define PITA_GPOUT 0x18
/* GPx output value */
#define PITA_GPIN 0x19
/* GPx input value */
#define PITA_GPOEN 0x1A
/* configure GPx as ouput pin */
/* I2C GP bits */
#define PITA_GPIN_SCL 0x01
/* Serial Clock Line */
#define PITA_GPIN_SDA 0x04
/* Serial DAta line */
#define PCA9553_1_SLAVEADDR (0xC4 >> 1)
/* PCA9553 LS0 fields values */
enum
{
PCA9553_LOW
,
PCA9553_HIGHZ
,
PCA9553_PWM0
,
PCA9553_PWM1
};
/* LEDs control */
#define PCA9553_ON PCA9553_LOW
#define PCA9553_OFF PCA9553_HIGHZ
#define PCA9553_SLOW PCA9553_PWM0
#define PCA9553_FAST PCA9553_PWM1
#define PCA9553_LED(c) (1 << (c))
#define PCA9553_LED_STATE(s, c) ((s) << ((c) << 1))
#define PCA9553_LED_ON(c) PCA9553_LED_STATE(PCA9553_ON, c)
#define PCA9553_LED_OFF(c) PCA9553_LED_STATE(PCA9553_OFF, c)
#define PCA9553_LED_SLOW(c) PCA9553_LED_STATE(PCA9553_SLOW, c)
#define PCA9553_LED_FAST(c) PCA9553_LED_STATE(PCA9553_FAST, c)
#define PCA9553_LED_MASK(c) PCA9553_LED_STATE(0x03, c)
#define PCA9553_LED_OFF_ALL (PCA9553_LED_OFF(0) | PCA9553_LED_OFF(1))
#define PCA9553_LS0_INIT 0x40
/* initial value (!= from 0x00) */
struct
peak_pciec_chan
{
struct
net_device
*
netdev
;
unsigned
long
prev_rx_bytes
;
unsigned
long
prev_tx_bytes
;
};
struct
peak_pciec_card
{
void
__iomem
*
cfg_base
;
/* Common for all channels */
void
__iomem
*
reg_base
;
/* first channel base address */
u8
led_cache
;
/* leds state cache */
/* PCIExpressCard i2c data */
struct
i2c_algo_bit_data
i2c_bit
;
struct
i2c_adapter
led_chip
;
struct
delayed_work
led_work
;
/* led delayed work */
int
chan_count
;
struct
peak_pciec_chan
channel
[
PEAK_PCI_CHAN_MAX
];
};
/* "normal" pci register write callback is overloaded for leds control */
static
void
peak_pci_write_reg
(
const
struct
sja1000_priv
*
priv
,
int
port
,
u8
val
);
static
inline
void
pita_set_scl_highz
(
struct
peak_pciec_card
*
card
)
{
u8
gp_outen
=
readb
(
card
->
cfg_base
+
PITA_GPOEN
)
&
~
PITA_GPIN_SCL
;
writeb
(
gp_outen
,
card
->
cfg_base
+
PITA_GPOEN
);
}
static
inline
void
pita_set_sda_highz
(
struct
peak_pciec_card
*
card
)
{
u8
gp_outen
=
readb
(
card
->
cfg_base
+
PITA_GPOEN
)
&
~
PITA_GPIN_SDA
;
writeb
(
gp_outen
,
card
->
cfg_base
+
PITA_GPOEN
);
}
static
void
peak_pciec_init_pita_gpio
(
struct
peak_pciec_card
*
card
)
{
/* raise SCL & SDA GPIOs to high-Z */
pita_set_scl_highz
(
card
);
pita_set_sda_highz
(
card
);
}
static
void
pita_setsda
(
void
*
data
,
int
state
)
{
struct
peak_pciec_card
*
card
=
(
struct
peak_pciec_card
*
)
data
;
u8
gp_out
,
gp_outen
;
/* set output sda always to 0 */
gp_out
=
readb
(
card
->
cfg_base
+
PITA_GPOUT
)
&
~
PITA_GPIN_SDA
;
writeb
(
gp_out
,
card
->
cfg_base
+
PITA_GPOUT
);
/* control output sda with GPOEN */
gp_outen
=
readb
(
card
->
cfg_base
+
PITA_GPOEN
);
if
(
state
)
gp_outen
&=
~
PITA_GPIN_SDA
;
else
gp_outen
|=
PITA_GPIN_SDA
;
writeb
(
gp_outen
,
card
->
cfg_base
+
PITA_GPOEN
);
}
static
void
pita_setscl
(
void
*
data
,
int
state
)
{
struct
peak_pciec_card
*
card
=
(
struct
peak_pciec_card
*
)
data
;
u8
gp_out
,
gp_outen
;
/* set output scl always to 0 */
gp_out
=
readb
(
card
->
cfg_base
+
PITA_GPOUT
)
&
~
PITA_GPIN_SCL
;
writeb
(
gp_out
,
card
->
cfg_base
+
PITA_GPOUT
);
/* control output scl with GPOEN */
gp_outen
=
readb
(
card
->
cfg_base
+
PITA_GPOEN
);
if
(
state
)
gp_outen
&=
~
PITA_GPIN_SCL
;
else
gp_outen
|=
PITA_GPIN_SCL
;
writeb
(
gp_outen
,
card
->
cfg_base
+
PITA_GPOEN
);
}
static
int
pita_getsda
(
void
*
data
)
{
struct
peak_pciec_card
*
card
=
(
struct
peak_pciec_card
*
)
data
;
/* set tristate */
pita_set_sda_highz
(
card
);
return
(
readb
(
card
->
cfg_base
+
PITA_GPIN
)
&
PITA_GPIN_SDA
)
?
1
:
0
;
}
static
int
pita_getscl
(
void
*
data
)
{
struct
peak_pciec_card
*
card
=
(
struct
peak_pciec_card
*
)
data
;
/* set tristate */
pita_set_scl_highz
(
card
);
return
(
readb
(
card
->
cfg_base
+
PITA_GPIN
)
&
PITA_GPIN_SCL
)
?
1
:
0
;
}
/*
* write commands to the LED chip though the I2C-bus of the PCAN-PCIeC
*/
static
int
peak_pciec_write_pca9553
(
struct
peak_pciec_card
*
card
,
u8
offset
,
u8
data
)
{
u8
buffer
[
2
]
=
{
offset
,
data
};
struct
i2c_msg
msg
=
{
.
addr
=
PCA9553_1_SLAVEADDR
,
.
len
=
2
,
.
buf
=
buffer
,
};
int
ret
;
/* cache led mask */
if
((
offset
==
5
)
&&
(
data
==
card
->
led_cache
))
return
0
;
ret
=
i2c_transfer
(
&
card
->
led_chip
,
&
msg
,
1
);
if
(
ret
<
0
)
return
ret
;
if
(
offset
==
5
)
card
->
led_cache
=
data
;
return
0
;
}
/*
* delayed work callback used to control the LEDs
*/
static
void
peak_pciec_led_work
(
struct
work_struct
*
work
)
{
struct
peak_pciec_card
*
card
=
container_of
(
work
,
struct
peak_pciec_card
,
led_work
.
work
);
struct
net_device
*
netdev
;
u8
new_led
=
card
->
led_cache
;
int
i
,
up_count
=
0
;
/* first check what is to do */
for
(
i
=
0
;
i
<
card
->
chan_count
;
i
++
)
{
/* default is: not configured */
new_led
&=
~
PCA9553_LED_MASK
(
i
);
new_led
|=
PCA9553_LED_ON
(
i
);
netdev
=
card
->
channel
[
i
].
netdev
;
if
(
!
netdev
||
!
(
netdev
->
flags
&
IFF_UP
))
continue
;
up_count
++
;
/* no activity (but configured) */
new_led
&=
~
PCA9553_LED_MASK
(
i
);
new_led
|=
PCA9553_LED_SLOW
(
i
);
/* if bytes counters changed, set fast blinking led */
if
(
netdev
->
stats
.
rx_bytes
!=
card
->
channel
[
i
].
prev_rx_bytes
)
{
card
->
channel
[
i
].
prev_rx_bytes
=
netdev
->
stats
.
rx_bytes
;
new_led
&=
~
PCA9553_LED_MASK
(
i
);
new_led
|=
PCA9553_LED_FAST
(
i
);
}
if
(
netdev
->
stats
.
tx_bytes
!=
card
->
channel
[
i
].
prev_tx_bytes
)
{
card
->
channel
[
i
].
prev_tx_bytes
=
netdev
->
stats
.
tx_bytes
;
new_led
&=
~
PCA9553_LED_MASK
(
i
);
new_led
|=
PCA9553_LED_FAST
(
i
);
}
}
/* check if LS0 settings changed, only update i2c if so */
peak_pciec_write_pca9553
(
card
,
5
,
new_led
);
/* restart timer (except if no more configured channels) */
if
(
up_count
)
schedule_delayed_work
(
&
card
->
led_work
,
HZ
);
}
/*
* set LEDs blinking state
*/
static
void
peak_pciec_set_leds
(
struct
peak_pciec_card
*
card
,
u8
led_mask
,
u8
s
)
{
u8
new_led
=
card
->
led_cache
;
int
i
;
/* first check what is to do */
for
(
i
=
0
;
i
<
card
->
chan_count
;
i
++
)
if
(
led_mask
&
PCA9553_LED
(
i
))
{
new_led
&=
~
PCA9553_LED_MASK
(
i
);
new_led
|=
PCA9553_LED_STATE
(
s
,
i
);
}
/* check if LS0 settings changed, only update i2c if so */
peak_pciec_write_pca9553
(
card
,
5
,
new_led
);
}
/*
* start one second delayed work to control LEDs
*/
static
void
peak_pciec_start_led_work
(
struct
peak_pciec_card
*
card
)
{
if
(
!
delayed_work_pending
(
&
card
->
led_work
))
schedule_delayed_work
(
&
card
->
led_work
,
HZ
);
}
/*
* stop LEDs delayed work
*/
static
void
peak_pciec_stop_led_work
(
struct
peak_pciec_card
*
card
)
{
cancel_delayed_work_sync
(
&
card
->
led_work
);
}
/*
* initialize the PCA9553 4-bit I2C-bus LED chip
*/
static
int
peak_pciec_init_leds
(
struct
peak_pciec_card
*
card
)
{
int
err
;
/* prescaler for frequency 0: "SLOW" = 1 Hz = "44" */
err
=
peak_pciec_write_pca9553
(
card
,
1
,
44
/
1
);
if
(
err
)
return
err
;
/* duty cycle 0: 50% */
err
=
peak_pciec_write_pca9553
(
card
,
2
,
0x80
);
if
(
err
)
return
err
;
/* prescaler for frequency 1: "FAST" = 5 Hz */
err
=
peak_pciec_write_pca9553
(
card
,
3
,
44
/
5
);
if
(
err
)
return
err
;
/* duty cycle 1: 50% */
err
=
peak_pciec_write_pca9553
(
card
,
4
,
0x80
);
if
(
err
)
return
err
;
/* switch LEDs to initial state */
return
peak_pciec_write_pca9553
(
card
,
5
,
PCA9553_LS0_INIT
);
}
/*
* restore LEDs state to off peak_pciec_leds_exit
*/
static
void
peak_pciec_leds_exit
(
struct
peak_pciec_card
*
card
)
{
/* switch LEDs to off */
peak_pciec_write_pca9553
(
card
,
5
,
PCA9553_LED_OFF_ALL
);
}
/*
* normal write sja1000 register method overloaded to catch when controller
* is started or stopped, to control leds
*/
static
void
peak_pciec_write_reg
(
const
struct
sja1000_priv
*
priv
,
int
port
,
u8
val
)
{
struct
peak_pci_chan
*
chan
=
priv
->
priv
;
struct
peak_pciec_card
*
card
=
chan
->
pciec_card
;
int
c
=
(
priv
->
reg_base
-
card
->
reg_base
)
/
PEAK_PCI_CHAN_SIZE
;
/* sja1000 register changes control the leds state */
if
(
port
==
REG_MOD
)
switch
(
val
)
{
case
MOD_RM
:
/* Reset Mode: set led on */
peak_pciec_set_leds
(
card
,
PCA9553_LED
(
c
),
PCA9553_ON
);
break
;
case
0x00
:
/* Normal Mode: led slow blinking and start led timer */
peak_pciec_set_leds
(
card
,
PCA9553_LED
(
c
),
PCA9553_SLOW
);
peak_pciec_start_led_work
(
card
);
break
;
default:
break
;
}
/* call base function */
peak_pci_write_reg
(
priv
,
port
,
val
);
}
static
struct
i2c_algo_bit_data
peak_pciec_i2c_bit_ops
=
{
.
setsda
=
pita_setsda
,
.
setscl
=
pita_setscl
,
.
getsda
=
pita_getsda
,
.
getscl
=
pita_getscl
,
.
udelay
=
10
,
.
timeout
=
HZ
,
};
static
int
peak_pciec_probe
(
struct
pci_dev
*
pdev
,
struct
net_device
*
dev
)
{
struct
sja1000_priv
*
priv
=
netdev_priv
(
dev
);
struct
peak_pci_chan
*
chan
=
priv
->
priv
;
struct
peak_pciec_card
*
card
;
int
err
;
/* copy i2c object address from 1st channel */
if
(
chan
->
prev_dev
)
{
struct
sja1000_priv
*
prev_priv
=
netdev_priv
(
chan
->
prev_dev
);
struct
peak_pci_chan
*
prev_chan
=
prev_priv
->
priv
;
card
=
prev_chan
->
pciec_card
;
if
(
!
card
)
return
-
ENODEV
;
/* channel is the first one: do the init part */
}
else
{
/* create the bit banging I2C adapter structure */
card
=
kzalloc
(
sizeof
(
struct
peak_pciec_card
),
GFP_KERNEL
);
if
(
!
card
)
{
dev_err
(
&
pdev
->
dev
,
"failed allocating memory for i2c chip
\n
"
);
return
-
ENOMEM
;
}
card
->
cfg_base
=
chan
->
cfg_base
;
card
->
reg_base
=
priv
->
reg_base
;
card
->
led_chip
.
owner
=
THIS_MODULE
;
card
->
led_chip
.
dev
.
parent
=
&
pdev
->
dev
;
card
->
led_chip
.
algo_data
=
&
card
->
i2c_bit
;
strncpy
(
card
->
led_chip
.
name
,
"peak_i2c"
,
sizeof
(
card
->
led_chip
.
name
));
card
->
i2c_bit
=
peak_pciec_i2c_bit_ops
;
card
->
i2c_bit
.
udelay
=
10
;
card
->
i2c_bit
.
timeout
=
HZ
;
card
->
i2c_bit
.
data
=
card
;
peak_pciec_init_pita_gpio
(
card
);
err
=
i2c_bit_add_bus
(
&
card
->
led_chip
);
if
(
err
)
{
dev_err
(
&
pdev
->
dev
,
"i2c init failed
\n
"
);
goto
pciec_init_err_1
;
}
err
=
peak_pciec_init_leds
(
card
);
if
(
err
)
{
dev_err
(
&
pdev
->
dev
,
"leds hardware init failed
\n
"
);
goto
pciec_init_err_2
;
}
INIT_DELAYED_WORK
(
&
card
->
led_work
,
peak_pciec_led_work
);
/* PCAN-ExpressCard needs its own callback for leds */
priv
->
write_reg
=
peak_pciec_write_reg
;
}
chan
->
pciec_card
=
card
;
card
->
channel
[
card
->
chan_count
++
].
netdev
=
dev
;
return
0
;
pciec_init_err_2:
i2c_del_adapter
(
&
card
->
led_chip
);
pciec_init_err_1:
peak_pciec_init_pita_gpio
(
card
);
kfree
(
card
);
return
err
;
}
static
void
peak_pciec_remove
(
struct
peak_pciec_card
*
card
)
{
peak_pciec_stop_led_work
(
card
);
peak_pciec_leds_exit
(
card
);
i2c_del_adapter
(
&
card
->
led_chip
);
peak_pciec_init_pita_gpio
(
card
);
kfree
(
card
);
}
#else
/* CONFIG_CAN_PEAK_PCIEC */
/*
* Placebo functions when PCAN-ExpressCard support is not selected
*/
static
inline
int
peak_pciec_probe
(
struct
pci_dev
*
pdev
,
struct
net_device
*
dev
)
{
return
-
ENODEV
;
}
static
inline
void
peak_pciec_remove
(
struct
peak_pciec_card
*
card
)
{
}
#endif
/* CONFIG_CAN_PEAK_PCIEC */
static
u8
peak_pci_read_reg
(
const
struct
sja1000_priv
*
priv
,
int
port
)
{
return
readb
(
priv
->
reg_base
+
(
port
<<
2
));
...
...
@@ -188,17 +637,31 @@ static int __devinit peak_pci_probe(struct pci_dev *pdev,
SET_NETDEV_DEV
(
dev
,
&
pdev
->
dev
);
/* Create chain of SJA1000 devices */
chan
->
prev_dev
=
pci_get_drvdata
(
pdev
);
pci_set_drvdata
(
pdev
,
dev
);
/*
* PCAN-ExpressCard needs some additional i2c init.
* This must be done *before* register_sja1000dev() but
* *after* devices linkage
*/
if
(
pdev
->
device
==
PEAK_PCIEC_DEVICE_ID
)
{
err
=
peak_pciec_probe
(
pdev
,
dev
);
if
(
err
)
{
dev_err
(
&
pdev
->
dev
,
"failed to probe device (err %d)
\n
"
,
err
);
goto
failure_free_dev
;
}
}
err
=
register_sja1000dev
(
dev
);
if
(
err
)
{
dev_err
(
&
pdev
->
dev
,
"failed to register device
\n
"
);
free_sja1000dev
(
dev
);
goto
failure_remove_channels
;
goto
failure_free_dev
;
}
/* Create chain of SJA1000 devices */
chan
->
prev_dev
=
pci_get_drvdata
(
pdev
);
pci_set_drvdata
(
pdev
,
dev
);
dev_info
(
&
pdev
->
dev
,
"%s at reg_base=0x%p cfg_base=0x%p irq=%d
\n
"
,
dev
->
name
,
priv
->
reg_base
,
chan
->
cfg_base
,
dev
->
irq
);
...
...
@@ -209,10 +672,15 @@ static int __devinit peak_pci_probe(struct pci_dev *pdev,
return
0
;
failure_free_dev:
pci_set_drvdata
(
pdev
,
chan
->
prev_dev
);
free_sja1000dev
(
dev
);
failure_remove_channels:
/* Disable interrupts */
writew
(
0x0
,
cfg_base
+
PITA_ICR
+
2
);
chan
=
NULL
;
for
(
dev
=
pci_get_drvdata
(
pdev
);
dev
;
dev
=
chan
->
prev_dev
)
{
unregister_sja1000dev
(
dev
);
free_sja1000dev
(
dev
);
...
...
@@ -220,6 +688,10 @@ static int __devinit peak_pci_probe(struct pci_dev *pdev,
chan
=
priv
->
priv
;
}
/* free any PCIeC resources too */
if
(
chan
&&
chan
->
pciec_card
)
peak_pciec_remove
(
chan
->
pciec_card
);
pci_iounmap
(
pdev
,
reg_base
);
failure_unmap_cfg_base:
...
...
@@ -251,8 +723,13 @@ static void __devexit peak_pci_remove(struct pci_dev *pdev)
unregister_sja1000dev
(
dev
);
free_sja1000dev
(
dev
);
dev
=
chan
->
prev_dev
;
if
(
!
dev
)
if
(
!
dev
)
{
/* do that only for first channel */
if
(
chan
->
pciec_card
)
peak_pciec_remove
(
chan
->
pciec_card
);
break
;
}
priv
=
netdev_priv
(
dev
);
chan
=
priv
->
priv
;
}
...
...
drivers/net/can/sja1000/peak_pcmcia.c
0 → 100644
View file @
ffcb9738
/*
* Copyright (C) 2010-2012 Stephane Grosjean <s.grosjean@peak-system.com>
*
* CAN driver for PEAK-System PCAN-PC Card
* Derived from the PCAN project file driver/src/pcan_pccard.c
* Copyright (C) 2006-2010 PEAK System-Technik GmbH
*
* 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.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/io.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
#include <linux/can.h>
#include <linux/can/dev.h>
#include "sja1000.h"
MODULE_AUTHOR
(
"Stephane Grosjean <s.grosjean@peak-system.com>"
);
MODULE_DESCRIPTION
(
"CAN driver for PEAK-System PCAN-PC Cards"
);
MODULE_LICENSE
(
"GPL v2"
);
MODULE_SUPPORTED_DEVICE
(
"PEAK PCAN-PC Card"
);
/* PEAK-System PCMCIA driver name */
#define PCC_NAME "peak_pcmcia"
#define PCC_CHAN_MAX 2
#define PCC_CAN_CLOCK (16000000 / 2)
#define PCC_MANF_ID 0x0377
#define PCC_CARD_ID 0x0001
#define PCC_CHAN_SIZE 0x20
#define PCC_CHAN_OFF(c) ((c) * PCC_CHAN_SIZE)
#define PCC_COMN_OFF (PCC_CHAN_OFF(PCC_CHAN_MAX))
#define PCC_COMN_SIZE 0x40
/* common area registers */
#define PCC_CCR 0x00
#define PCC_CSR 0x02
#define PCC_CPR 0x04
#define PCC_SPI_DIR 0x06
#define PCC_SPI_DOR 0x08
#define PCC_SPI_ADR 0x0a
#define PCC_SPI_IR 0x0c
#define PCC_FW_MAJOR 0x10
#define PCC_FW_MINOR 0x12
/* CCR bits */
#define PCC_CCR_CLK_16 0x00
#define PCC_CCR_CLK_10 0x01
#define PCC_CCR_CLK_21 0x02
#define PCC_CCR_CLK_8 0x03
#define PCC_CCR_CLK_MASK PCC_CCR_CLK_8
#define PCC_CCR_RST_CHAN(c) (0x01 << ((c) + 2))
#define PCC_CCR_RST_ALL (PCC_CCR_RST_CHAN(0) | PCC_CCR_RST_CHAN(1))
#define PCC_CCR_RST_MASK PCC_CCR_RST_ALL
/* led selection bits */
#define PCC_LED(c) (1 << (c))
#define PCC_LED_ALL (PCC_LED(0) | PCC_LED(1))
/* led state value */
#define PCC_LED_ON 0x00
#define PCC_LED_FAST 0x01
#define PCC_LED_SLOW 0x02
#define PCC_LED_OFF 0x03
#define PCC_CCR_LED_CHAN(s, c) ((s) << (((c) + 2) << 1))
#define PCC_CCR_LED_ON_CHAN(c) PCC_CCR_LED_CHAN(PCC_LED_ON, c)
#define PCC_CCR_LED_FAST_CHAN(c) PCC_CCR_LED_CHAN(PCC_LED_FAST, c)
#define PCC_CCR_LED_SLOW_CHAN(c) PCC_CCR_LED_CHAN(PCC_LED_SLOW, c)
#define PCC_CCR_LED_OFF_CHAN(c) PCC_CCR_LED_CHAN(PCC_LED_OFF, c)
#define PCC_CCR_LED_MASK_CHAN(c) PCC_CCR_LED_OFF_CHAN(c)
#define PCC_CCR_LED_OFF_ALL (PCC_CCR_LED_OFF_CHAN(0) | \
PCC_CCR_LED_OFF_CHAN(1))
#define PCC_CCR_LED_MASK PCC_CCR_LED_OFF_ALL
#define PCC_CCR_INIT (PCC_CCR_CLK_16 | PCC_CCR_RST_ALL | PCC_CCR_LED_OFF_ALL)
/* CSR bits */
#define PCC_CSR_SPI_BUSY 0x04
/* time waiting for SPI busy (prevent from infinite loop) */
#define PCC_SPI_MAX_BUSY_WAIT_MS 3
/* max count of reading the SPI status register waiting for a change */
/* (prevent from infinite loop) */
#define PCC_WRITE_MAX_LOOP 1000
/* max nb of int handled by that isr in one shot (prevent from infinite loop) */
#define PCC_ISR_MAX_LOOP 10
/* EEPROM chip instruction set */
/* note: EEPROM Read/Write instructions include A8 bit */
#define PCC_EEP_WRITE(a) (0x02 | (((a) & 0x100) >> 5))
#define PCC_EEP_READ(a) (0x03 | (((a) & 0x100) >> 5))
#define PCC_EEP_WRDI 0x04
/* EEPROM Write Disable */
#define PCC_EEP_RDSR 0x05
/* EEPROM Read Status Register */
#define PCC_EEP_WREN 0x06
/* EEPROM Write Enable */
/* EEPROM Status Register bits */
#define PCC_EEP_SR_WEN 0x02
/* EEPROM SR Write Enable bit */
#define PCC_EEP_SR_WIP 0x01
/* EEPROM SR Write In Progress bit */
/*
* 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 PCC_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 PCC_CDR (CDR_CBP | CDR_CLKOUT_MASK)
struct
pcan_channel
{
struct
net_device
*
netdev
;
unsigned
long
prev_rx_bytes
;
unsigned
long
prev_tx_bytes
;
};
/* PCAN-PC Card private structure */
struct
pcan_pccard
{
struct
pcmcia_device
*
pdev
;
int
chan_count
;
struct
pcan_channel
channel
[
PCC_CHAN_MAX
];
u8
ccr
;
u8
fw_major
;
u8
fw_minor
;
void
__iomem
*
ioport_addr
;
struct
timer_list
led_timer
;
};
static
struct
pcmcia_device_id
pcan_table
[]
=
{
PCMCIA_DEVICE_MANF_CARD
(
PCC_MANF_ID
,
PCC_CARD_ID
),
PCMCIA_DEVICE_NULL
,
};
MODULE_DEVICE_TABLE
(
pcmcia
,
pcan_table
);
static
void
pcan_set_leds
(
struct
pcan_pccard
*
card
,
u8
mask
,
u8
state
);
/*
* start timer which controls leds state
*/
static
void
pcan_start_led_timer
(
struct
pcan_pccard
*
card
)
{
if
(
!
timer_pending
(
&
card
->
led_timer
))
mod_timer
(
&
card
->
led_timer
,
jiffies
+
HZ
);
}
/*
* stop the timer which controls leds state
*/
static
void
pcan_stop_led_timer
(
struct
pcan_pccard
*
card
)
{
del_timer_sync
(
&
card
->
led_timer
);
}
/*
* read a sja1000 register
*/
static
u8
pcan_read_canreg
(
const
struct
sja1000_priv
*
priv
,
int
port
)
{
return
ioread8
(
priv
->
reg_base
+
port
);
}
/*
* write a sja1000 register
*/
static
void
pcan_write_canreg
(
const
struct
sja1000_priv
*
priv
,
int
port
,
u8
v
)
{
struct
pcan_pccard
*
card
=
priv
->
priv
;
int
c
=
(
priv
->
reg_base
-
card
->
ioport_addr
)
/
PCC_CHAN_SIZE
;
/* sja1000 register changes control the leds state */
if
(
port
==
REG_MOD
)
switch
(
v
)
{
case
MOD_RM
:
/* Reset Mode: set led on */
pcan_set_leds
(
card
,
PCC_LED
(
c
),
PCC_LED_ON
);
break
;
case
0x00
:
/* Normal Mode: led slow blinking and start led timer */
pcan_set_leds
(
card
,
PCC_LED
(
c
),
PCC_LED_SLOW
);
pcan_start_led_timer
(
card
);
break
;
default:
break
;
}
iowrite8
(
v
,
priv
->
reg_base
+
port
);
}
/*
* read a register from the common area
*/
static
u8
pcan_read_reg
(
struct
pcan_pccard
*
card
,
int
port
)
{
return
ioread8
(
card
->
ioport_addr
+
PCC_COMN_OFF
+
port
);
}
/*
* write a register into the common area
*/
static
void
pcan_write_reg
(
struct
pcan_pccard
*
card
,
int
port
,
u8
v
)
{
/* cache ccr value */
if
(
port
==
PCC_CCR
)
{
if
(
card
->
ccr
==
v
)
return
;
card
->
ccr
=
v
;
}
iowrite8
(
v
,
card
->
ioport_addr
+
PCC_COMN_OFF
+
port
);
}
/*
* check whether the card is present by checking its fw version numbers
* against values read at probing time.
*/
static
inline
int
pcan_pccard_present
(
struct
pcan_pccard
*
card
)
{
return
((
pcan_read_reg
(
card
,
PCC_FW_MAJOR
)
==
card
->
fw_major
)
&&
(
pcan_read_reg
(
card
,
PCC_FW_MINOR
)
==
card
->
fw_minor
));
}
/*
* wait for SPI engine while it is busy
*/
static
int
pcan_wait_spi_busy
(
struct
pcan_pccard
*
card
)
{
unsigned
long
timeout
=
jiffies
+
msecs_to_jiffies
(
PCC_SPI_MAX_BUSY_WAIT_MS
)
+
1
;
/* be sure to read status at least once after sleeping */
while
(
pcan_read_reg
(
card
,
PCC_CSR
)
&
PCC_CSR_SPI_BUSY
)
{
if
(
time_after
(
jiffies
,
timeout
))
return
-
EBUSY
;
schedule
();
}
return
0
;
}
/*
* write data in device eeprom
*/
static
int
pcan_write_eeprom
(
struct
pcan_pccard
*
card
,
u16
addr
,
u8
v
)
{
u8
status
;
int
err
,
i
;
/* write instruction enabling write */
pcan_write_reg
(
card
,
PCC_SPI_IR
,
PCC_EEP_WREN
);
err
=
pcan_wait_spi_busy
(
card
);
if
(
err
)
goto
we_spi_err
;
/* wait until write enabled */
for
(
i
=
0
;
i
<
PCC_WRITE_MAX_LOOP
;
i
++
)
{
/* write instruction reading the status register */
pcan_write_reg
(
card
,
PCC_SPI_IR
,
PCC_EEP_RDSR
);
err
=
pcan_wait_spi_busy
(
card
);
if
(
err
)
goto
we_spi_err
;
/* get status register value and check write enable bit */
status
=
pcan_read_reg
(
card
,
PCC_SPI_DIR
);
if
(
status
&
PCC_EEP_SR_WEN
)
break
;
}
if
(
i
>=
PCC_WRITE_MAX_LOOP
)
{
dev_err
(
&
card
->
pdev
->
dev
,
"stop waiting to be allowed to write in eeprom
\n
"
);
return
-
EIO
;
}
/* set address and data */
pcan_write_reg
(
card
,
PCC_SPI_ADR
,
addr
&
0xff
);
pcan_write_reg
(
card
,
PCC_SPI_DOR
,
v
);
/*
* write instruction with bit[3] set according to address value:
* if addr refers to upper half of the memory array: bit[3] = 1
*/
pcan_write_reg
(
card
,
PCC_SPI_IR
,
PCC_EEP_WRITE
(
addr
));
err
=
pcan_wait_spi_busy
(
card
);
if
(
err
)
goto
we_spi_err
;
/* wait while write in progress */
for
(
i
=
0
;
i
<
PCC_WRITE_MAX_LOOP
;
i
++
)
{
/* write instruction reading the status register */
pcan_write_reg
(
card
,
PCC_SPI_IR
,
PCC_EEP_RDSR
);
err
=
pcan_wait_spi_busy
(
card
);
if
(
err
)
goto
we_spi_err
;
/* get status register value and check write in progress bit */
status
=
pcan_read_reg
(
card
,
PCC_SPI_DIR
);
if
(
!
(
status
&
PCC_EEP_SR_WIP
))
break
;
}
if
(
i
>=
PCC_WRITE_MAX_LOOP
)
{
dev_err
(
&
card
->
pdev
->
dev
,
"stop waiting for write in eeprom to complete
\n
"
);
return
-
EIO
;
}
/* write instruction disabling write */
pcan_write_reg
(
card
,
PCC_SPI_IR
,
PCC_EEP_WRDI
);
err
=
pcan_wait_spi_busy
(
card
);
if
(
err
)
goto
we_spi_err
;
return
0
;
we_spi_err:
dev_err
(
&
card
->
pdev
->
dev
,
"stop waiting (spi engine always busy) err %d
\n
"
,
err
);
return
err
;
}
static
void
pcan_set_leds
(
struct
pcan_pccard
*
card
,
u8
led_mask
,
u8
state
)
{
u8
ccr
=
card
->
ccr
;
int
i
;
for
(
i
=
0
;
i
<
card
->
chan_count
;
i
++
)
if
(
led_mask
&
PCC_LED
(
i
))
{
/* clear corresponding led bits in ccr */
ccr
&=
~
PCC_CCR_LED_MASK_CHAN
(
i
);
/* then set new bits */
ccr
|=
PCC_CCR_LED_CHAN
(
state
,
i
);
}
/* real write only if something has changed in ccr */
pcan_write_reg
(
card
,
PCC_CCR
,
ccr
);
}
/*
* enable/disable CAN connectors power
*/
static
inline
void
pcan_set_can_power
(
struct
pcan_pccard
*
card
,
int
onoff
)
{
int
err
;
err
=
pcan_write_eeprom
(
card
,
0
,
!!
onoff
);
if
(
err
)
dev_err
(
&
card
->
pdev
->
dev
,
"failed setting power %s to can connectors (err %d)
\n
"
,
(
onoff
)
?
"on"
:
"off"
,
err
);
}
/*
* set leds state according to channel activity
*/
static
void
pcan_led_timer
(
unsigned
long
arg
)
{
struct
pcan_pccard
*
card
=
(
struct
pcan_pccard
*
)
arg
;
struct
net_device
*
netdev
;
int
i
,
up_count
=
0
;
u8
ccr
;
ccr
=
card
->
ccr
;
for
(
i
=
0
;
i
<
card
->
chan_count
;
i
++
)
{
/* default is: not configured */
ccr
&=
~
PCC_CCR_LED_MASK_CHAN
(
i
);
ccr
|=
PCC_CCR_LED_ON_CHAN
(
i
);
netdev
=
card
->
channel
[
i
].
netdev
;
if
(
!
netdev
||
!
(
netdev
->
flags
&
IFF_UP
))
continue
;
up_count
++
;
/* no activity (but configured) */
ccr
&=
~
PCC_CCR_LED_MASK_CHAN
(
i
);
ccr
|=
PCC_CCR_LED_SLOW_CHAN
(
i
);
/* if bytes counters changed, set fast blinking led */
if
(
netdev
->
stats
.
rx_bytes
!=
card
->
channel
[
i
].
prev_rx_bytes
)
{
card
->
channel
[
i
].
prev_rx_bytes
=
netdev
->
stats
.
rx_bytes
;
ccr
&=
~
PCC_CCR_LED_MASK_CHAN
(
i
);
ccr
|=
PCC_CCR_LED_FAST_CHAN
(
i
);
}
if
(
netdev
->
stats
.
tx_bytes
!=
card
->
channel
[
i
].
prev_tx_bytes
)
{
card
->
channel
[
i
].
prev_tx_bytes
=
netdev
->
stats
.
tx_bytes
;
ccr
&=
~
PCC_CCR_LED_MASK_CHAN
(
i
);
ccr
|=
PCC_CCR_LED_FAST_CHAN
(
i
);
}
}
/* write the new leds state */
pcan_write_reg
(
card
,
PCC_CCR
,
ccr
);
/* restart timer (except if no more configured channels) */
if
(
up_count
)
mod_timer
(
&
card
->
led_timer
,
jiffies
+
HZ
);
}
/*
* interrupt service routine
*/
static
irqreturn_t
pcan_isr
(
int
irq
,
void
*
dev_id
)
{
struct
pcan_pccard
*
card
=
dev_id
;
int
irq_handled
;
/* prevent from infinite loop */
for
(
irq_handled
=
0
;
irq_handled
<
PCC_ISR_MAX_LOOP
;
irq_handled
++
)
{
/* handle shared interrupt and next loop */
int
nothing_to_handle
=
1
;
int
i
;
/* check interrupt for each channel */
for
(
i
=
0
;
i
<
card
->
chan_count
;
i
++
)
{
struct
net_device
*
netdev
;
/*
* check whether the card is present before calling
* sja1000_interrupt() to speed up hotplug detection
*/
if
(
!
pcan_pccard_present
(
card
))
{
/* card unplugged during isr */
return
IRQ_NONE
;
}
/*
* should check whether all or SJA1000_MAX_IRQ
* interrupts have been handled: loop again to be sure.
*/
netdev
=
card
->
channel
[
i
].
netdev
;
if
(
netdev
&&
sja1000_interrupt
(
irq
,
netdev
)
==
IRQ_HANDLED
)
nothing_to_handle
=
0
;
}
if
(
nothing_to_handle
)
break
;
}
return
(
irq_handled
)
?
IRQ_HANDLED
:
IRQ_NONE
;
}
/*
* free all resources used by the channels and switch off leds and can power
*/
static
void
pcan_free_channels
(
struct
pcan_pccard
*
card
)
{
int
i
;
u8
led_mask
=
0
;
for
(
i
=
0
;
i
<
card
->
chan_count
;
i
++
)
{
struct
net_device
*
netdev
;
char
name
[
IFNAMSIZ
];
led_mask
|=
PCC_LED
(
i
);
netdev
=
card
->
channel
[
i
].
netdev
;
if
(
!
netdev
)
continue
;
strncpy
(
name
,
netdev
->
name
,
IFNAMSIZ
);
unregister_sja1000dev
(
netdev
);
free_sja1000dev
(
netdev
);
dev_info
(
&
card
->
pdev
->
dev
,
"%s removed
\n
"
,
name
);
}
/* do it only if device not removed */
if
(
pcan_pccard_present
(
card
))
{
pcan_set_leds
(
card
,
led_mask
,
PCC_LED_OFF
);
pcan_set_can_power
(
card
,
0
);
}
}
/*
* check if a CAN controller is present at the specified location
*/
static
inline
int
pcan_channel_present
(
struct
sja1000_priv
*
priv
)
{
/* make sure SJA1000 is in reset mode */
pcan_write_canreg
(
priv
,
REG_MOD
,
1
);
pcan_write_canreg
(
priv
,
REG_CDR
,
CDR_PELICAN
);
/* read reset-values */
if
(
pcan_read_canreg
(
priv
,
REG_CDR
)
==
CDR_PELICAN
)
return
1
;
return
0
;
}
static
int
pcan_add_channels
(
struct
pcan_pccard
*
card
)
{
struct
pcmcia_device
*
pdev
=
card
->
pdev
;
int
i
,
err
=
0
;
u8
ccr
=
PCC_CCR_INIT
;
/* init common registers (reset channels and leds off) */
card
->
ccr
=
~
ccr
;
pcan_write_reg
(
card
,
PCC_CCR
,
ccr
);
/* wait 2ms before unresetting channels */
mdelay
(
2
);
ccr
&=
~
PCC_CCR_RST_ALL
;
pcan_write_reg
(
card
,
PCC_CCR
,
ccr
);
/* create one network device per channel detected */
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
card
->
channel
);
i
++
)
{
struct
net_device
*
netdev
;
struct
sja1000_priv
*
priv
;
netdev
=
alloc_sja1000dev
(
0
);
if
(
!
netdev
)
{
err
=
-
ENOMEM
;
break
;
}
/* update linkages */
priv
=
netdev_priv
(
netdev
);
priv
->
priv
=
card
;
SET_NETDEV_DEV
(
netdev
,
&
pdev
->
dev
);
priv
->
irq_flags
=
IRQF_SHARED
;
netdev
->
irq
=
pdev
->
irq
;
priv
->
reg_base
=
card
->
ioport_addr
+
PCC_CHAN_OFF
(
i
);
/* check if channel is present */
if
(
!
pcan_channel_present
(
priv
))
{
dev_err
(
&
pdev
->
dev
,
"channel %d not present
\n
"
,
i
);
free_sja1000dev
(
netdev
);
continue
;
}
priv
->
read_reg
=
pcan_read_canreg
;
priv
->
write_reg
=
pcan_write_canreg
;
priv
->
can
.
clock
.
freq
=
PCC_CAN_CLOCK
;
priv
->
ocr
=
PCC_OCR
;
priv
->
cdr
=
PCC_CDR
;
/* Neither a slave device distributes the clock */
if
(
i
>
0
)
priv
->
cdr
|=
CDR_CLK_OFF
;
priv
->
flags
|=
SJA1000_CUSTOM_IRQ_HANDLER
;
/* register SJA1000 device */
err
=
register_sja1000dev
(
netdev
);
if
(
err
)
{
free_sja1000dev
(
netdev
);
continue
;
}
card
->
channel
[
i
].
netdev
=
netdev
;
card
->
chan_count
++
;
/* set corresponding led on in the new ccr */
ccr
&=
~
PCC_CCR_LED_OFF_CHAN
(
i
);
dev_info
(
&
pdev
->
dev
,
"%s on channel %d at 0x%p irq %d
\n
"
,
netdev
->
name
,
i
,
priv
->
reg_base
,
pdev
->
irq
);
}
/* write new ccr (change leds state) */
pcan_write_reg
(
card
,
PCC_CCR
,
ccr
);
return
err
;
}
static
int
pcan_conf_check
(
struct
pcmcia_device
*
pdev
,
void
*
priv_data
)
{
pdev
->
resource
[
0
]
->
flags
&=
~
IO_DATA_PATH_WIDTH
;
pdev
->
resource
[
0
]
->
flags
|=
IO_DATA_PATH_WIDTH_8
;
/* only */
pdev
->
io_lines
=
10
;
/* This reserves IO space but doesn't actually enable it */
return
pcmcia_request_io
(
pdev
);
}
/*
* free all resources used by the device
*/
static
void
pcan_free
(
struct
pcmcia_device
*
pdev
)
{
struct
pcan_pccard
*
card
=
pdev
->
priv
;
if
(
!
card
)
return
;
free_irq
(
pdev
->
irq
,
card
);
pcan_stop_led_timer
(
card
);
pcan_free_channels
(
card
);
ioport_unmap
(
card
->
ioport_addr
);
kfree
(
card
);
pdev
->
priv
=
NULL
;
}
/*
* setup PCMCIA socket and probe for PEAK-System PC-CARD
*/
static
int
__devinit
pcan_probe
(
struct
pcmcia_device
*
pdev
)
{
struct
pcan_pccard
*
card
;
int
err
;
pdev
->
config_flags
|=
CONF_ENABLE_IRQ
|
CONF_AUTO_SET_IO
;
err
=
pcmcia_loop_config
(
pdev
,
pcan_conf_check
,
NULL
);
if
(
err
)
{
dev_err
(
&
pdev
->
dev
,
"pcmcia_loop_config() error %d
\n
"
,
err
);
goto
probe_err_1
;
}
if
(
!
pdev
->
irq
)
{
dev_err
(
&
pdev
->
dev
,
"no irq assigned
\n
"
);
err
=
-
ENODEV
;
goto
probe_err_1
;
}
err
=
pcmcia_enable_device
(
pdev
);
if
(
err
)
{
dev_err
(
&
pdev
->
dev
,
"pcmcia_enable_device failed err=%d
\n
"
,
err
);
goto
probe_err_1
;
}
card
=
kzalloc
(
sizeof
(
struct
pcan_pccard
),
GFP_KERNEL
);
if
(
!
card
)
{
dev_err
(
&
pdev
->
dev
,
"couldn't allocate card memory
\n
"
);
err
=
-
ENOMEM
;
goto
probe_err_2
;
}
card
->
pdev
=
pdev
;
pdev
->
priv
=
card
;
/* sja1000 api uses iomem */
card
->
ioport_addr
=
ioport_map
(
pdev
->
resource
[
0
]
->
start
,
resource_size
(
pdev
->
resource
[
0
]));
if
(
!
card
->
ioport_addr
)
{
dev_err
(
&
pdev
->
dev
,
"couldn't map io port into io memory
\n
"
);
err
=
-
ENOMEM
;
goto
probe_err_3
;
}
card
->
fw_major
=
pcan_read_reg
(
card
,
PCC_FW_MAJOR
);
card
->
fw_minor
=
pcan_read_reg
(
card
,
PCC_FW_MINOR
);
/* display board name and firware version */
dev_info
(
&
pdev
->
dev
,
"PEAK-System pcmcia card %s fw %d.%d
\n
"
,
pdev
->
prod_id
[
1
]
?
pdev
->
prod_id
[
1
]
:
"PCAN-PC Card"
,
card
->
fw_major
,
card
->
fw_minor
);
/* detect available channels */
pcan_add_channels
(
card
);
if
(
!
card
->
chan_count
)
goto
probe_err_4
;
/* init the timer which controls the leds */
init_timer
(
&
card
->
led_timer
);
card
->
led_timer
.
function
=
pcan_led_timer
;
card
->
led_timer
.
data
=
(
unsigned
long
)
card
;
/* request the given irq */
err
=
request_irq
(
pdev
->
irq
,
&
pcan_isr
,
IRQF_SHARED
,
PCC_NAME
,
card
);
if
(
err
)
{
dev_err
(
&
pdev
->
dev
,
"couldn't request irq%d
\n
"
,
pdev
->
irq
);
goto
probe_err_5
;
}
/* power on the connectors */
pcan_set_can_power
(
card
,
1
);
return
0
;
probe_err_5:
/* unregister can devices from network */
pcan_free_channels
(
card
);
probe_err_4:
ioport_unmap
(
card
->
ioport_addr
);
probe_err_3:
kfree
(
card
);
pdev
->
priv
=
NULL
;
probe_err_2:
pcmcia_disable_device
(
pdev
);
probe_err_1:
return
err
;
}
/*
* release claimed resources
*/
static
void
pcan_remove
(
struct
pcmcia_device
*
pdev
)
{
pcan_free
(
pdev
);
pcmcia_disable_device
(
pdev
);
}
static
struct
pcmcia_driver
pcan_driver
=
{
.
name
=
PCC_NAME
,
.
probe
=
pcan_probe
,
.
remove
=
pcan_remove
,
.
id_table
=
pcan_table
,
};
static
int
__init
pcan_init
(
void
)
{
return
pcmcia_register_driver
(
&
pcan_driver
);
}
module_init
(
pcan_init
);
static
void
__exit
pcan_exit
(
void
)
{
pcmcia_unregister_driver
(
&
pcan_driver
);
}
module_exit
(
pcan_exit
);
drivers/net/can/usb/Kconfig
View file @
ffcb9738
...
...
@@ -13,4 +13,10 @@ config CAN_ESD_USB2
This driver supports the CAN-USB/2 interface
from esd electronic system design gmbh (http://www.esd.eu).
config CAN_PEAK_USB
tristate "PEAK PCAN-USB/USB Pro interfaces"
---help---
This driver supports the PCAN-USB and PCAN-USB Pro adapters
from PEAK-System Technik (http://www.peak-system.com).
endmenu
drivers/net/can/usb/Makefile
View file @
ffcb9738
...
...
@@ -4,5 +4,6 @@
obj-$(CONFIG_CAN_EMS_USB)
+=
ems_usb.o
obj-$(CONFIG_CAN_ESD_USB2)
+=
esd_usb2.o
obj-$(CONFIG_CAN_PEAK_USB)
+=
peak_usb/
ccflags-$(CONFIG_CAN_DEBUG_DEVICES)
:=
-DDEBUG
drivers/net/can/usb/peak_usb/Makefile
0 → 100644
View file @
ffcb9738
obj-$(CONFIG_CAN_PEAK_USB)
+=
peak_usb.o
peak_usb-y
=
pcan_usb_core.o pcan_usb.o pcan_usb_pro.o
drivers/net/can/usb/peak_usb/pcan_usb.c
0 → 100644
View file @
ffcb9738
/*
* CAN driver for PEAK System PCAN-USB adapter
* Derived from the PCAN project file driver/src/pcan_usb.c
*
* Copyright (C) 2003-2010 PEAK System-Technik GmbH
* Copyright (C) 2011-2012 Stephane Grosjean <s.grosjean@peak-system.com>
*
* Many thanks to Klaus Hitschler <klaus.hitschler@gmx.de>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published
* by the Free Software Foundation; version 2 of the License.
*
* 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.
*/
#include <linux/netdevice.h>
#include <linux/usb.h>
#include <linux/module.h>
#include <linux/can.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>
#include "pcan_usb_core.h"
MODULE_SUPPORTED_DEVICE
(
"PEAK-System PCAN-USB adapter"
);
/* PCAN-USB Endpoints */
#define PCAN_USB_EP_CMDOUT 1
#define PCAN_USB_EP_CMDIN (PCAN_USB_EP_CMDOUT | USB_DIR_IN)
#define PCAN_USB_EP_MSGOUT 2
#define PCAN_USB_EP_MSGIN (PCAN_USB_EP_MSGOUT | USB_DIR_IN)
/* PCAN-USB command struct */
#define PCAN_USB_CMD_FUNC 0
#define PCAN_USB_CMD_NUM 1
#define PCAN_USB_CMD_ARGS 2
#define PCAN_USB_CMD_ARGS_LEN 14
#define PCAN_USB_CMD_LEN (PCAN_USB_CMD_ARGS + \
PCAN_USB_CMD_ARGS_LEN)
/* PCAN-USB command timeout (ms.) */
#define PCAN_USB_COMMAND_TIMEOUT 1000
/* PCAN-USB startup timeout (ms.) */
#define PCAN_USB_STARTUP_TIMEOUT 10
/* PCAN-USB rx/tx buffers size */
#define PCAN_USB_RX_BUFFER_SIZE 64
#define PCAN_USB_TX_BUFFER_SIZE 64
#define PCAN_USB_MSG_HEADER_LEN 2
/* PCAN-USB adapter internal clock (MHz) */
#define PCAN_USB_CRYSTAL_HZ 16000000
/* PCAN-USB USB message record status/len field */
#define PCAN_USB_STATUSLEN_TIMESTAMP (1 << 7)
#define PCAN_USB_STATUSLEN_INTERNAL (1 << 6)
#define PCAN_USB_STATUSLEN_EXT_ID (1 << 5)
#define PCAN_USB_STATUSLEN_RTR (1 << 4)
#define PCAN_USB_STATUSLEN_DLC (0xf)
/* PCAN-USB error flags */
#define PCAN_USB_ERROR_TXFULL 0x01
#define PCAN_USB_ERROR_RXQOVR 0x02
#define PCAN_USB_ERROR_BUS_LIGHT 0x04
#define PCAN_USB_ERROR_BUS_HEAVY 0x08
#define PCAN_USB_ERROR_BUS_OFF 0x10
#define PCAN_USB_ERROR_RXQEMPTY 0x20
#define PCAN_USB_ERROR_QOVR 0x40
#define PCAN_USB_ERROR_TXQFULL 0x80
/* SJA1000 modes */
#define SJA1000_MODE_NORMAL 0x00
#define SJA1000_MODE_INIT 0x01
/*
* tick duration = 42.666 us =>
* (tick_number * 44739243) >> 20 ~ (tick_number * 42666) / 1000
* accuracy = 10^-7
*/
#define PCAN_USB_TS_DIV_SHIFTER 20
#define PCAN_USB_TS_US_PER_TICK 44739243
/* PCAN-USB messages record types */
#define PCAN_USB_REC_ERROR 1
#define PCAN_USB_REC_ANALOG 2
#define PCAN_USB_REC_BUSLOAD 3
#define PCAN_USB_REC_TS 4
#define PCAN_USB_REC_BUSEVT 5
/* private to PCAN-USB adapter */
struct
pcan_usb
{
struct
peak_usb_device
dev
;
struct
peak_time_ref
time_ref
;
struct
timer_list
restart_timer
;
};
/* incoming message context for decoding */
struct
pcan_usb_msg_context
{
u16
ts16
;
u8
prev_ts8
;
u8
*
ptr
;
u8
*
end
;
u8
rec_cnt
;
u8
rec_idx
;
u8
rec_data_idx
;
struct
net_device
*
netdev
;
struct
pcan_usb
*
pdev
;
};
/*
* send a command
*/
static
int
pcan_usb_send_cmd
(
struct
peak_usb_device
*
dev
,
u8
f
,
u8
n
,
u8
*
p
)
{
int
err
;
int
actual_length
;
/* usb device unregistered? */
if
(
!
(
dev
->
state
&
PCAN_USB_STATE_CONNECTED
))
return
0
;
dev
->
cmd_buf
[
PCAN_USB_CMD_FUNC
]
=
f
;
dev
->
cmd_buf
[
PCAN_USB_CMD_NUM
]
=
n
;
if
(
p
)
memcpy
(
dev
->
cmd_buf
+
PCAN_USB_CMD_ARGS
,
p
,
PCAN_USB_CMD_ARGS_LEN
);
err
=
usb_bulk_msg
(
dev
->
udev
,
usb_sndbulkpipe
(
dev
->
udev
,
PCAN_USB_EP_CMDOUT
),
dev
->
cmd_buf
,
PCAN_USB_CMD_LEN
,
&
actual_length
,
PCAN_USB_COMMAND_TIMEOUT
);
if
(
err
)
netdev_err
(
dev
->
netdev
,
"sending cmd f=0x%x n=0x%x failure: %d
\n
"
,
f
,
n
,
err
);
return
err
;
}
/*
* send a command then wait for its response
*/
static
int
pcan_usb_wait_rsp
(
struct
peak_usb_device
*
dev
,
u8
f
,
u8
n
,
u8
*
p
)
{
int
err
;
int
actual_length
;
/* usb device unregistered? */
if
(
!
(
dev
->
state
&
PCAN_USB_STATE_CONNECTED
))
return
0
;
/* first, send command */
err
=
pcan_usb_send_cmd
(
dev
,
f
,
n
,
NULL
);
if
(
err
)
return
err
;
err
=
usb_bulk_msg
(
dev
->
udev
,
usb_rcvbulkpipe
(
dev
->
udev
,
PCAN_USB_EP_CMDIN
),
dev
->
cmd_buf
,
PCAN_USB_CMD_LEN
,
&
actual_length
,
PCAN_USB_COMMAND_TIMEOUT
);
if
(
err
)
netdev_err
(
dev
->
netdev
,
"waiting rsp f=0x%x n=0x%x failure: %d
\n
"
,
f
,
n
,
err
);
else
if
(
p
)
memcpy
(
p
,
dev
->
cmd_buf
+
PCAN_USB_CMD_ARGS
,
PCAN_USB_CMD_ARGS_LEN
);
return
err
;
}
static
int
pcan_usb_set_sja1000
(
struct
peak_usb_device
*
dev
,
u8
mode
)
{
u8
args
[
PCAN_USB_CMD_ARGS_LEN
]
=
{
[
1
]
=
mode
,
};
return
pcan_usb_send_cmd
(
dev
,
9
,
2
,
args
);
}
static
int
pcan_usb_set_bus
(
struct
peak_usb_device
*
dev
,
u8
onoff
)
{
u8
args
[
PCAN_USB_CMD_ARGS_LEN
]
=
{
[
0
]
=
!!
onoff
,
};
return
pcan_usb_send_cmd
(
dev
,
3
,
2
,
args
);
}
static
int
pcan_usb_set_silent
(
struct
peak_usb_device
*
dev
,
u8
onoff
)
{
u8
args
[
PCAN_USB_CMD_ARGS_LEN
]
=
{
[
0
]
=
!!
onoff
,
};
return
pcan_usb_send_cmd
(
dev
,
3
,
3
,
args
);
}
static
int
pcan_usb_set_ext_vcc
(
struct
peak_usb_device
*
dev
,
u8
onoff
)
{
u8
args
[
PCAN_USB_CMD_ARGS_LEN
]
=
{
[
0
]
=
!!
onoff
,
};
return
pcan_usb_send_cmd
(
dev
,
10
,
2
,
args
);
}
/*
* set bittiming value to can
*/
static
int
pcan_usb_set_bittiming
(
struct
peak_usb_device
*
dev
,
struct
can_bittiming
*
bt
)
{
u8
args
[
PCAN_USB_CMD_ARGS_LEN
];
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
);
if
(
dev
->
can
.
ctrlmode
&
CAN_CTRLMODE_3_SAMPLES
)
btr1
|=
0x80
;
netdev_info
(
dev
->
netdev
,
"setting BTR0=0x%02x BTR1=0x%02x
\n
"
,
btr0
,
btr1
);
args
[
0
]
=
btr1
;
args
[
1
]
=
btr0
;
return
pcan_usb_send_cmd
(
dev
,
1
,
2
,
args
);
}
/*
* init/reset can
*/
static
int
pcan_usb_write_mode
(
struct
peak_usb_device
*
dev
,
u8
onoff
)
{
int
err
;
err
=
pcan_usb_set_bus
(
dev
,
onoff
);
if
(
err
)
return
err
;
if
(
!
onoff
)
{
err
=
pcan_usb_set_sja1000
(
dev
,
SJA1000_MODE_INIT
);
}
else
{
/* the PCAN-USB needs time to init */
set_current_state
(
TASK_INTERRUPTIBLE
);
schedule_timeout
(
msecs_to_jiffies
(
PCAN_USB_STARTUP_TIMEOUT
));
}
return
err
;
}
/*
* handle end of waiting for the device to reset
*/
static
void
pcan_usb_restart
(
unsigned
long
arg
)
{
/* notify candev and netdev */
peak_usb_restart_complete
((
struct
peak_usb_device
*
)
arg
);
}
/*
* handle the submission of the restart urb
*/
static
void
pcan_usb_restart_pending
(
struct
urb
*
urb
)
{
struct
pcan_usb
*
pdev
=
urb
->
context
;
/* the PCAN-USB needs time to restart */
mod_timer
(
&
pdev
->
restart_timer
,
jiffies
+
msecs_to_jiffies
(
PCAN_USB_STARTUP_TIMEOUT
));
/* can delete usb resources */
peak_usb_async_complete
(
urb
);
}
/*
* handle asynchronous restart
*/
static
int
pcan_usb_restart_async
(
struct
peak_usb_device
*
dev
,
struct
urb
*
urb
,
u8
*
buf
)
{
struct
pcan_usb
*
pdev
=
container_of
(
dev
,
struct
pcan_usb
,
dev
);
if
(
timer_pending
(
&
pdev
->
restart_timer
))
return
-
EBUSY
;
/* set bus on */
buf
[
PCAN_USB_CMD_FUNC
]
=
3
;
buf
[
PCAN_USB_CMD_NUM
]
=
2
;
buf
[
PCAN_USB_CMD_ARGS
]
=
1
;
usb_fill_bulk_urb
(
urb
,
dev
->
udev
,
usb_sndbulkpipe
(
dev
->
udev
,
PCAN_USB_EP_CMDOUT
),
buf
,
PCAN_USB_CMD_LEN
,
pcan_usb_restart_pending
,
pdev
);
return
usb_submit_urb
(
urb
,
GFP_ATOMIC
);
}
/*
* read serial number from device
*/
static
int
pcan_usb_get_serial
(
struct
peak_usb_device
*
dev
,
u32
*
serial_number
)
{
u8
args
[
PCAN_USB_CMD_ARGS_LEN
];
int
err
;
err
=
pcan_usb_wait_rsp
(
dev
,
6
,
1
,
args
);
if
(
err
)
{
netdev_err
(
dev
->
netdev
,
"getting serial failure: %d
\n
"
,
err
);
}
else
if
(
serial_number
)
{
u32
tmp32
;
memcpy
(
&
tmp32
,
args
,
4
);
*
serial_number
=
le32_to_cpu
(
tmp32
);
}
return
err
;
}
/*
* read device id from device
*/
static
int
pcan_usb_get_device_id
(
struct
peak_usb_device
*
dev
,
u32
*
device_id
)
{
u8
args
[
PCAN_USB_CMD_ARGS_LEN
];
int
err
;
err
=
pcan_usb_wait_rsp
(
dev
,
4
,
1
,
args
);
if
(
err
)
netdev_err
(
dev
->
netdev
,
"getting device id failure: %d
\n
"
,
err
);
else
if
(
device_id
)
*
device_id
=
args
[
0
];
return
err
;
}
/*
* update current time ref with received timestamp
*/
static
int
pcan_usb_update_ts
(
struct
pcan_usb_msg_context
*
mc
)
{
u16
tmp16
;
if
((
mc
->
ptr
+
2
)
>
mc
->
end
)
return
-
EINVAL
;
memcpy
(
&
tmp16
,
mc
->
ptr
,
2
);
mc
->
ts16
=
le16_to_cpu
(
tmp16
);
if
(
mc
->
rec_idx
>
0
)
peak_usb_update_ts_now
(
&
mc
->
pdev
->
time_ref
,
mc
->
ts16
);
else
peak_usb_set_ts_now
(
&
mc
->
pdev
->
time_ref
,
mc
->
ts16
);
return
0
;
}
/*
* decode received timestamp
*/
static
int
pcan_usb_decode_ts
(
struct
pcan_usb_msg_context
*
mc
,
u8
first_packet
)
{
/* only 1st packet supplies a word timestamp */
if
(
first_packet
)
{
u16
tmp16
;
if
((
mc
->
ptr
+
2
)
>
mc
->
end
)
return
-
EINVAL
;
memcpy
(
&
tmp16
,
mc
->
ptr
,
2
);
mc
->
ptr
+=
2
;
mc
->
ts16
=
le16_to_cpu
(
tmp16
);
mc
->
prev_ts8
=
mc
->
ts16
&
0x00ff
;
}
else
{
u8
ts8
;
if
((
mc
->
ptr
+
1
)
>
mc
->
end
)
return
-
EINVAL
;
ts8
=
*
mc
->
ptr
++
;
if
(
ts8
<
mc
->
prev_ts8
)
mc
->
ts16
+=
0x100
;
mc
->
ts16
&=
0xff00
;
mc
->
ts16
|=
ts8
;
mc
->
prev_ts8
=
ts8
;
}
return
0
;
}
static
int
pcan_usb_decode_error
(
struct
pcan_usb_msg_context
*
mc
,
u8
n
,
u8
status_len
)
{
struct
sk_buff
*
skb
;
struct
can_frame
*
cf
;
struct
timeval
tv
;
enum
can_state
new_state
;
/* ignore this error until 1st ts received */
if
(
n
==
PCAN_USB_ERROR_QOVR
)
if
(
!
mc
->
pdev
->
time_ref
.
tick_count
)
return
0
;
new_state
=
mc
->
pdev
->
dev
.
can
.
state
;
switch
(
mc
->
pdev
->
dev
.
can
.
state
)
{
case
CAN_STATE_ERROR_ACTIVE
:
if
(
n
&
PCAN_USB_ERROR_BUS_LIGHT
)
{
new_state
=
CAN_STATE_ERROR_WARNING
;
break
;
}
case
CAN_STATE_ERROR_WARNING
:
if
(
n
&
PCAN_USB_ERROR_BUS_HEAVY
)
{
new_state
=
CAN_STATE_ERROR_PASSIVE
;
break
;
}
if
(
n
&
PCAN_USB_ERROR_BUS_OFF
)
{
new_state
=
CAN_STATE_BUS_OFF
;
break
;
}
if
(
n
&
(
PCAN_USB_ERROR_RXQOVR
|
PCAN_USB_ERROR_QOVR
))
{
/*
* trick to bypass next comparison and process other
* errors
*/
new_state
=
CAN_STATE_MAX
;
break
;
}
if
((
n
&
PCAN_USB_ERROR_BUS_LIGHT
)
==
0
)
{
/* no error (back to active state) */
mc
->
pdev
->
dev
.
can
.
state
=
CAN_STATE_ERROR_ACTIVE
;
return
0
;
}
break
;
case
CAN_STATE_ERROR_PASSIVE
:
if
(
n
&
PCAN_USB_ERROR_BUS_OFF
)
{
new_state
=
CAN_STATE_BUS_OFF
;
break
;
}
if
(
n
&
PCAN_USB_ERROR_BUS_LIGHT
)
{
new_state
=
CAN_STATE_ERROR_WARNING
;
break
;
}
if
(
n
&
(
PCAN_USB_ERROR_RXQOVR
|
PCAN_USB_ERROR_QOVR
))
{
/*
* trick to bypass next comparison and process other
* errors
*/
new_state
=
CAN_STATE_MAX
;
break
;
}
if
((
n
&
PCAN_USB_ERROR_BUS_HEAVY
)
==
0
)
{
/* no error (back to active state) */
mc
->
pdev
->
dev
.
can
.
state
=
CAN_STATE_ERROR_ACTIVE
;
return
0
;
}
break
;
default:
/* do nothing waiting for restart */
return
0
;
}
/* donot post any error if current state didn't change */
if
(
mc
->
pdev
->
dev
.
can
.
state
==
new_state
)
return
0
;
/* allocate an skb to store the error frame */
skb
=
alloc_can_err_skb
(
mc
->
netdev
,
&
cf
);
if
(
!
skb
)
return
-
ENOMEM
;
switch
(
new_state
)
{
case
CAN_STATE_BUS_OFF
:
cf
->
can_id
|=
CAN_ERR_BUSOFF
;
can_bus_off
(
mc
->
netdev
);
break
;
case
CAN_STATE_ERROR_PASSIVE
:
cf
->
can_id
|=
CAN_ERR_CRTL
;
cf
->
data
[
1
]
|=
CAN_ERR_CRTL_TX_PASSIVE
|
CAN_ERR_CRTL_RX_PASSIVE
;
mc
->
pdev
->
dev
.
can
.
can_stats
.
error_passive
++
;
break
;
case
CAN_STATE_ERROR_WARNING
:
cf
->
can_id
|=
CAN_ERR_CRTL
;
cf
->
data
[
1
]
|=
CAN_ERR_CRTL_TX_WARNING
|
CAN_ERR_CRTL_RX_WARNING
;
mc
->
pdev
->
dev
.
can
.
can_stats
.
error_warning
++
;
break
;
default:
/* CAN_STATE_MAX (trick to handle other errors) */
cf
->
can_id
|=
CAN_ERR_CRTL
;
cf
->
data
[
1
]
|=
CAN_ERR_CRTL_RX_OVERFLOW
;
mc
->
netdev
->
stats
.
rx_over_errors
++
;
mc
->
netdev
->
stats
.
rx_errors
++
;
new_state
=
mc
->
pdev
->
dev
.
can
.
state
;
break
;
}
mc
->
pdev
->
dev
.
can
.
state
=
new_state
;
if
(
status_len
&
PCAN_USB_STATUSLEN_TIMESTAMP
)
{
peak_usb_get_ts_tv
(
&
mc
->
pdev
->
time_ref
,
mc
->
ts16
,
&
tv
);
skb
->
tstamp
=
timeval_to_ktime
(
tv
);
}
netif_rx
(
skb
);
mc
->
netdev
->
stats
.
rx_packets
++
;
mc
->
netdev
->
stats
.
rx_bytes
+=
cf
->
can_dlc
;
return
0
;
}
/*
* decode non-data usb message
*/
static
int
pcan_usb_decode_status
(
struct
pcan_usb_msg_context
*
mc
,
u8
status_len
)
{
u8
rec_len
=
status_len
&
PCAN_USB_STATUSLEN_DLC
;
u8
f
,
n
;
int
err
;
/* check whether function and number can be read */
if
((
mc
->
ptr
+
2
)
>
mc
->
end
)
return
-
EINVAL
;
f
=
mc
->
ptr
[
PCAN_USB_CMD_FUNC
];
n
=
mc
->
ptr
[
PCAN_USB_CMD_NUM
];
mc
->
ptr
+=
PCAN_USB_CMD_ARGS
;
if
(
status_len
&
PCAN_USB_STATUSLEN_TIMESTAMP
)
{
int
err
=
pcan_usb_decode_ts
(
mc
,
!
mc
->
rec_idx
);
if
(
err
)
return
err
;
}
switch
(
f
)
{
case
PCAN_USB_REC_ERROR
:
err
=
pcan_usb_decode_error
(
mc
,
n
,
status_len
);
if
(
err
)
return
err
;
break
;
case
PCAN_USB_REC_ANALOG
:
/* analog values (ignored) */
rec_len
=
2
;
break
;
case
PCAN_USB_REC_BUSLOAD
:
/* bus load (ignored) */
rec_len
=
1
;
break
;
case
PCAN_USB_REC_TS
:
/* only timestamp */
if
(
pcan_usb_update_ts
(
mc
))
return
-
EINVAL
;
break
;
case
PCAN_USB_REC_BUSEVT
:
/* error frame/bus event */
if
(
n
&
PCAN_USB_ERROR_TXQFULL
)
netdev_dbg
(
mc
->
netdev
,
"device Tx queue full)
\n
"
);
break
;
default:
netdev_err
(
mc
->
netdev
,
"unexpected function %u
\n
"
,
f
);
break
;
}
if
((
mc
->
ptr
+
rec_len
)
>
mc
->
end
)
return
-
EINVAL
;
mc
->
ptr
+=
rec_len
;
return
0
;
}
/*
* decode data usb message
*/
static
int
pcan_usb_decode_data
(
struct
pcan_usb_msg_context
*
mc
,
u8
status_len
)
{
u8
rec_len
=
status_len
&
PCAN_USB_STATUSLEN_DLC
;
struct
sk_buff
*
skb
;
struct
can_frame
*
cf
;
struct
timeval
tv
;
skb
=
alloc_can_skb
(
mc
->
netdev
,
&
cf
);
if
(
!
skb
)
return
-
ENOMEM
;
if
(
status_len
&
PCAN_USB_STATUSLEN_EXT_ID
)
{
u32
tmp32
;
if
((
mc
->
ptr
+
4
)
>
mc
->
end
)
goto
decode_failed
;
memcpy
(
&
tmp32
,
mc
->
ptr
,
4
);
mc
->
ptr
+=
4
;
cf
->
can_id
=
le32_to_cpu
(
tmp32
>>
3
)
|
CAN_EFF_FLAG
;
}
else
{
u16
tmp16
;
if
((
mc
->
ptr
+
2
)
>
mc
->
end
)
goto
decode_failed
;
memcpy
(
&
tmp16
,
mc
->
ptr
,
2
);
mc
->
ptr
+=
2
;
cf
->
can_id
=
le16_to_cpu
(
tmp16
>>
5
);
}
cf
->
can_dlc
=
get_can_dlc
(
rec_len
);
/* first data packet timestamp is a word */
if
(
pcan_usb_decode_ts
(
mc
,
!
mc
->
rec_data_idx
))
goto
decode_failed
;
/* read data */
memset
(
cf
->
data
,
0x0
,
sizeof
(
cf
->
data
));
if
(
status_len
&
PCAN_USB_STATUSLEN_RTR
)
{
cf
->
can_id
|=
CAN_RTR_FLAG
;
}
else
{
if
((
mc
->
ptr
+
rec_len
)
>
mc
->
end
)
goto
decode_failed
;
memcpy
(
cf
->
data
,
mc
->
ptr
,
rec_len
);
mc
->
ptr
+=
rec_len
;
}
/* convert timestamp into kernel time */
peak_usb_get_ts_tv
(
&
mc
->
pdev
->
time_ref
,
mc
->
ts16
,
&
tv
);
skb
->
tstamp
=
timeval_to_ktime
(
tv
);
/* push the skb */
netif_rx
(
skb
);
/* update statistics */
mc
->
netdev
->
stats
.
rx_packets
++
;
mc
->
netdev
->
stats
.
rx_bytes
+=
cf
->
can_dlc
;
return
0
;
decode_failed:
dev_kfree_skb
(
skb
);
return
-
EINVAL
;
}
/*
* process incoming message
*/
static
int
pcan_usb_decode_msg
(
struct
peak_usb_device
*
dev
,
u8
*
ibuf
,
u32
lbuf
)
{
struct
pcan_usb_msg_context
mc
=
{
.
rec_cnt
=
ibuf
[
1
],
.
ptr
=
ibuf
+
PCAN_USB_MSG_HEADER_LEN
,
.
end
=
ibuf
+
lbuf
,
.
netdev
=
dev
->
netdev
,
.
pdev
=
container_of
(
dev
,
struct
pcan_usb
,
dev
),
};
int
err
;
for
(
err
=
0
;
mc
.
rec_idx
<
mc
.
rec_cnt
&&
!
err
;
mc
.
rec_idx
++
)
{
u8
sl
=
*
mc
.
ptr
++
;
/* handle status and error frames here */
if
(
sl
&
PCAN_USB_STATUSLEN_INTERNAL
)
{
err
=
pcan_usb_decode_status
(
&
mc
,
sl
);
/* handle normal can frames here */
}
else
{
err
=
pcan_usb_decode_data
(
&
mc
,
sl
);
mc
.
rec_data_idx
++
;
}
}
return
err
;
}
/*
* process any incoming buffer
*/
static
int
pcan_usb_decode_buf
(
struct
peak_usb_device
*
dev
,
struct
urb
*
urb
)
{
int
err
=
0
;
if
(
urb
->
actual_length
>
PCAN_USB_MSG_HEADER_LEN
)
{
err
=
pcan_usb_decode_msg
(
dev
,
urb
->
transfer_buffer
,
urb
->
actual_length
);
}
else
if
(
urb
->
actual_length
>
0
)
{
netdev_err
(
dev
->
netdev
,
"usb message length error (%u)
\n
"
,
urb
->
actual_length
);
err
=
-
EINVAL
;
}
return
err
;
}
/*
* process outgoing packet
*/
static
int
pcan_usb_encode_msg
(
struct
peak_usb_device
*
dev
,
struct
sk_buff
*
skb
,
u8
*
obuf
,
size_t
*
size
)
{
struct
net_device
*
netdev
=
dev
->
netdev
;
struct
net_device_stats
*
stats
=
&
netdev
->
stats
;
struct
can_frame
*
cf
=
(
struct
can_frame
*
)
skb
->
data
;
u8
*
pc
;
obuf
[
0
]
=
2
;
obuf
[
1
]
=
1
;
pc
=
obuf
+
PCAN_USB_MSG_HEADER_LEN
;
/* status/len byte */
*
pc
=
cf
->
can_dlc
;
if
(
cf
->
can_id
&
CAN_RTR_FLAG
)
*
pc
|=
PCAN_USB_STATUSLEN_RTR
;
/* can id */
if
(
cf
->
can_id
&
CAN_EFF_FLAG
)
{
__le32
tmp32
=
cpu_to_le32
(
cf
->
can_id
&
CAN_ERR_MASK
);
tmp32
<<=
3
;
*
pc
|=
PCAN_USB_STATUSLEN_EXT_ID
;
memcpy
(
++
pc
,
&
tmp32
,
4
);
pc
+=
4
;
}
else
{
__le16
tmp16
=
cpu_to_le32
(
cf
->
can_id
&
CAN_ERR_MASK
);
tmp16
<<=
5
;
memcpy
(
++
pc
,
&
tmp16
,
2
);
pc
+=
2
;
}
/* can data */
if
(
!
(
cf
->
can_id
&
CAN_RTR_FLAG
))
{
memcpy
(
pc
,
cf
->
data
,
cf
->
can_dlc
);
pc
+=
cf
->
can_dlc
;
}
obuf
[(
*
size
)
-
1
]
=
(
u8
)(
stats
->
tx_packets
&
0xff
);
return
0
;
}
/*
* start interface
*/
static
int
pcan_usb_start
(
struct
peak_usb_device
*
dev
)
{
struct
pcan_usb
*
pdev
=
container_of
(
dev
,
struct
pcan_usb
,
dev
);
/* number of bits used in timestamps read from adapter struct */
peak_usb_init_time_ref
(
&
pdev
->
time_ref
,
&
pcan_usb
);
/* if revision greater than 3, can put silent mode on/off */
if
(
dev
->
device_rev
>
3
)
{
int
err
;
err
=
pcan_usb_set_silent
(
dev
,
dev
->
can
.
ctrlmode
&
CAN_CTRLMODE_LISTENONLY
);
if
(
err
)
return
err
;
}
return
pcan_usb_set_ext_vcc
(
dev
,
0
);
}
static
int
pcan_usb_init
(
struct
peak_usb_device
*
dev
)
{
struct
pcan_usb
*
pdev
=
container_of
(
dev
,
struct
pcan_usb
,
dev
);
u32
serial_number
;
int
err
;
/* initialize a timer needed to wait for hardware restart */
init_timer
(
&
pdev
->
restart_timer
);
pdev
->
restart_timer
.
function
=
pcan_usb_restart
;
pdev
->
restart_timer
.
data
=
(
unsigned
long
)
dev
;
/*
* explicit use of dev_xxx() instead of netdev_xxx() here:
* information displayed are related to the device itself, not
* to the canx netdevice.
*/
err
=
pcan_usb_get_serial
(
dev
,
&
serial_number
);
if
(
err
)
{
dev_err
(
dev
->
netdev
->
dev
.
parent
,
"unable to read %s serial number (err %d)
\n
"
,
pcan_usb
.
name
,
err
);
return
err
;
}
dev_info
(
dev
->
netdev
->
dev
.
parent
,
"PEAK-System %s adapter hwrev %u serial %08X (%u channel)
\n
"
,
pcan_usb
.
name
,
dev
->
device_rev
,
serial_number
,
pcan_usb
.
ctrl_count
);
return
0
;
}
/*
* probe function for new PCAN-USB usb interface
*/
static
int
pcan_usb_probe
(
struct
usb_interface
*
intf
)
{
struct
usb_host_interface
*
if_desc
;
int
i
;
if_desc
=
intf
->
altsetting
;
/* check interface endpoint addresses */
for
(
i
=
0
;
i
<
if_desc
->
desc
.
bNumEndpoints
;
i
++
)
{
struct
usb_endpoint_descriptor
*
ep
=
&
if_desc
->
endpoint
[
i
].
desc
;
switch
(
ep
->
bEndpointAddress
)
{
case
PCAN_USB_EP_CMDOUT
:
case
PCAN_USB_EP_CMDIN
:
case
PCAN_USB_EP_MSGOUT
:
case
PCAN_USB_EP_MSGIN
:
break
;
default:
return
-
ENODEV
;
}
}
return
0
;
}
/*
* describe the PCAN-USB adapter
*/
struct
peak_usb_adapter
pcan_usb
=
{
.
name
=
"PCAN-USB"
,
.
device_id
=
PCAN_USB_PRODUCT_ID
,
.
ctrl_count
=
1
,
.
clock
=
{
.
freq
=
PCAN_USB_CRYSTAL_HZ
/
2
,
},
.
bittiming_const
=
{
.
name
=
"pcan_usb"
,
.
tseg1_min
=
1
,
.
tseg1_max
=
16
,
.
tseg2_min
=
1
,
.
tseg2_max
=
8
,
.
sjw_max
=
4
,
.
brp_min
=
1
,
.
brp_max
=
64
,
.
brp_inc
=
1
,
},
/* size of device private data */
.
sizeof_dev_private
=
sizeof
(
struct
pcan_usb
),
/* timestamps usage */
.
ts_used_bits
=
16
,
.
ts_period
=
24575
,
/* calibration period in ts. */
.
us_per_ts_scale
=
PCAN_USB_TS_US_PER_TICK
,
/* us=(ts*scale) */
.
us_per_ts_shift
=
PCAN_USB_TS_DIV_SHIFTER
,
/* >> shift */
/* give here messages in/out endpoints */
.
ep_msg_in
=
PCAN_USB_EP_MSGIN
,
.
ep_msg_out
=
{
PCAN_USB_EP_MSGOUT
},
/* size of rx/tx usb buffers */
.
rx_buffer_size
=
PCAN_USB_RX_BUFFER_SIZE
,
.
tx_buffer_size
=
PCAN_USB_TX_BUFFER_SIZE
,
/* device callbacks */
.
intf_probe
=
pcan_usb_probe
,
.
dev_init
=
pcan_usb_init
,
.
dev_set_bus
=
pcan_usb_write_mode
,
.
dev_set_bittiming
=
pcan_usb_set_bittiming
,
.
dev_get_device_id
=
pcan_usb_get_device_id
,
.
dev_decode_buf
=
pcan_usb_decode_buf
,
.
dev_encode_msg
=
pcan_usb_encode_msg
,
.
dev_start
=
pcan_usb_start
,
.
dev_restart_async
=
pcan_usb_restart_async
,
};
drivers/net/can/usb/peak_usb/pcan_usb_core.c
0 → 100644
View file @
ffcb9738
/*
* CAN driver for PEAK System USB adapters
* Derived from the PCAN project file driver/src/pcan_usb_core.c
*
* Copyright (C) 2003-2010 PEAK System-Technik GmbH
* Copyright (C) 2010-2012 Stephane Grosjean <s.grosjean@peak-system.com>
*
* Many thanks to Klaus Hitschler <klaus.hitschler@gmx.de>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published
* by the Free Software Foundation; version 2 of the License.
*
* 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.
*/
#include <linux/init.h>
#include <linux/signal.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/usb.h>
#include <linux/can.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>
#include "pcan_usb_core.h"
MODULE_AUTHOR
(
"Stephane Grosjean <s.grosjean@peak-system.com>"
);
MODULE_DESCRIPTION
(
"CAN driver for PEAK-System USB adapters"
);
MODULE_LICENSE
(
"GPL v2"
);
/* Table of devices that work with this driver */
static
struct
usb_device_id
peak_usb_table
[]
=
{
{
USB_DEVICE
(
PCAN_USB_VENDOR_ID
,
PCAN_USB_PRODUCT_ID
)},
{
USB_DEVICE
(
PCAN_USB_VENDOR_ID
,
PCAN_USBPRO_PRODUCT_ID
)},
{}
/* Terminating entry */
};
MODULE_DEVICE_TABLE
(
usb
,
peak_usb_table
);
/* List of supported PCAN-USB adapters (NULL terminated list) */
static
struct
peak_usb_adapter
*
peak_usb_adapters_list
[]
=
{
&
pcan_usb
,
&
pcan_usb_pro
,
NULL
,
};
/*
* dump memory
*/
#define DUMP_WIDTH 16
void
dump_mem
(
char
*
prompt
,
void
*
p
,
int
l
)
{
pr_info
(
"%s dumping %s (%d bytes):
\n
"
,
PCAN_USB_DRIVER_NAME
,
prompt
?
prompt
:
"memory"
,
l
);
print_hex_dump
(
KERN_INFO
,
PCAN_USB_DRIVER_NAME
" "
,
DUMP_PREFIX_NONE
,
DUMP_WIDTH
,
1
,
p
,
l
,
false
);
}
/*
* initialize a time_ref object with usb adapter own settings
*/
void
peak_usb_init_time_ref
(
struct
peak_time_ref
*
time_ref
,
struct
peak_usb_adapter
*
adapter
)
{
if
(
time_ref
)
{
memset
(
time_ref
,
0
,
sizeof
(
struct
peak_time_ref
));
time_ref
->
adapter
=
adapter
;
}
}
static
void
peak_usb_add_us
(
struct
timeval
*
tv
,
u32
delta_us
)
{
/* number of s. to add to final time */
u32
delta_s
=
delta_us
/
1000000
;
delta_us
-=
delta_s
*
1000000
;
tv
->
tv_usec
+=
delta_us
;
if
(
tv
->
tv_usec
>=
1000000
)
{
tv
->
tv_usec
-=
1000000
;
delta_s
++
;
}
tv
->
tv_sec
+=
delta_s
;
}
/*
* sometimes, another now may be more recent than current one...
*/
void
peak_usb_update_ts_now
(
struct
peak_time_ref
*
time_ref
,
u32
ts_now
)
{
time_ref
->
ts_dev_2
=
ts_now
;
/* should wait at least two passes before computing */
if
(
time_ref
->
tv_host
.
tv_sec
>
0
)
{
u32
delta_ts
=
time_ref
->
ts_dev_2
-
time_ref
->
ts_dev_1
;
if
(
time_ref
->
ts_dev_2
<
time_ref
->
ts_dev_1
)
delta_ts
&=
(
1
<<
time_ref
->
adapter
->
ts_used_bits
)
-
1
;
time_ref
->
ts_total
+=
delta_ts
;
}
}
/*
* register device timestamp as now
*/
void
peak_usb_set_ts_now
(
struct
peak_time_ref
*
time_ref
,
u32
ts_now
)
{
if
(
time_ref
->
tv_host_0
.
tv_sec
==
0
)
{
/* use monotonic clock to correctly compute further deltas */
time_ref
->
tv_host_0
=
ktime_to_timeval
(
ktime_get
());
time_ref
->
tv_host
.
tv_sec
=
0
;
}
else
{
/*
* delta_us should not be >= 2^32 => delta_s should be < 4294
* handle 32-bits wrapping here: if count of s. reaches 4200,
* reset counters and change time base
*/
if
(
time_ref
->
tv_host
.
tv_sec
!=
0
)
{
u32
delta_s
=
time_ref
->
tv_host
.
tv_sec
-
time_ref
->
tv_host_0
.
tv_sec
;
if
(
delta_s
>
4200
)
{
time_ref
->
tv_host_0
=
time_ref
->
tv_host
;
time_ref
->
ts_total
=
0
;
}
}
time_ref
->
tv_host
=
ktime_to_timeval
(
ktime_get
());
time_ref
->
tick_count
++
;
}
time_ref
->
ts_dev_1
=
time_ref
->
ts_dev_2
;
peak_usb_update_ts_now
(
time_ref
,
ts_now
);
}
/*
* compute timeval according to current ts and time_ref data
*/
void
peak_usb_get_ts_tv
(
struct
peak_time_ref
*
time_ref
,
u32
ts
,
struct
timeval
*
tv
)
{
/* protect from getting timeval before setting now */
if
(
time_ref
->
tv_host
.
tv_sec
>
0
)
{
u64
delta_us
;
delta_us
=
ts
-
time_ref
->
ts_dev_2
;
if
(
ts
<
time_ref
->
ts_dev_2
)
delta_us
&=
(
1
<<
time_ref
->
adapter
->
ts_used_bits
)
-
1
;
delta_us
+=
time_ref
->
ts_total
;
delta_us
*=
time_ref
->
adapter
->
us_per_ts_scale
;
delta_us
>>=
time_ref
->
adapter
->
us_per_ts_shift
;
*
tv
=
time_ref
->
tv_host_0
;
peak_usb_add_us
(
tv
,
(
u32
)
delta_us
);
}
else
{
*
tv
=
ktime_to_timeval
(
ktime_get
());
}
}
/*
* callback for bulk Rx urb
*/
static
void
peak_usb_read_bulk_callback
(
struct
urb
*
urb
)
{
struct
peak_usb_device
*
dev
=
urb
->
context
;
struct
net_device
*
netdev
;
int
err
;
netdev
=
dev
->
netdev
;
if
(
!
netif_device_present
(
netdev
))
return
;
/* check reception status */
switch
(
urb
->
status
)
{
case
0
:
/* success */
break
;
case
-
EILSEQ
:
case
-
ENOENT
:
case
-
ECONNRESET
:
case
-
ESHUTDOWN
:
return
;
default:
if
(
net_ratelimit
())
netdev_err
(
netdev
,
"Rx urb aborted (%d)
\n
"
,
urb
->
status
);
goto
resubmit_urb
;
}
/* protect from any incoming empty msgs */
if
((
urb
->
actual_length
>
0
)
&&
(
dev
->
adapter
->
dev_decode_buf
))
{
/* handle these kinds of msgs only if _start callback called */
if
(
dev
->
state
&
PCAN_USB_STATE_STARTED
)
{
err
=
dev
->
adapter
->
dev_decode_buf
(
dev
,
urb
);
if
(
err
)
dump_mem
(
"received usb message"
,
urb
->
transfer_buffer
,
urb
->
transfer_buffer_length
);
}
}
resubmit_urb:
usb_fill_bulk_urb
(
urb
,
dev
->
udev
,
usb_rcvbulkpipe
(
dev
->
udev
,
dev
->
ep_msg_in
),
urb
->
transfer_buffer
,
dev
->
adapter
->
rx_buffer_size
,
peak_usb_read_bulk_callback
,
dev
);
usb_anchor_urb
(
urb
,
&
dev
->
rx_submitted
);
err
=
usb_submit_urb
(
urb
,
GFP_ATOMIC
);
if
(
!
err
)
return
;
usb_unanchor_urb
(
urb
);
if
(
err
==
-
ENODEV
)
netif_device_detach
(
netdev
);
else
netdev_err
(
netdev
,
"failed resubmitting read bulk urb: %d
\n
"
,
err
);
}
/*
* callback for bulk Tx urb
*/
static
void
peak_usb_write_bulk_callback
(
struct
urb
*
urb
)
{
struct
peak_tx_urb_context
*
context
=
urb
->
context
;
struct
peak_usb_device
*
dev
;
struct
net_device
*
netdev
;
BUG_ON
(
!
context
);
dev
=
context
->
dev
;
netdev
=
dev
->
netdev
;
atomic_dec
(
&
dev
->
active_tx_urbs
);
if
(
!
netif_device_present
(
netdev
))
return
;
/* check tx status */
switch
(
urb
->
status
)
{
case
0
:
/* transmission complete */
netdev
->
stats
.
tx_packets
++
;
netdev
->
stats
.
tx_bytes
+=
context
->
dlc
;
/* prevent tx timeout */
netdev
->
trans_start
=
jiffies
;
break
;
default:
if
(
net_ratelimit
())
netdev_err
(
netdev
,
"Tx urb aborted (%d)
\n
"
,
urb
->
status
);
case
-
EPROTO
:
case
-
ENOENT
:
case
-
ECONNRESET
:
case
-
ESHUTDOWN
:
break
;
}
/* should always release echo skb and corresponding context */
can_get_echo_skb
(
netdev
,
context
->
echo_index
);
context
->
echo_index
=
PCAN_USB_MAX_TX_URBS
;
/* do wakeup tx queue in case of success only */
if
(
!
urb
->
status
)
netif_wake_queue
(
netdev
);
}
/*
* called by netdev to send one skb on the CAN interface.
*/
static
netdev_tx_t
peak_usb_ndo_start_xmit
(
struct
sk_buff
*
skb
,
struct
net_device
*
netdev
)
{
struct
peak_usb_device
*
dev
=
netdev_priv
(
netdev
);
struct
peak_tx_urb_context
*
context
=
NULL
;
struct
net_device_stats
*
stats
=
&
netdev
->
stats
;
struct
can_frame
*
cf
=
(
struct
can_frame
*
)
skb
->
data
;
struct
urb
*
urb
;
u8
*
obuf
;
int
i
,
err
;
size_t
size
=
dev
->
adapter
->
tx_buffer_size
;
if
(
can_dropped_invalid_skb
(
netdev
,
skb
))
return
NETDEV_TX_OK
;
for
(
i
=
0
;
i
<
PCAN_USB_MAX_TX_URBS
;
i
++
)
if
(
dev
->
tx_contexts
[
i
].
echo_index
==
PCAN_USB_MAX_TX_URBS
)
{
context
=
dev
->
tx_contexts
+
i
;
break
;
}
if
(
!
context
)
{
/* should not occur except during restart */
return
NETDEV_TX_BUSY
;
}
urb
=
context
->
urb
;
obuf
=
urb
->
transfer_buffer
;
err
=
dev
->
adapter
->
dev_encode_msg
(
dev
,
skb
,
obuf
,
&
size
);
if
(
err
)
{
if
(
net_ratelimit
())
netdev_err
(
netdev
,
"packet dropped
\n
"
);
dev_kfree_skb
(
skb
);
stats
->
tx_dropped
++
;
return
NETDEV_TX_OK
;
}
context
->
echo_index
=
i
;
context
->
dlc
=
cf
->
can_dlc
;
usb_anchor_urb
(
urb
,
&
dev
->
tx_submitted
);
can_put_echo_skb
(
skb
,
netdev
,
context
->
echo_index
);
atomic_inc
(
&
dev
->
active_tx_urbs
);
err
=
usb_submit_urb
(
urb
,
GFP_ATOMIC
);
if
(
err
)
{
can_free_echo_skb
(
netdev
,
context
->
echo_index
);
usb_unanchor_urb
(
urb
);
/* this context is not used in fact */
context
->
echo_index
=
PCAN_USB_MAX_TX_URBS
;
atomic_dec
(
&
dev
->
active_tx_urbs
);
switch
(
err
)
{
case
-
ENODEV
:
netif_device_detach
(
netdev
);
break
;
default:
netdev_warn
(
netdev
,
"tx urb submitting failed err=%d
\n
"
,
err
);
case
-
ENOENT
:
/* cable unplugged */
stats
->
tx_dropped
++
;
}
}
else
{
netdev
->
trans_start
=
jiffies
;
/* slow down tx path */
if
(
atomic_read
(
&
dev
->
active_tx_urbs
)
>=
PCAN_USB_MAX_TX_URBS
)
netif_stop_queue
(
netdev
);
}
return
NETDEV_TX_OK
;
}
/*
* start the CAN interface.
* Rx and Tx urbs are allocated here. Rx urbs are submitted here.
*/
static
int
peak_usb_start
(
struct
peak_usb_device
*
dev
)
{
struct
net_device
*
netdev
=
dev
->
netdev
;
int
err
,
i
;
for
(
i
=
0
;
i
<
PCAN_USB_MAX_RX_URBS
;
i
++
)
{
struct
urb
*
urb
;
u8
*
buf
;
/* create a URB, and a buffer for it, to receive usb messages */
urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
urb
)
{
netdev_err
(
netdev
,
"No memory left for URBs
\n
"
);
err
=
-
ENOMEM
;
break
;
}
buf
=
kmalloc
(
dev
->
adapter
->
rx_buffer_size
,
GFP_KERNEL
);
if
(
!
buf
)
{
netdev_err
(
netdev
,
"No memory left for USB buffer
\n
"
);
usb_free_urb
(
urb
);
err
=
-
ENOMEM
;
break
;
}
usb_fill_bulk_urb
(
urb
,
dev
->
udev
,
usb_rcvbulkpipe
(
dev
->
udev
,
dev
->
ep_msg_in
),
buf
,
dev
->
adapter
->
rx_buffer_size
,
peak_usb_read_bulk_callback
,
dev
);
/* ask last usb_free_urb() to also kfree() transfer_buffer */
urb
->
transfer_flags
|=
URB_FREE_BUFFER
;
usb_anchor_urb
(
urb
,
&
dev
->
rx_submitted
);
err
=
usb_submit_urb
(
urb
,
GFP_KERNEL
);
if
(
err
)
{
if
(
err
==
-
ENODEV
)
netif_device_detach
(
dev
->
netdev
);
usb_unanchor_urb
(
urb
);
kfree
(
buf
);
usb_free_urb
(
urb
);
break
;
}
/* drop reference, USB core will take care of freeing it */
usb_free_urb
(
urb
);
}
/* did we submit any URBs? Warn if we was not able to submit all urbs */
if
(
i
<
PCAN_USB_MAX_RX_URBS
)
{
if
(
i
==
0
)
{
netdev_err
(
netdev
,
"couldn't setup any rx URB
\n
"
);
return
err
;
}
netdev_warn
(
netdev
,
"rx performance may be slow
\n
"
);
}
/* pre-alloc tx buffers and corresponding urbs */
for
(
i
=
0
;
i
<
PCAN_USB_MAX_TX_URBS
;
i
++
)
{
struct
peak_tx_urb_context
*
context
;
struct
urb
*
urb
;
u8
*
buf
;
/* create a URB and a buffer for it, to transmit usb messages */
urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
urb
)
{
netdev_err
(
netdev
,
"No memory left for URBs
\n
"
);
err
=
-
ENOMEM
;
break
;
}
buf
=
kmalloc
(
dev
->
adapter
->
tx_buffer_size
,
GFP_KERNEL
);
if
(
!
buf
)
{
netdev_err
(
netdev
,
"No memory left for USB buffer
\n
"
);
usb_free_urb
(
urb
);
err
=
-
ENOMEM
;
break
;
}
context
=
dev
->
tx_contexts
+
i
;
context
->
dev
=
dev
;
context
->
urb
=
urb
;
usb_fill_bulk_urb
(
urb
,
dev
->
udev
,
usb_sndbulkpipe
(
dev
->
udev
,
dev
->
ep_msg_out
),
buf
,
dev
->
adapter
->
tx_buffer_size
,
peak_usb_write_bulk_callback
,
context
);
/* ask last usb_free_urb() to also kfree() transfer_buffer */
urb
->
transfer_flags
|=
URB_FREE_BUFFER
;
}
/* warn if we were not able to allocate enough tx contexts */
if
(
i
<
PCAN_USB_MAX_TX_URBS
)
{
if
(
i
==
0
)
{
netdev_err
(
netdev
,
"couldn't setup any tx URB
\n
"
);
return
err
;
}
netdev_warn
(
netdev
,
"tx performance may be slow
\n
"
);
}
if
(
dev
->
adapter
->
dev_start
)
{
err
=
dev
->
adapter
->
dev_start
(
dev
);
if
(
err
)
goto
failed
;
}
dev
->
state
|=
PCAN_USB_STATE_STARTED
;
/* can set bus on now */
if
(
dev
->
adapter
->
dev_set_bus
)
{
err
=
dev
->
adapter
->
dev_set_bus
(
dev
,
1
);
if
(
err
)
goto
failed
;
}
dev
->
can
.
state
=
CAN_STATE_ERROR_ACTIVE
;
return
0
;
failed:
if
(
err
==
-
ENODEV
)
netif_device_detach
(
dev
->
netdev
);
netdev_warn
(
netdev
,
"couldn't submit control: %d
\n
"
,
err
);
return
err
;
}
/*
* called by netdev to open the corresponding CAN interface.
*/
static
int
peak_usb_ndo_open
(
struct
net_device
*
netdev
)
{
struct
peak_usb_device
*
dev
=
netdev_priv
(
netdev
);
int
err
;
/* common open */
err
=
open_candev
(
netdev
);
if
(
err
)
return
err
;
/* finally start device */
err
=
peak_usb_start
(
dev
);
if
(
err
)
{
netdev_err
(
netdev
,
"couldn't start device: %d
\n
"
,
err
);
close_candev
(
netdev
);
return
err
;
}
dev
->
open_time
=
jiffies
;
netif_start_queue
(
netdev
);
return
0
;
}
/*
* unlink in-flight Rx and Tx urbs and free their memory.
*/
static
void
peak_usb_unlink_all_urbs
(
struct
peak_usb_device
*
dev
)
{
int
i
;
/* free all Rx (submitted) urbs */
usb_kill_anchored_urbs
(
&
dev
->
rx_submitted
);
/* free unsubmitted Tx urbs first */
for
(
i
=
0
;
i
<
PCAN_USB_MAX_TX_URBS
;
i
++
)
{
struct
urb
*
urb
=
dev
->
tx_contexts
[
i
].
urb
;
if
(
!
urb
||
dev
->
tx_contexts
[
i
].
echo_index
!=
PCAN_USB_MAX_TX_URBS
)
{
/*
* this urb is already released or always submitted,
* let usb core free by itself
*/
continue
;
}
usb_free_urb
(
urb
);
dev
->
tx_contexts
[
i
].
urb
=
NULL
;
}
/* then free all submitted Tx urbs */
usb_kill_anchored_urbs
(
&
dev
->
tx_submitted
);
atomic_set
(
&
dev
->
active_tx_urbs
,
0
);
}
/*
* called by netdev to close the corresponding CAN interface.
*/
static
int
peak_usb_ndo_stop
(
struct
net_device
*
netdev
)
{
struct
peak_usb_device
*
dev
=
netdev_priv
(
netdev
);
dev
->
state
&=
~
PCAN_USB_STATE_STARTED
;
netif_stop_queue
(
netdev
);
/* unlink all pending urbs and free used memory */
peak_usb_unlink_all_urbs
(
dev
);
if
(
dev
->
adapter
->
dev_stop
)
dev
->
adapter
->
dev_stop
(
dev
);
close_candev
(
netdev
);
dev
->
open_time
=
0
;
dev
->
can
.
state
=
CAN_STATE_STOPPED
;
/* can set bus off now */
if
(
dev
->
adapter
->
dev_set_bus
)
{
int
err
=
dev
->
adapter
->
dev_set_bus
(
dev
,
0
);
if
(
err
)
return
err
;
}
return
0
;
}
/*
* handle end of waiting for the device to reset
*/
void
peak_usb_restart_complete
(
struct
peak_usb_device
*
dev
)
{
/* finally MUST update can state */
dev
->
can
.
state
=
CAN_STATE_ERROR_ACTIVE
;
/* netdev queue can be awaken now */
netif_wake_queue
(
dev
->
netdev
);
}
void
peak_usb_async_complete
(
struct
urb
*
urb
)
{
kfree
(
urb
->
transfer_buffer
);
usb_free_urb
(
urb
);
}
/*
* device (auto-)restart mechanism runs in a timer context =>
* MUST handle restart with asynchronous usb transfers
*/
static
int
peak_usb_restart
(
struct
peak_usb_device
*
dev
)
{
struct
urb
*
urb
;
int
err
;
u8
*
buf
;
/*
* if device doesn't define any asynchronous restart handler, simply
* wake the netdev queue up
*/
if
(
!
dev
->
adapter
->
dev_restart_async
)
{
peak_usb_restart_complete
(
dev
);
return
0
;
}
/* first allocate a urb to handle the asynchronous steps */
urb
=
usb_alloc_urb
(
0
,
GFP_ATOMIC
);
if
(
!
urb
)
{
netdev_err
(
dev
->
netdev
,
"no memory left for urb
\n
"
);
return
-
ENOMEM
;
}
/* also allocate enough space for the commands to send */
buf
=
kmalloc
(
PCAN_USB_MAX_CMD_LEN
,
GFP_ATOMIC
);
if
(
!
buf
)
{
netdev_err
(
dev
->
netdev
,
"no memory left for async cmd
\n
"
);
usb_free_urb
(
urb
);
return
-
ENOMEM
;
}
/* call the device specific handler for the restart */
err
=
dev
->
adapter
->
dev_restart_async
(
dev
,
urb
,
buf
);
if
(
!
err
)
return
0
;
kfree
(
buf
);
usb_free_urb
(
urb
);
return
err
;
}
/*
* candev callback used to change CAN mode.
* Warning: this is called from a timer context!
*/
static
int
peak_usb_set_mode
(
struct
net_device
*
netdev
,
enum
can_mode
mode
)
{
struct
peak_usb_device
*
dev
=
netdev_priv
(
netdev
);
int
err
=
0
;
if
(
!
dev
->
open_time
)
return
-
EINVAL
;
switch
(
mode
)
{
case
CAN_MODE_START
:
err
=
peak_usb_restart
(
dev
);
if
(
err
)
netdev_err
(
netdev
,
"couldn't start device (err %d)
\n
"
,
err
);
break
;
default:
return
-
EOPNOTSUPP
;
}
return
err
;
}
/*
* candev callback used to set device bitrate.
*/
static
int
peak_usb_set_bittiming
(
struct
net_device
*
netdev
)
{
struct
peak_usb_device
*
dev
=
netdev_priv
(
netdev
);
struct
can_bittiming
*
bt
=
&
dev
->
can
.
bittiming
;
if
(
dev
->
adapter
->
dev_set_bittiming
)
{
int
err
=
dev
->
adapter
->
dev_set_bittiming
(
dev
,
bt
);
if
(
err
)
netdev_info
(
netdev
,
"couldn't set bitrate (err %d)
\n
"
,
err
);
return
err
;
}
return
0
;
}
static
const
struct
net_device_ops
peak_usb_netdev_ops
=
{
.
ndo_open
=
peak_usb_ndo_open
,
.
ndo_stop
=
peak_usb_ndo_stop
,
.
ndo_start_xmit
=
peak_usb_ndo_start_xmit
,
};
/*
* create one device which is attached to CAN controller #ctrl_idx of the
* usb adapter.
*/
static
int
peak_usb_create_dev
(
struct
peak_usb_adapter
*
peak_usb_adapter
,
struct
usb_interface
*
intf
,
int
ctrl_idx
)
{
struct
usb_device
*
usb_dev
=
interface_to_usbdev
(
intf
);
int
sizeof_candev
=
peak_usb_adapter
->
sizeof_dev_private
;
struct
peak_usb_device
*
dev
;
struct
net_device
*
netdev
;
int
i
,
err
;
u16
tmp16
;
if
(
sizeof_candev
<
sizeof
(
struct
peak_usb_device
))
sizeof_candev
=
sizeof
(
struct
peak_usb_device
);
netdev
=
alloc_candev
(
sizeof_candev
,
PCAN_USB_MAX_TX_URBS
);
if
(
!
netdev
)
{
dev_err
(
&
intf
->
dev
,
"%s: couldn't alloc candev
\n
"
,
PCAN_USB_DRIVER_NAME
);
return
-
ENOMEM
;
}
dev
=
netdev_priv
(
netdev
);
/* allocate a buffer large enough to send commands */
dev
->
cmd_buf
=
kmalloc
(
PCAN_USB_MAX_CMD_LEN
,
GFP_KERNEL
);
if
(
!
dev
->
cmd_buf
)
{
dev_err
(
&
intf
->
dev
,
"%s: couldn't alloc cmd buffer
\n
"
,
PCAN_USB_DRIVER_NAME
);
err
=
-
ENOMEM
;
goto
lbl_set_intf_data
;
}
dev
->
udev
=
usb_dev
;
dev
->
netdev
=
netdev
;
dev
->
adapter
=
peak_usb_adapter
;
dev
->
ctrl_idx
=
ctrl_idx
;
dev
->
state
=
PCAN_USB_STATE_CONNECTED
;
dev
->
ep_msg_in
=
peak_usb_adapter
->
ep_msg_in
;
dev
->
ep_msg_out
=
peak_usb_adapter
->
ep_msg_out
[
ctrl_idx
];
dev
->
can
.
clock
=
peak_usb_adapter
->
clock
;
dev
->
can
.
bittiming_const
=
&
peak_usb_adapter
->
bittiming_const
;
dev
->
can
.
do_set_bittiming
=
peak_usb_set_bittiming
;
dev
->
can
.
do_set_mode
=
peak_usb_set_mode
;
dev
->
can
.
ctrlmode_supported
=
CAN_CTRLMODE_3_SAMPLES
|
CAN_CTRLMODE_LISTENONLY
;
netdev
->
netdev_ops
=
&
peak_usb_netdev_ops
;
netdev
->
flags
|=
IFF_ECHO
;
/* we support local echo */
init_usb_anchor
(
&
dev
->
rx_submitted
);
init_usb_anchor
(
&
dev
->
tx_submitted
);
atomic_set
(
&
dev
->
active_tx_urbs
,
0
);
for
(
i
=
0
;
i
<
PCAN_USB_MAX_TX_URBS
;
i
++
)
dev
->
tx_contexts
[
i
].
echo_index
=
PCAN_USB_MAX_TX_URBS
;
dev
->
prev_siblings
=
usb_get_intfdata
(
intf
);
usb_set_intfdata
(
intf
,
dev
);
SET_NETDEV_DEV
(
netdev
,
&
intf
->
dev
);
err
=
register_candev
(
netdev
);
if
(
err
)
{
dev_err
(
&
intf
->
dev
,
"couldn't register CAN device: %d
\n
"
,
err
);
goto
lbl_free_cmd_buf
;
}
if
(
dev
->
prev_siblings
)
(
dev
->
prev_siblings
)
->
next_siblings
=
dev
;
/* keep hw revision into the netdevice */
tmp16
=
le16_to_cpu
(
usb_dev
->
descriptor
.
bcdDevice
);
dev
->
device_rev
=
tmp16
>>
8
;
if
(
dev
->
adapter
->
dev_init
)
{
err
=
dev
->
adapter
->
dev_init
(
dev
);
if
(
err
)
goto
lbl_free_cmd_buf
;
}
/* set bus off */
if
(
dev
->
adapter
->
dev_set_bus
)
{
err
=
dev
->
adapter
->
dev_set_bus
(
dev
,
0
);
if
(
err
)
goto
lbl_free_cmd_buf
;
}
/* get device number early */
if
(
dev
->
adapter
->
dev_get_device_id
)
dev
->
adapter
->
dev_get_device_id
(
dev
,
&
dev
->
device_number
);
netdev_info
(
netdev
,
"attached to %s channel %u (device %u)
\n
"
,
peak_usb_adapter
->
name
,
ctrl_idx
,
dev
->
device_number
);
return
0
;
lbl_free_cmd_buf:
kfree
(
dev
->
cmd_buf
);
lbl_set_intf_data:
usb_set_intfdata
(
intf
,
dev
->
prev_siblings
);
free_candev
(
netdev
);
return
err
;
}
/*
* called by the usb core when the device is unplugged from the system
*/
static
void
peak_usb_disconnect
(
struct
usb_interface
*
intf
)
{
struct
peak_usb_device
*
dev
;
/* unregister as many netdev devices as siblings */
for
(
dev
=
usb_get_intfdata
(
intf
);
dev
;
dev
=
dev
->
prev_siblings
)
{
struct
net_device
*
netdev
=
dev
->
netdev
;
char
name
[
IFNAMSIZ
];
dev
->
state
&=
~
PCAN_USB_STATE_CONNECTED
;
strncpy
(
name
,
netdev
->
name
,
IFNAMSIZ
);
unregister_netdev
(
netdev
);
free_candev
(
netdev
);
kfree
(
dev
->
cmd_buf
);
dev
->
next_siblings
=
NULL
;
if
(
dev
->
adapter
->
dev_free
)
dev
->
adapter
->
dev_free
(
dev
);
dev_info
(
&
intf
->
dev
,
"%s removed
\n
"
,
name
);
}
usb_set_intfdata
(
intf
,
NULL
);
}
/*
* probe function for new PEAK-System devices
*/
static
int
peak_usb_probe
(
struct
usb_interface
*
intf
,
const
struct
usb_device_id
*
id
)
{
struct
usb_device
*
usb_dev
=
interface_to_usbdev
(
intf
);
struct
peak_usb_adapter
*
peak_usb_adapter
,
**
pp
;
int
i
,
err
=
-
ENOMEM
;
usb_dev
=
interface_to_usbdev
(
intf
);
/* get corresponding PCAN-USB adapter */
for
(
pp
=
peak_usb_adapters_list
;
*
pp
;
pp
++
)
if
((
*
pp
)
->
device_id
==
usb_dev
->
descriptor
.
idProduct
)
break
;
peak_usb_adapter
=
*
pp
;
if
(
!
peak_usb_adapter
)
{
/* should never come except device_id bad usage in this file */
pr_err
(
"%s: didn't find device id. 0x%x in devices list
\n
"
,
PCAN_USB_DRIVER_NAME
,
usb_dev
->
descriptor
.
idProduct
);
return
-
ENODEV
;
}
/* got corresponding adapter: check if it handles current interface */
if
(
peak_usb_adapter
->
intf_probe
)
{
err
=
peak_usb_adapter
->
intf_probe
(
intf
);
if
(
err
)
return
err
;
}
for
(
i
=
0
;
i
<
peak_usb_adapter
->
ctrl_count
;
i
++
)
{
err
=
peak_usb_create_dev
(
peak_usb_adapter
,
intf
,
i
);
if
(
err
)
{
/* deregister already created devices */
peak_usb_disconnect
(
intf
);
break
;
}
}
return
err
;
}
/* usb specific object needed to register this driver with the usb subsystem */
static
struct
usb_driver
peak_usb_driver
=
{
.
name
=
PCAN_USB_DRIVER_NAME
,
.
disconnect
=
peak_usb_disconnect
,
.
probe
=
peak_usb_probe
,
.
id_table
=
peak_usb_table
,
};
static
int
__init
peak_usb_init
(
void
)
{
int
err
;
/* register this driver with the USB subsystem */
err
=
usb_register
(
&
peak_usb_driver
);
if
(
err
)
pr_err
(
"%s: usb_register failed (err %d)
\n
"
,
PCAN_USB_DRIVER_NAME
,
err
);
return
err
;
}
static
int
peak_usb_do_device_exit
(
struct
device
*
d
,
void
*
arg
)
{
struct
usb_interface
*
intf
=
to_usb_interface
(
d
);
struct
peak_usb_device
*
dev
;
/* stop as many netdev devices as siblings */
for
(
dev
=
usb_get_intfdata
(
intf
);
dev
;
dev
=
dev
->
prev_siblings
)
{
struct
net_device
*
netdev
=
dev
->
netdev
;
if
(
netif_device_present
(
netdev
))
if
(
dev
->
adapter
->
dev_exit
)
dev
->
adapter
->
dev_exit
(
dev
);
}
return
0
;
}
static
void
__exit
peak_usb_exit
(
void
)
{
int
err
;
/* last chance do send any synchronous commands here */
err
=
driver_for_each_device
(
&
peak_usb_driver
.
drvwrap
.
driver
,
NULL
,
NULL
,
peak_usb_do_device_exit
);
if
(
err
)
pr_err
(
"%s: failed to stop all can devices (err %d)
\n
"
,
PCAN_USB_DRIVER_NAME
,
err
);
/* deregister this driver with the USB subsystem */
usb_deregister
(
&
peak_usb_driver
);
pr_info
(
"%s: PCAN-USB interfaces driver unloaded
\n
"
,
PCAN_USB_DRIVER_NAME
);
}
module_init
(
peak_usb_init
);
module_exit
(
peak_usb_exit
);
drivers/net/can/usb/peak_usb/pcan_usb_core.h
0 → 100644
View file @
ffcb9738
/*
* CAN driver for PEAK System USB adapters
* Derived from the PCAN project file driver/src/pcan_usb_core.c
*
* Copyright (C) 2003-2010 PEAK System-Technik GmbH
* Copyright (C) 2010-2012 Stephane Grosjean <s.grosjean@peak-system.com>
*
* Many thanks to Klaus Hitschler <klaus.hitschler@gmx.de>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published
* by the Free Software Foundation; version 2 of the License.
*
* 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.
*/
#ifndef PCAN_USB_CORE_H
#define PCAN_USB_CORE_H
/* PEAK-System vendor id. */
#define PCAN_USB_VENDOR_ID 0x0c72
/* supported device ids. */
#define PCAN_USB_PRODUCT_ID 0x000c
#define PCAN_USBPRO_PRODUCT_ID 0x000d
#define PCAN_USB_DRIVER_NAME "peak_usb"
/* number of urbs that are submitted for rx/tx per channel */
#define PCAN_USB_MAX_RX_URBS 4
#define PCAN_USB_MAX_TX_URBS 10
/* usb adapters maximum channels per usb interface */
#define PCAN_USB_MAX_CHANNEL 2
/* maximum length of the usb commands sent to/received from the devices */
#define PCAN_USB_MAX_CMD_LEN 32
struct
peak_usb_device
;
/* PEAK-System USB adapter descriptor */
struct
peak_usb_adapter
{
char
*
name
;
u32
device_id
;
struct
can_clock
clock
;
struct
can_bittiming_const
bittiming_const
;
unsigned
int
ctrl_count
;
int
(
*
intf_probe
)(
struct
usb_interface
*
intf
);
int
(
*
dev_init
)(
struct
peak_usb_device
*
dev
);
void
(
*
dev_exit
)(
struct
peak_usb_device
*
dev
);
void
(
*
dev_free
)(
struct
peak_usb_device
*
dev
);
int
(
*
dev_open
)(
struct
peak_usb_device
*
dev
);
int
(
*
dev_close
)(
struct
peak_usb_device
*
dev
);
int
(
*
dev_set_bittiming
)(
struct
peak_usb_device
*
dev
,
struct
can_bittiming
*
bt
);
int
(
*
dev_set_bus
)(
struct
peak_usb_device
*
dev
,
u8
onoff
);
int
(
*
dev_get_device_id
)(
struct
peak_usb_device
*
dev
,
u32
*
device_id
);
int
(
*
dev_decode_buf
)(
struct
peak_usb_device
*
dev
,
struct
urb
*
urb
);
int
(
*
dev_encode_msg
)(
struct
peak_usb_device
*
dev
,
struct
sk_buff
*
skb
,
u8
*
obuf
,
size_t
*
size
);
int
(
*
dev_start
)(
struct
peak_usb_device
*
dev
);
int
(
*
dev_stop
)(
struct
peak_usb_device
*
dev
);
int
(
*
dev_restart_async
)(
struct
peak_usb_device
*
dev
,
struct
urb
*
urb
,
u8
*
buf
);
u8
ep_msg_in
;
u8
ep_msg_out
[
PCAN_USB_MAX_CHANNEL
];
u8
ts_used_bits
;
u32
ts_period
;
u8
us_per_ts_shift
;
u32
us_per_ts_scale
;
int
rx_buffer_size
;
int
tx_buffer_size
;
int
sizeof_dev_private
;
};
extern
struct
peak_usb_adapter
pcan_usb
;
extern
struct
peak_usb_adapter
pcan_usb_pro
;
struct
peak_time_ref
{
struct
timeval
tv_host_0
,
tv_host
;
u32
ts_dev_1
,
ts_dev_2
;
u64
ts_total
;
u32
tick_count
;
struct
peak_usb_adapter
*
adapter
;
};
struct
peak_tx_urb_context
{
struct
peak_usb_device
*
dev
;
u32
echo_index
;
u8
dlc
;
struct
urb
*
urb
;
};
#define PCAN_USB_STATE_CONNECTED 0x00000001
#define PCAN_USB_STATE_STARTED 0x00000002
/* PEAK-System USB device */
struct
peak_usb_device
{
struct
can_priv
can
;
struct
peak_usb_adapter
*
adapter
;
unsigned
int
ctrl_idx
;
int
open_time
;
u32
state
;
struct
sk_buff
*
echo_skb
[
PCAN_USB_MAX_TX_URBS
];
struct
usb_device
*
udev
;
struct
net_device
*
netdev
;
atomic_t
active_tx_urbs
;
struct
usb_anchor
tx_submitted
;
struct
peak_tx_urb_context
tx_contexts
[
PCAN_USB_MAX_TX_URBS
];
u8
*
cmd_buf
;
struct
usb_anchor
rx_submitted
;
u32
device_number
;
u8
device_rev
;
u8
ep_msg_in
;
u8
ep_msg_out
;
u16
bus_load
;
struct
peak_usb_device
*
prev_siblings
;
struct
peak_usb_device
*
next_siblings
;
};
void
dump_mem
(
char
*
prompt
,
void
*
p
,
int
l
);
/* common timestamp management */
void
peak_usb_init_time_ref
(
struct
peak_time_ref
*
time_ref
,
struct
peak_usb_adapter
*
adapter
);
void
peak_usb_update_ts_now
(
struct
peak_time_ref
*
time_ref
,
u32
ts_now
);
void
peak_usb_set_ts_now
(
struct
peak_time_ref
*
time_ref
,
u32
ts_now
);
void
peak_usb_get_ts_tv
(
struct
peak_time_ref
*
time_ref
,
u32
ts
,
struct
timeval
*
tv
);
void
peak_usb_async_complete
(
struct
urb
*
urb
);
void
peak_usb_restart_complete
(
struct
peak_usb_device
*
dev
);
#endif
drivers/net/can/usb/peak_usb/pcan_usb_pro.c
0 → 100644
View file @
ffcb9738
/*
* CAN driver for PEAK System PCAN-USB Pro adapter
* Derived from the PCAN project file driver/src/pcan_usbpro.c
*
* Copyright (C) 2003-2011 PEAK System-Technik GmbH
* Copyright (C) 2011-2012 Stephane Grosjean <s.grosjean@peak-system.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published
* by the Free Software Foundation; version 2 of the License.
*
* 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.
*/
#include <linux/netdevice.h>
#include <linux/usb.h>
#include <linux/module.h>
#include <linux/can.h>
#include <linux/can/dev.h>
#include <linux/can/error.h>
#include "pcan_usb_core.h"
#include "pcan_usb_pro.h"
MODULE_SUPPORTED_DEVICE
(
"PEAK-System PCAN-USB Pro adapter"
);
/* PCAN-USB Pro Endpoints */
#define PCAN_USBPRO_EP_CMDOUT 1
#define PCAN_USBPRO_EP_CMDIN (PCAN_USBPRO_EP_CMDOUT | USB_DIR_IN)
#define PCAN_USBPRO_EP_MSGOUT_0 2
#define PCAN_USBPRO_EP_MSGIN (PCAN_USBPRO_EP_MSGOUT_0 | USB_DIR_IN)
#define PCAN_USBPRO_EP_MSGOUT_1 3
#define PCAN_USBPRO_EP_UNUSED (PCAN_USBPRO_EP_MSGOUT_1 | USB_DIR_IN)
#define PCAN_USBPRO_CHANNEL_COUNT 2
/* PCAN-USB Pro adapter internal clock (MHz) */
#define PCAN_USBPRO_CRYSTAL_HZ 56000000
/* PCAN-USB Pro command timeout (ms.) */
#define PCAN_USBPRO_COMMAND_TIMEOUT 1000
/* PCAN-USB Pro rx/tx buffers size */
#define PCAN_USBPRO_RX_BUFFER_SIZE 1024
#define PCAN_USBPRO_TX_BUFFER_SIZE 64
#define PCAN_USBPRO_MSG_HEADER_LEN 4
/* some commands responses need to be re-submitted */
#define PCAN_USBPRO_RSP_SUBMIT_MAX 2
#define PCAN_USBPRO_RTR 0x01
#define PCAN_USBPRO_EXT 0x02
#define PCAN_USBPRO_CMD_BUFFER_SIZE 512
/* handle device specific info used by the netdevices */
struct
pcan_usb_pro_interface
{
struct
peak_usb_device
*
dev
[
PCAN_USBPRO_CHANNEL_COUNT
];
struct
peak_time_ref
time_ref
;
int
cm_ignore_count
;
int
dev_opened_count
;
};
/* device information */
struct
pcan_usb_pro_device
{
struct
peak_usb_device
dev
;
struct
pcan_usb_pro_interface
*
usb_if
;
u32
cached_ccbt
;
};
/* internal structure used to handle messages sent to bulk urb */
struct
pcan_usb_pro_msg
{
u8
*
rec_ptr
;
int
rec_buffer_size
;
int
rec_buffer_len
;
union
{
u16
*
rec_cnt_rd
;
u32
*
rec_cnt
;
u8
*
rec_buffer
;
}
u
;
};
/* records sizes table indexed on message id. (8-bits value) */
static
u16
pcan_usb_pro_sizeof_rec
[
256
]
=
{
[
PCAN_USBPRO_SETBTR
]
=
sizeof
(
struct
pcan_usb_pro_btr
),
[
PCAN_USBPRO_SETBUSACT
]
=
sizeof
(
struct
pcan_usb_pro_busact
),
[
PCAN_USBPRO_SETSILENT
]
=
sizeof
(
struct
pcan_usb_pro_silent
),
[
PCAN_USBPRO_SETFILTR
]
=
sizeof
(
struct
pcan_usb_pro_filter
),
[
PCAN_USBPRO_SETTS
]
=
sizeof
(
struct
pcan_usb_pro_setts
),
[
PCAN_USBPRO_GETDEVID
]
=
sizeof
(
struct
pcan_usb_pro_devid
),
[
PCAN_USBPRO_SETLED
]
=
sizeof
(
struct
pcan_usb_pro_setled
),
[
PCAN_USBPRO_RXMSG8
]
=
sizeof
(
struct
pcan_usb_pro_rxmsg
),
[
PCAN_USBPRO_RXMSG4
]
=
sizeof
(
struct
pcan_usb_pro_rxmsg
)
-
4
,
[
PCAN_USBPRO_RXMSG0
]
=
sizeof
(
struct
pcan_usb_pro_rxmsg
)
-
8
,
[
PCAN_USBPRO_RXRTR
]
=
sizeof
(
struct
pcan_usb_pro_rxmsg
)
-
8
,
[
PCAN_USBPRO_RXSTATUS
]
=
sizeof
(
struct
pcan_usb_pro_rxstatus
),
[
PCAN_USBPRO_RXTS
]
=
sizeof
(
struct
pcan_usb_pro_rxts
),
[
PCAN_USBPRO_TXMSG8
]
=
sizeof
(
struct
pcan_usb_pro_txmsg
),
[
PCAN_USBPRO_TXMSG4
]
=
sizeof
(
struct
pcan_usb_pro_txmsg
)
-
4
,
[
PCAN_USBPRO_TXMSG0
]
=
sizeof
(
struct
pcan_usb_pro_txmsg
)
-
8
,
};
/*
* initialize PCAN-USB Pro message data structure
*/
static
u8
*
pcan_msg_init
(
struct
pcan_usb_pro_msg
*
pm
,
void
*
buffer_addr
,
int
buffer_size
)
{
if
(
buffer_size
<
PCAN_USBPRO_MSG_HEADER_LEN
)
return
NULL
;
pm
->
u
.
rec_buffer
=
(
u8
*
)
buffer_addr
;
pm
->
rec_buffer_size
=
pm
->
rec_buffer_len
=
buffer_size
;
pm
->
rec_ptr
=
pm
->
u
.
rec_buffer
+
PCAN_USBPRO_MSG_HEADER_LEN
;
return
pm
->
rec_ptr
;
}
static
u8
*
pcan_msg_init_empty
(
struct
pcan_usb_pro_msg
*
pm
,
void
*
buffer_addr
,
int
buffer_size
)
{
u8
*
pr
=
pcan_msg_init
(
pm
,
buffer_addr
,
buffer_size
);
if
(
pr
)
{
pm
->
rec_buffer_len
=
PCAN_USBPRO_MSG_HEADER_LEN
;
*
pm
->
u
.
rec_cnt
=
0
;
}
return
pr
;
}
/*
* add one record to a message being built
*/
static
int
pcan_msg_add_rec
(
struct
pcan_usb_pro_msg
*
pm
,
u8
id
,
...)
{
int
len
,
i
;
u8
*
pc
;
va_list
ap
;
va_start
(
ap
,
id
);
pc
=
pm
->
rec_ptr
+
1
;
i
=
0
;
switch
(
id
)
{
case
PCAN_USBPRO_TXMSG8
:
i
+=
4
;
case
PCAN_USBPRO_TXMSG4
:
i
+=
4
;
case
PCAN_USBPRO_TXMSG0
:
*
pc
++
=
va_arg
(
ap
,
int
);
*
pc
++
=
va_arg
(
ap
,
int
);
*
pc
++
=
va_arg
(
ap
,
int
);
*
(
u32
*
)
pc
=
cpu_to_le32
(
va_arg
(
ap
,
u32
));
pc
+=
4
;
memcpy
(
pc
,
va_arg
(
ap
,
int
*
),
i
);
pc
+=
i
;
break
;
case
PCAN_USBPRO_SETBTR
:
case
PCAN_USBPRO_GETDEVID
:
*
pc
++
=
va_arg
(
ap
,
int
);
pc
+=
2
;
*
(
u32
*
)
pc
=
cpu_to_le32
(
va_arg
(
ap
,
u32
));
pc
+=
4
;
break
;
case
PCAN_USBPRO_SETFILTR
:
case
PCAN_USBPRO_SETBUSACT
:
case
PCAN_USBPRO_SETSILENT
:
*
pc
++
=
va_arg
(
ap
,
int
);
*
(
u16
*
)
pc
=
cpu_to_le16
(
va_arg
(
ap
,
int
));
pc
+=
2
;
break
;
case
PCAN_USBPRO_SETLED
:
*
pc
++
=
va_arg
(
ap
,
int
);
*
(
u16
*
)
pc
=
cpu_to_le16
(
va_arg
(
ap
,
int
));
pc
+=
2
;
*
(
u32
*
)
pc
=
cpu_to_le32
(
va_arg
(
ap
,
u32
));
pc
+=
4
;
break
;
case
PCAN_USBPRO_SETTS
:
pc
++
;
*
(
u16
*
)
pc
=
cpu_to_le16
(
va_arg
(
ap
,
int
));
pc
+=
2
;
break
;
default:
pr_err
(
"%s: %s(): unknown data type %02Xh (%d)
\n
"
,
PCAN_USB_DRIVER_NAME
,
__func__
,
id
,
id
);
pc
--
;
break
;
}
len
=
pc
-
pm
->
rec_ptr
;
if
(
len
>
0
)
{
*
pm
->
u
.
rec_cnt
=
cpu_to_le32
(
*
pm
->
u
.
rec_cnt
+
1
);
*
pm
->
rec_ptr
=
id
;
pm
->
rec_ptr
=
pc
;
pm
->
rec_buffer_len
+=
len
;
}
va_end
(
ap
);
return
len
;
}
/*
* send PCAN-USB Pro command synchronously
*/
static
int
pcan_usb_pro_send_cmd
(
struct
peak_usb_device
*
dev
,
struct
pcan_usb_pro_msg
*
pum
)
{
int
actual_length
;
int
err
;
/* usb device unregistered? */
if
(
!
(
dev
->
state
&
PCAN_USB_STATE_CONNECTED
))
return
0
;
err
=
usb_bulk_msg
(
dev
->
udev
,
usb_sndbulkpipe
(
dev
->
udev
,
PCAN_USBPRO_EP_CMDOUT
),
pum
->
u
.
rec_buffer
,
pum
->
rec_buffer_len
,
&
actual_length
,
PCAN_USBPRO_COMMAND_TIMEOUT
);
if
(
err
)
netdev_err
(
dev
->
netdev
,
"sending command failure: %d
\n
"
,
err
);
return
err
;
}
/*
* wait for PCAN-USB Pro command response
*/
static
int
pcan_usb_pro_wait_rsp
(
struct
peak_usb_device
*
dev
,
struct
pcan_usb_pro_msg
*
pum
)
{
u8
req_data_type
,
req_channel
;
int
actual_length
;
int
i
,
err
=
0
;
/* usb device unregistered? */
if
(
!
(
dev
->
state
&
PCAN_USB_STATE_CONNECTED
))
return
0
;
req_data_type
=
pum
->
u
.
rec_buffer
[
4
];
req_channel
=
pum
->
u
.
rec_buffer
[
5
];
*
pum
->
u
.
rec_cnt
=
0
;
for
(
i
=
0
;
!
err
&&
i
<
PCAN_USBPRO_RSP_SUBMIT_MAX
;
i
++
)
{
struct
pcan_usb_pro_msg
rsp
;
union
pcan_usb_pro_rec
*
pr
;
u32
r
,
rec_cnt
;
u16
rec_len
;
u8
*
pc
;
err
=
usb_bulk_msg
(
dev
->
udev
,
usb_rcvbulkpipe
(
dev
->
udev
,
PCAN_USBPRO_EP_CMDIN
),
pum
->
u
.
rec_buffer
,
pum
->
rec_buffer_len
,
&
actual_length
,
PCAN_USBPRO_COMMAND_TIMEOUT
);
if
(
err
)
{
netdev_err
(
dev
->
netdev
,
"waiting rsp error %d
\n
"
,
err
);
break
;
}
if
(
actual_length
==
0
)
continue
;
err
=
-
EBADMSG
;
if
(
actual_length
<
PCAN_USBPRO_MSG_HEADER_LEN
)
{
netdev_err
(
dev
->
netdev
,
"got abnormal too small rsp (len=%d)
\n
"
,
actual_length
);
break
;
}
pc
=
pcan_msg_init
(
&
rsp
,
pum
->
u
.
rec_buffer
,
actual_length
);
rec_cnt
=
le32_to_cpu
(
*
rsp
.
u
.
rec_cnt
);
/* loop on records stored into message */
for
(
r
=
0
;
r
<
rec_cnt
;
r
++
)
{
pr
=
(
union
pcan_usb_pro_rec
*
)
pc
;
rec_len
=
pcan_usb_pro_sizeof_rec
[
pr
->
data_type
];
if
(
!
rec_len
)
{
netdev_err
(
dev
->
netdev
,
"got unprocessed record in msg
\n
"
);
dump_mem
(
"rcvd rsp msg"
,
pum
->
u
.
rec_buffer
,
actual_length
);
break
;
}
/* check if response corresponds to request */
if
(
pr
->
data_type
!=
req_data_type
)
netdev_err
(
dev
->
netdev
,
"got unwanted rsp %xh: ignored
\n
"
,
pr
->
data_type
);
/* check if channel in response corresponds too */
else
if
((
req_channel
!=
0xff
)
&&
\
(
pr
->
bus_act
.
channel
!=
req_channel
))
netdev_err
(
dev
->
netdev
,
"got rsp %xh but on chan%u: ignored
\n
"
,
req_data_type
,
pr
->
bus_act
.
channel
);
/* got the response */
else
return
0
;
/* otherwise, go on with next record in message */
pc
+=
rec_len
;
}
}
return
(
i
>=
PCAN_USBPRO_RSP_SUBMIT_MAX
)
?
-
ERANGE
:
err
;
}
static
int
pcan_usb_pro_send_req
(
struct
peak_usb_device
*
dev
,
int
req_id
,
int
req_value
,
void
*
req_addr
,
int
req_size
)
{
int
err
;
u8
req_type
;
unsigned
int
p
;
/* usb device unregistered? */
if
(
!
(
dev
->
state
&
PCAN_USB_STATE_CONNECTED
))
return
0
;
memset
(
req_addr
,
'\0'
,
req_size
);
req_type
=
USB_TYPE_VENDOR
|
USB_RECIP_OTHER
;
switch
(
req_id
)
{
case
PCAN_USBPRO_REQ_FCT
:
p
=
usb_sndctrlpipe
(
dev
->
udev
,
0
);
break
;
default:
p
=
usb_rcvctrlpipe
(
dev
->
udev
,
0
);
req_type
|=
USB_DIR_IN
;
break
;
}
err
=
usb_control_msg
(
dev
->
udev
,
p
,
req_id
,
req_type
,
req_value
,
0
,
req_addr
,
req_size
,
2
*
USB_CTRL_GET_TIMEOUT
);
if
(
err
<
0
)
{
netdev_info
(
dev
->
netdev
,
"unable to request usb[type=%d value=%d] err=%d
\n
"
,
req_id
,
req_value
,
err
);
return
err
;
}
return
0
;
}
static
int
pcan_usb_pro_set_ts
(
struct
peak_usb_device
*
dev
,
u16
onoff
)
{
struct
pcan_usb_pro_msg
um
;
pcan_msg_init_empty
(
&
um
,
dev
->
cmd_buf
,
PCAN_USB_MAX_CMD_LEN
);
pcan_msg_add_rec
(
&
um
,
PCAN_USBPRO_SETTS
,
onoff
);
return
pcan_usb_pro_send_cmd
(
dev
,
&
um
);
}
static
int
pcan_usb_pro_set_bitrate
(
struct
peak_usb_device
*
dev
,
u32
ccbt
)
{
struct
pcan_usb_pro_device
*
pdev
=
container_of
(
dev
,
struct
pcan_usb_pro_device
,
dev
);
struct
pcan_usb_pro_msg
um
;
pcan_msg_init_empty
(
&
um
,
dev
->
cmd_buf
,
PCAN_USB_MAX_CMD_LEN
);
pcan_msg_add_rec
(
&
um
,
PCAN_USBPRO_SETBTR
,
dev
->
ctrl_idx
,
ccbt
);
/* cache the CCBT value to reuse it before next buson */
pdev
->
cached_ccbt
=
ccbt
;
return
pcan_usb_pro_send_cmd
(
dev
,
&
um
);
}
static
int
pcan_usb_pro_set_bus
(
struct
peak_usb_device
*
dev
,
u8
onoff
)
{
struct
pcan_usb_pro_msg
um
;
/* if bus=on, be sure the bitrate being set before! */
if
(
onoff
)
{
struct
pcan_usb_pro_device
*
pdev
=
container_of
(
dev
,
struct
pcan_usb_pro_device
,
dev
);
pcan_usb_pro_set_bitrate
(
dev
,
pdev
->
cached_ccbt
);
}
pcan_msg_init_empty
(
&
um
,
dev
->
cmd_buf
,
PCAN_USB_MAX_CMD_LEN
);
pcan_msg_add_rec
(
&
um
,
PCAN_USBPRO_SETBUSACT
,
dev
->
ctrl_idx
,
onoff
);
return
pcan_usb_pro_send_cmd
(
dev
,
&
um
);
}
static
int
pcan_usb_pro_set_silent
(
struct
peak_usb_device
*
dev
,
u8
onoff
)
{
struct
pcan_usb_pro_msg
um
;
pcan_msg_init_empty
(
&
um
,
dev
->
cmd_buf
,
PCAN_USB_MAX_CMD_LEN
);
pcan_msg_add_rec
(
&
um
,
PCAN_USBPRO_SETSILENT
,
dev
->
ctrl_idx
,
onoff
);
return
pcan_usb_pro_send_cmd
(
dev
,
&
um
);
}
static
int
pcan_usb_pro_set_filter
(
struct
peak_usb_device
*
dev
,
u16
filter_mode
)
{
struct
pcan_usb_pro_msg
um
;
pcan_msg_init_empty
(
&
um
,
dev
->
cmd_buf
,
PCAN_USB_MAX_CMD_LEN
);
pcan_msg_add_rec
(
&
um
,
PCAN_USBPRO_SETFILTR
,
dev
->
ctrl_idx
,
filter_mode
);
return
pcan_usb_pro_send_cmd
(
dev
,
&
um
);
}
static
int
pcan_usb_pro_set_led
(
struct
peak_usb_device
*
dev
,
u8
mode
,
u32
timeout
)
{
struct
pcan_usb_pro_msg
um
;
pcan_msg_init_empty
(
&
um
,
dev
->
cmd_buf
,
PCAN_USB_MAX_CMD_LEN
);
pcan_msg_add_rec
(
&
um
,
PCAN_USBPRO_SETLED
,
dev
->
ctrl_idx
,
mode
,
timeout
);
return
pcan_usb_pro_send_cmd
(
dev
,
&
um
);
}
static
int
pcan_usb_pro_get_device_id
(
struct
peak_usb_device
*
dev
,
u32
*
device_id
)
{
struct
pcan_usb_pro_devid
*
pdn
;
struct
pcan_usb_pro_msg
um
;
int
err
;
u8
*
pc
;
pc
=
pcan_msg_init_empty
(
&
um
,
dev
->
cmd_buf
,
PCAN_USB_MAX_CMD_LEN
);
pcan_msg_add_rec
(
&
um
,
PCAN_USBPRO_GETDEVID
,
dev
->
ctrl_idx
);
err
=
pcan_usb_pro_send_cmd
(
dev
,
&
um
);
if
(
err
)
return
err
;
err
=
pcan_usb_pro_wait_rsp
(
dev
,
&
um
);
if
(
err
)
return
err
;
pdn
=
(
struct
pcan_usb_pro_devid
*
)
pc
;
if
(
device_id
)
*
device_id
=
le32_to_cpu
(
pdn
->
serial_num
);
return
err
;
}
static
int
pcan_usb_pro_set_bittiming
(
struct
peak_usb_device
*
dev
,
struct
can_bittiming
*
bt
)
{
u32
ccbt
;
ccbt
=
(
dev
->
can
.
ctrlmode
&
CAN_CTRLMODE_3_SAMPLES
)
?
0x00800000
:
0
;
ccbt
|=
(
bt
->
sjw
-
1
)
<<
24
;
ccbt
|=
(
bt
->
phase_seg2
-
1
)
<<
20
;
ccbt
|=
(
bt
->
prop_seg
+
bt
->
phase_seg1
-
1
)
<<
16
;
/* = tseg1 */
ccbt
|=
bt
->
brp
-
1
;
netdev_info
(
dev
->
netdev
,
"setting ccbt=0x%08x
\n
"
,
ccbt
);
return
pcan_usb_pro_set_bitrate
(
dev
,
ccbt
);
}
static
void
pcan_usb_pro_restart_complete
(
struct
urb
*
urb
)
{
/* can delete usb resources */
peak_usb_async_complete
(
urb
);
/* notify candev and netdev */
peak_usb_restart_complete
(
urb
->
context
);
}
/*
* handle restart but in asynchronously way
*/
static
int
pcan_usb_pro_restart_async
(
struct
peak_usb_device
*
dev
,
struct
urb
*
urb
,
u8
*
buf
)
{
struct
pcan_usb_pro_msg
um
;
pcan_msg_init_empty
(
&
um
,
buf
,
PCAN_USB_MAX_CMD_LEN
);
pcan_msg_add_rec
(
&
um
,
PCAN_USBPRO_SETBUSACT
,
dev
->
ctrl_idx
,
1
);
usb_fill_bulk_urb
(
urb
,
dev
->
udev
,
usb_sndbulkpipe
(
dev
->
udev
,
PCAN_USBPRO_EP_CMDOUT
),
buf
,
PCAN_USB_MAX_CMD_LEN
,
pcan_usb_pro_restart_complete
,
dev
);
return
usb_submit_urb
(
urb
,
GFP_ATOMIC
);
}
static
void
pcan_usb_pro_drv_loaded
(
struct
peak_usb_device
*
dev
,
int
loaded
)
{
u8
buffer
[
16
];
buffer
[
0
]
=
0
;
buffer
[
1
]
=
!!
loaded
;
pcan_usb_pro_send_req
(
dev
,
PCAN_USBPRO_REQ_FCT
,
PCAN_USBPRO_FCT_DRVLD
,
buffer
,
sizeof
(
buffer
));
}
static
inline
struct
pcan_usb_pro_interface
*
pcan_usb_pro_dev_if
(
struct
peak_usb_device
*
dev
)
{
struct
pcan_usb_pro_device
*
pdev
=
container_of
(
dev
,
struct
pcan_usb_pro_device
,
dev
);
return
pdev
->
usb_if
;
}
static
int
pcan_usb_pro_handle_canmsg
(
struct
pcan_usb_pro_interface
*
usb_if
,
struct
pcan_usb_pro_rxmsg
*
rx
)
{
const
unsigned
int
ctrl_idx
=
(
rx
->
len
>>
4
)
&
0x0f
;
struct
peak_usb_device
*
dev
=
usb_if
->
dev
[
ctrl_idx
];
struct
net_device
*
netdev
=
dev
->
netdev
;
struct
can_frame
*
can_frame
;
struct
sk_buff
*
skb
;
struct
timeval
tv
;
skb
=
alloc_can_skb
(
netdev
,
&
can_frame
);
if
(
!
skb
)
return
-
ENOMEM
;
can_frame
->
can_id
=
le32_to_cpu
(
rx
->
id
);
can_frame
->
can_dlc
=
rx
->
len
&
0x0f
;
if
(
rx
->
flags
&
PCAN_USBPRO_EXT
)
can_frame
->
can_id
|=
CAN_EFF_FLAG
;
if
(
rx
->
flags
&
PCAN_USBPRO_RTR
)
can_frame
->
can_id
|=
CAN_RTR_FLAG
;
else
memcpy
(
can_frame
->
data
,
rx
->
data
,
can_frame
->
can_dlc
);
peak_usb_get_ts_tv
(
&
usb_if
->
time_ref
,
le32_to_cpu
(
rx
->
ts32
),
&
tv
);
skb
->
tstamp
=
timeval_to_ktime
(
tv
);
netif_rx
(
skb
);
netdev
->
stats
.
rx_packets
++
;
netdev
->
stats
.
rx_bytes
+=
can_frame
->
can_dlc
;
return
0
;
}
static
int
pcan_usb_pro_handle_error
(
struct
pcan_usb_pro_interface
*
usb_if
,
struct
pcan_usb_pro_rxstatus
*
er
)
{
const
u32
raw_status
=
le32_to_cpu
(
er
->
status
);
const
unsigned
int
ctrl_idx
=
(
er
->
channel
>>
4
)
&
0x0f
;
struct
peak_usb_device
*
dev
=
usb_if
->
dev
[
ctrl_idx
];
struct
net_device
*
netdev
=
dev
->
netdev
;
struct
can_frame
*
can_frame
;
enum
can_state
new_state
=
CAN_STATE_ERROR_ACTIVE
;
u8
err_mask
=
0
;
struct
sk_buff
*
skb
;
struct
timeval
tv
;
/* nothing should be sent while in BUS_OFF state */
if
(
dev
->
can
.
state
==
CAN_STATE_BUS_OFF
)
return
0
;
if
(
!
raw_status
)
{
/* no error bit (back to active state) */
dev
->
can
.
state
=
CAN_STATE_ERROR_ACTIVE
;
return
0
;
}
if
(
raw_status
&
(
PCAN_USBPRO_STATUS_OVERRUN
|
PCAN_USBPRO_STATUS_QOVERRUN
))
{
/* trick to bypass next comparison and process other errors */
new_state
=
CAN_STATE_MAX
;
}
if
(
raw_status
&
PCAN_USBPRO_STATUS_BUS
)
{
new_state
=
CAN_STATE_BUS_OFF
;
}
else
if
(
raw_status
&
PCAN_USBPRO_STATUS_ERROR
)
{
u32
rx_err_cnt
=
(
le32_to_cpu
(
er
->
err_frm
)
&
0x00ff0000
)
>>
16
;
u32
tx_err_cnt
=
(
le32_to_cpu
(
er
->
err_frm
)
&
0xff000000
)
>>
24
;
if
(
rx_err_cnt
>
127
)
err_mask
|=
CAN_ERR_CRTL_RX_PASSIVE
;
else
if
(
rx_err_cnt
>
96
)
err_mask
|=
CAN_ERR_CRTL_RX_WARNING
;
if
(
tx_err_cnt
>
127
)
err_mask
|=
CAN_ERR_CRTL_TX_PASSIVE
;
else
if
(
tx_err_cnt
>
96
)
err_mask
|=
CAN_ERR_CRTL_TX_WARNING
;
if
(
err_mask
&
(
CAN_ERR_CRTL_RX_WARNING
|
CAN_ERR_CRTL_TX_WARNING
))
new_state
=
CAN_STATE_ERROR_WARNING
;
else
if
(
err_mask
&
(
CAN_ERR_CRTL_RX_PASSIVE
|
CAN_ERR_CRTL_TX_PASSIVE
))
new_state
=
CAN_STATE_ERROR_PASSIVE
;
}
/* donot post any error if current state didn't change */
if
(
dev
->
can
.
state
==
new_state
)
return
0
;
/* allocate an skb to store the error frame */
skb
=
alloc_can_err_skb
(
netdev
,
&
can_frame
);
if
(
!
skb
)
return
-
ENOMEM
;
switch
(
new_state
)
{
case
CAN_STATE_BUS_OFF
:
can_frame
->
can_id
|=
CAN_ERR_BUSOFF
;
can_bus_off
(
netdev
);
break
;
case
CAN_STATE_ERROR_PASSIVE
:
can_frame
->
can_id
|=
CAN_ERR_CRTL
;
can_frame
->
data
[
1
]
|=
err_mask
;
dev
->
can
.
can_stats
.
error_passive
++
;
break
;
case
CAN_STATE_ERROR_WARNING
:
can_frame
->
can_id
|=
CAN_ERR_CRTL
;
can_frame
->
data
[
1
]
|=
err_mask
;
dev
->
can
.
can_stats
.
error_warning
++
;
break
;
case
CAN_STATE_ERROR_ACTIVE
:
break
;
default:
/* CAN_STATE_MAX (trick to handle other errors) */
if
(
raw_status
&
PCAN_USBPRO_STATUS_OVERRUN
)
{
can_frame
->
can_id
|=
CAN_ERR_PROT
;
can_frame
->
data
[
2
]
|=
CAN_ERR_PROT_OVERLOAD
;
netdev
->
stats
.
rx_over_errors
++
;
netdev
->
stats
.
rx_errors
++
;
}
if
(
raw_status
&
PCAN_USBPRO_STATUS_QOVERRUN
)
{
can_frame
->
can_id
|=
CAN_ERR_CRTL
;
can_frame
->
data
[
1
]
|=
CAN_ERR_CRTL_RX_OVERFLOW
;
netdev
->
stats
.
rx_over_errors
++
;
netdev
->
stats
.
rx_errors
++
;
}
new_state
=
CAN_STATE_ERROR_ACTIVE
;
break
;
}
dev
->
can
.
state
=
new_state
;
peak_usb_get_ts_tv
(
&
usb_if
->
time_ref
,
le32_to_cpu
(
er
->
ts32
),
&
tv
);
skb
->
tstamp
=
timeval_to_ktime
(
tv
);
netif_rx
(
skb
);
netdev
->
stats
.
rx_packets
++
;
netdev
->
stats
.
rx_bytes
+=
can_frame
->
can_dlc
;
return
0
;
}
static
void
pcan_usb_pro_handle_ts
(
struct
pcan_usb_pro_interface
*
usb_if
,
struct
pcan_usb_pro_rxts
*
ts
)
{
/* should wait until clock is stabilized */
if
(
usb_if
->
cm_ignore_count
>
0
)
usb_if
->
cm_ignore_count
--
;
else
peak_usb_set_ts_now
(
&
usb_if
->
time_ref
,
le32_to_cpu
(
ts
->
ts64
[
1
]));
}
/*
* callback for bulk IN urb
*/
static
int
pcan_usb_pro_decode_buf
(
struct
peak_usb_device
*
dev
,
struct
urb
*
urb
)
{
struct
pcan_usb_pro_interface
*
usb_if
=
pcan_usb_pro_dev_if
(
dev
);
struct
net_device
*
netdev
=
dev
->
netdev
;
struct
pcan_usb_pro_msg
usb_msg
;
u8
*
rec_ptr
,
*
msg_end
;
u16
rec_cnt
;
int
err
=
0
;
rec_ptr
=
pcan_msg_init
(
&
usb_msg
,
urb
->
transfer_buffer
,
urb
->
actual_length
);
if
(
!
rec_ptr
)
{
netdev_err
(
netdev
,
"bad msg hdr len %d
\n
"
,
urb
->
actual_length
);
return
-
EINVAL
;
}
/* loop reading all the records from the incoming message */
msg_end
=
urb
->
transfer_buffer
+
urb
->
actual_length
;
rec_cnt
=
le16_to_cpu
(
*
usb_msg
.
u
.
rec_cnt_rd
);
for
(;
rec_cnt
>
0
;
rec_cnt
--
)
{
union
pcan_usb_pro_rec
*
pr
=
(
union
pcan_usb_pro_rec
*
)
rec_ptr
;
u16
sizeof_rec
=
pcan_usb_pro_sizeof_rec
[
pr
->
data_type
];
if
(
!
sizeof_rec
)
{
netdev_err
(
netdev
,
"got unsupported rec in usb msg:
\n
"
);
err
=
-
ENOTSUPP
;
break
;
}
/* check if the record goes out of current packet */
if
(
rec_ptr
+
sizeof_rec
>
msg_end
)
{
netdev_err
(
netdev
,
"got frag rec: should inc usb rx buf size
\n
"
);
err
=
-
EBADMSG
;
break
;
}
switch
(
pr
->
data_type
)
{
case
PCAN_USBPRO_RXMSG8
:
case
PCAN_USBPRO_RXMSG4
:
case
PCAN_USBPRO_RXMSG0
:
case
PCAN_USBPRO_RXRTR
:
err
=
pcan_usb_pro_handle_canmsg
(
usb_if
,
&
pr
->
rx_msg
);
if
(
err
<
0
)
goto
fail
;
break
;
case
PCAN_USBPRO_RXSTATUS
:
err
=
pcan_usb_pro_handle_error
(
usb_if
,
&
pr
->
rx_status
);
if
(
err
<
0
)
goto
fail
;
break
;
case
PCAN_USBPRO_RXTS
:
pcan_usb_pro_handle_ts
(
usb_if
,
&
pr
->
rx_ts
);
break
;
default:
netdev_err
(
netdev
,
"unhandled rec type 0x%02x (%d): ignored
\n
"
,
pr
->
data_type
,
pr
->
data_type
);
break
;
}
rec_ptr
+=
sizeof_rec
;
}
fail:
if
(
err
)
dump_mem
(
"received msg"
,
urb
->
transfer_buffer
,
urb
->
actual_length
);
return
err
;
}
static
int
pcan_usb_pro_encode_msg
(
struct
peak_usb_device
*
dev
,
struct
sk_buff
*
skb
,
u8
*
obuf
,
size_t
*
size
)
{
struct
can_frame
*
cf
=
(
struct
can_frame
*
)
skb
->
data
;
u8
data_type
,
len
,
flags
;
struct
pcan_usb_pro_msg
usb_msg
;
pcan_msg_init_empty
(
&
usb_msg
,
obuf
,
*
size
);
if
((
cf
->
can_id
&
CAN_RTR_FLAG
)
||
(
cf
->
can_dlc
==
0
))
data_type
=
PCAN_USBPRO_TXMSG0
;
else
if
(
cf
->
can_dlc
<=
4
)
data_type
=
PCAN_USBPRO_TXMSG4
;
else
data_type
=
PCAN_USBPRO_TXMSG8
;
len
=
(
dev
->
ctrl_idx
<<
4
)
|
(
cf
->
can_dlc
&
0x0f
);
flags
=
0
;
if
(
cf
->
can_id
&
CAN_EFF_FLAG
)
flags
|=
0x02
;
if
(
cf
->
can_id
&
CAN_RTR_FLAG
)
flags
|=
0x01
;
pcan_msg_add_rec
(
&
usb_msg
,
data_type
,
0
,
flags
,
len
,
cf
->
can_id
,
cf
->
data
);
*
size
=
usb_msg
.
rec_buffer_len
;
return
0
;
}
static
int
pcan_usb_pro_start
(
struct
peak_usb_device
*
dev
)
{
struct
pcan_usb_pro_device
*
pdev
=
container_of
(
dev
,
struct
pcan_usb_pro_device
,
dev
);
int
err
;
err
=
pcan_usb_pro_set_silent
(
dev
,
dev
->
can
.
ctrlmode
&
CAN_CTRLMODE_LISTENONLY
);
if
(
err
)
return
err
;
/* filter mode: 0-> All OFF; 1->bypass */
err
=
pcan_usb_pro_set_filter
(
dev
,
1
);
if
(
err
)
return
err
;
/* opening first device: */
if
(
pdev
->
usb_if
->
dev_opened_count
==
0
)
{
/* reset time_ref */
peak_usb_init_time_ref
(
&
pdev
->
usb_if
->
time_ref
,
&
pcan_usb_pro
);
/* ask device to send ts messages */
err
=
pcan_usb_pro_set_ts
(
dev
,
1
);
}
pdev
->
usb_if
->
dev_opened_count
++
;
return
err
;
}
/*
* stop interface
* (last chance before set bus off)
*/
static
int
pcan_usb_pro_stop
(
struct
peak_usb_device
*
dev
)
{
struct
pcan_usb_pro_device
*
pdev
=
container_of
(
dev
,
struct
pcan_usb_pro_device
,
dev
);
/* turn off ts msgs for that interface if no other dev opened */
if
(
pdev
->
usb_if
->
dev_opened_count
==
1
)
pcan_usb_pro_set_ts
(
dev
,
0
);
pdev
->
usb_if
->
dev_opened_count
--
;
return
0
;
}
/*
* called when probing to initialize a device object.
*/
static
int
pcan_usb_pro_init
(
struct
peak_usb_device
*
dev
)
{
struct
pcan_usb_pro_interface
*
usb_if
;
struct
pcan_usb_pro_device
*
pdev
=
container_of
(
dev
,
struct
pcan_usb_pro_device
,
dev
);
/* do this for 1st channel only */
if
(
!
dev
->
prev_siblings
)
{
struct
pcan_usb_pro_fwinfo
fi
;
struct
pcan_usb_pro_blinfo
bi
;
int
err
;
/* allocate netdevices common structure attached to first one */
usb_if
=
kzalloc
(
sizeof
(
struct
pcan_usb_pro_interface
),
GFP_KERNEL
);
if
(
!
usb_if
)
return
-
ENOMEM
;
/* number of ts msgs to ignore before taking one into account */
usb_if
->
cm_ignore_count
=
5
;
/*
* explicit use of dev_xxx() instead of netdev_xxx() here:
* information displayed are related to the device itself, not
* to the canx netdevices.
*/
err
=
pcan_usb_pro_send_req
(
dev
,
PCAN_USBPRO_REQ_INFO
,
PCAN_USBPRO_INFO_FW
,
&
fi
,
sizeof
(
fi
));
if
(
err
)
{
dev_err
(
dev
->
netdev
->
dev
.
parent
,
"unable to read %s firmware info (err %d)
\n
"
,
pcan_usb_pro
.
name
,
err
);
return
err
;
}
err
=
pcan_usb_pro_send_req
(
dev
,
PCAN_USBPRO_REQ_INFO
,
PCAN_USBPRO_INFO_BL
,
&
bi
,
sizeof
(
bi
));
if
(
err
)
{
dev_err
(
dev
->
netdev
->
dev
.
parent
,
"unable to read %s bootloader info (err %d)
\n
"
,
pcan_usb_pro
.
name
,
err
);
return
err
;
}
dev_info
(
dev
->
netdev
->
dev
.
parent
,
"PEAK-System %s hwrev %u serial %08X.%08X (%u channels)
\n
"
,
pcan_usb_pro
.
name
,
bi
.
hw_rev
,
bi
.
serial_num_hi
,
bi
.
serial_num_lo
,
pcan_usb_pro
.
ctrl_count
);
/* tell the device the can driver is running */
pcan_usb_pro_drv_loaded
(
dev
,
1
);
}
else
{
usb_if
=
pcan_usb_pro_dev_if
(
dev
->
prev_siblings
);
}
pdev
->
usb_if
=
usb_if
;
usb_if
->
dev
[
dev
->
ctrl_idx
]
=
dev
;
/* set LED in default state (end of init phase) */
pcan_usb_pro_set_led
(
dev
,
0
,
1
);
return
0
;
}
static
void
pcan_usb_pro_exit
(
struct
peak_usb_device
*
dev
)
{
struct
pcan_usb_pro_device
*
pdev
=
container_of
(
dev
,
struct
pcan_usb_pro_device
,
dev
);
/*
* when rmmod called before unplug and if down, should reset things
* before leaving
*/
if
(
dev
->
can
.
state
!=
CAN_STATE_STOPPED
)
{
/* set bus off on the corresponding channel */
pcan_usb_pro_set_bus
(
dev
,
0
);
}
/* if channel #0 (only) */
if
(
dev
->
ctrl_idx
==
0
)
{
/* turn off calibration message if any device were opened */
if
(
pdev
->
usb_if
->
dev_opened_count
>
0
)
pcan_usb_pro_set_ts
(
dev
,
0
);
/* tell the PCAN-USB Pro device the driver is being unloaded */
pcan_usb_pro_drv_loaded
(
dev
,
0
);
}
}
/*
* called when PCAN-USB Pro adapter is unplugged
*/
static
void
pcan_usb_pro_free
(
struct
peak_usb_device
*
dev
)
{
/* last device: can free pcan_usb_pro_interface object now */
if
(
!
dev
->
prev_siblings
&&
!
dev
->
next_siblings
)
kfree
(
pcan_usb_pro_dev_if
(
dev
));
}
/*
* probe function for new PCAN-USB Pro usb interface
*/
static
int
pcan_usb_pro_probe
(
struct
usb_interface
*
intf
)
{
struct
usb_host_interface
*
if_desc
;
int
i
;
if_desc
=
intf
->
altsetting
;
/* check interface endpoint addresses */
for
(
i
=
0
;
i
<
if_desc
->
desc
.
bNumEndpoints
;
i
++
)
{
struct
usb_endpoint_descriptor
*
ep
=
&
if_desc
->
endpoint
[
i
].
desc
;
/*
* below is the list of valid ep addreses. Any other ep address
* is considered as not-CAN interface address => no dev created
*/
switch
(
ep
->
bEndpointAddress
)
{
case
PCAN_USBPRO_EP_CMDOUT
:
case
PCAN_USBPRO_EP_CMDIN
:
case
PCAN_USBPRO_EP_MSGOUT_0
:
case
PCAN_USBPRO_EP_MSGOUT_1
:
case
PCAN_USBPRO_EP_MSGIN
:
case
PCAN_USBPRO_EP_UNUSED
:
break
;
default:
return
-
ENODEV
;
}
}
return
0
;
}
/*
* describe the PCAN-USB Pro adapter
*/
struct
peak_usb_adapter
pcan_usb_pro
=
{
.
name
=
"PCAN-USB Pro"
,
.
device_id
=
PCAN_USBPRO_PRODUCT_ID
,
.
ctrl_count
=
PCAN_USBPRO_CHANNEL_COUNT
,
.
clock
=
{
.
freq
=
PCAN_USBPRO_CRYSTAL_HZ
,
},
.
bittiming_const
=
{
.
name
=
"pcan_usb_pro"
,
.
tseg1_min
=
1
,
.
tseg1_max
=
16
,
.
tseg2_min
=
1
,
.
tseg2_max
=
8
,
.
sjw_max
=
4
,
.
brp_min
=
1
,
.
brp_max
=
1024
,
.
brp_inc
=
1
,
},
/* size of device private data */
.
sizeof_dev_private
=
sizeof
(
struct
pcan_usb_pro_device
),
/* timestamps usage */
.
ts_used_bits
=
32
,
.
ts_period
=
1000000
,
/* calibration period in ts. */
.
us_per_ts_scale
=
1
,
/* us = (ts * scale) >> shift */
.
us_per_ts_shift
=
0
,
/* give here messages in/out endpoints */
.
ep_msg_in
=
PCAN_USBPRO_EP_MSGIN
,
.
ep_msg_out
=
{
PCAN_USBPRO_EP_MSGOUT_0
,
PCAN_USBPRO_EP_MSGOUT_1
},
/* size of rx/tx usb buffers */
.
rx_buffer_size
=
PCAN_USBPRO_RX_BUFFER_SIZE
,
.
tx_buffer_size
=
PCAN_USBPRO_TX_BUFFER_SIZE
,
/* device callbacks */
.
intf_probe
=
pcan_usb_pro_probe
,
.
dev_init
=
pcan_usb_pro_init
,
.
dev_exit
=
pcan_usb_pro_exit
,
.
dev_free
=
pcan_usb_pro_free
,
.
dev_set_bus
=
pcan_usb_pro_set_bus
,
.
dev_set_bittiming
=
pcan_usb_pro_set_bittiming
,
.
dev_get_device_id
=
pcan_usb_pro_get_device_id
,
.
dev_decode_buf
=
pcan_usb_pro_decode_buf
,
.
dev_encode_msg
=
pcan_usb_pro_encode_msg
,
.
dev_start
=
pcan_usb_pro_start
,
.
dev_stop
=
pcan_usb_pro_stop
,
.
dev_restart_async
=
pcan_usb_pro_restart_async
,
};
drivers/net/can/usb/peak_usb/pcan_usb_pro.h
0 → 100644
View file @
ffcb9738
/*
* CAN driver for PEAK System PCAN-USB Pro adapter
* Derived from the PCAN project file driver/src/pcan_usbpro_fw.h
*
* Copyright (C) 2003-2011 PEAK System-Technik GmbH
* Copyright (C) 2011-2012 Stephane Grosjean <s.grosjean@peak-system.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published
* by the Free Software Foundation; version 2 of the License.
*
* 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.
*/
#ifndef PCAN_USB_PRO_H
#define PCAN_USB_PRO_H
/*
* USB Vendor request data types
*/
#define PCAN_USBPRO_REQ_INFO 0
#define PCAN_USBPRO_REQ_FCT 2
/* Vendor Request value for XXX_INFO */
#define PCAN_USBPRO_INFO_BL 0
#define PCAN_USBPRO_INFO_FW 1
/* Vendor Request value for XXX_FCT */
#define PCAN_USBPRO_FCT_DRVLD 5
/* tell device driver is loaded */
/* PCAN_USBPRO_INFO_BL vendor request record type */
struct
__packed
pcan_usb_pro_blinfo
{
u32
ctrl_type
;
u8
version
[
4
];
u8
day
;
u8
month
;
u8
year
;
u8
dummy
;
u32
serial_num_hi
;
u32
serial_num_lo
;
u32
hw_type
;
u32
hw_rev
;
};
/* PCAN_USBPRO_INFO_FW vendor request record type */
struct
__packed
pcan_usb_pro_fwinfo
{
u32
ctrl_type
;
u8
version
[
4
];
u8
day
;
u8
month
;
u8
year
;
u8
dummy
;
u32
fw_type
;
};
/*
* USB Command record types
*/
#define PCAN_USBPRO_SETBTR 0x02
#define PCAN_USBPRO_SETBUSACT 0x04
#define PCAN_USBPRO_SETSILENT 0x05
#define PCAN_USBPRO_SETFILTR 0x0a
#define PCAN_USBPRO_SETTS 0x10
#define PCAN_USBPRO_GETDEVID 0x12
#define PCAN_USBPRO_SETLED 0x1C
#define PCAN_USBPRO_RXMSG8 0x80
#define PCAN_USBPRO_RXMSG4 0x81
#define PCAN_USBPRO_RXMSG0 0x82
#define PCAN_USBPRO_RXRTR 0x83
#define PCAN_USBPRO_RXSTATUS 0x84
#define PCAN_USBPRO_RXTS 0x85
#define PCAN_USBPRO_TXMSG8 0x41
#define PCAN_USBPRO_TXMSG4 0x42
#define PCAN_USBPRO_TXMSG0 0x43
/* record structures */
struct
__packed
pcan_usb_pro_btr
{
u8
data_type
;
u8
channel
;
u16
dummy
;
u32
CCBT
;
};
struct
__packed
pcan_usb_pro_busact
{
u8
data_type
;
u8
channel
;
u16
onoff
;
};
struct
__packed
pcan_usb_pro_silent
{
u8
data_type
;
u8
channel
;
u16
onoff
;
};
struct
__packed
pcan_usb_pro_filter
{
u8
data_type
;
u8
dummy
;
u16
filter_mode
;
};
struct
__packed
pcan_usb_pro_setts
{
u8
data_type
;
u8
dummy
;
u16
mode
;
};
struct
__packed
pcan_usb_pro_devid
{
u8
data_type
;
u8
channel
;
u16
dummy
;
u32
serial_num
;
};
struct
__packed
pcan_usb_pro_setled
{
u8
data_type
;
u8
channel
;
u16
mode
;
u32
timeout
;
};
struct
__packed
pcan_usb_pro_rxmsg
{
u8
data_type
;
u8
client
;
u8
flags
;
u8
len
;
u32
ts32
;
u32
id
;
u8
data
[
8
];
};
#define PCAN_USBPRO_STATUS_ERROR 0x0001
#define PCAN_USBPRO_STATUS_BUS 0x0002
#define PCAN_USBPRO_STATUS_OVERRUN 0x0004
#define PCAN_USBPRO_STATUS_QOVERRUN 0x0008
struct
__packed
pcan_usb_pro_rxstatus
{
u8
data_type
;
u8
channel
;
u16
status
;
u32
ts32
;
u32
err_frm
;
};
struct
__packed
pcan_usb_pro_rxts
{
u8
data_type
;
u8
dummy
[
3
];
u32
ts64
[
2
];
};
struct
__packed
pcan_usb_pro_txmsg
{
u8
data_type
;
u8
client
;
u8
flags
;
u8
len
;
u32
id
;
u8
data
[
8
];
};
union
pcan_usb_pro_rec
{
u8
data_type
;
struct
pcan_usb_pro_btr
btr
;
struct
pcan_usb_pro_busact
bus_act
;
struct
pcan_usb_pro_silent
silent_mode
;
struct
pcan_usb_pro_filter
filter_mode
;
struct
pcan_usb_pro_setts
ts
;
struct
pcan_usb_pro_devid
dev_id
;
struct
pcan_usb_pro_setled
set_led
;
struct
pcan_usb_pro_rxmsg
rx_msg
;
struct
pcan_usb_pro_rxstatus
rx_status
;
struct
pcan_usb_pro_rxts
rx_ts
;
struct
pcan_usb_pro_txmsg
tx_msg
;
};
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment