Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
raspberrypi-kernel
提交
ffcb9738
R
raspberrypi-kernel
项目概览
openeuler
/
raspberrypi-kernel
通知
13
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
raspberrypi-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
ffcb9738
编写于
3月 04, 2012
作者:
D
David S. Miller
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' of
git://gitorious.org/linux-can/linux-can-next
上级
4c1dc80a
d8a19935
变更
13
展开全部
隐藏空白更改
内联
并排
Showing
13 changed file
with
4490 addition
and
18 deletion
+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
未找到文件。
drivers/net/can/cc770/cc770.c
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
ffcb9738
此差异已折叠。
点击以展开。
drivers/net/can/usb/peak_usb/pcan_usb_core.c
0 → 100644
浏览文件 @
ffcb9738
此差异已折叠。
点击以展开。
drivers/net/can/usb/peak_usb/pcan_usb_core.h
0 → 100644
浏览文件 @
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
浏览文件 @
ffcb9738
此差异已折叠。
点击以展开。
drivers/net/can/usb/peak_usb/pcan_usb_pro.h
0 → 100644
浏览文件 @
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
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录