提交 de565664 编写于 作者: D David S. Miller

can: Revert outdated cc770 driver patches.

Newer versions have been floating about, and I applied
to older variant unfortunately.
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 ec2a5466
......@@ -116,8 +116,6 @@ source "drivers/net/can/sja1000/Kconfig"
source "drivers/net/can/c_can/Kconfig"
source "drivers/net/can/cc770/Kconfig"
source "drivers/net/can/usb/Kconfig"
source "drivers/net/can/softing/Kconfig"
......
......@@ -14,7 +14,6 @@ obj-y += softing/
obj-$(CONFIG_CAN_SJA1000) += sja1000/
obj-$(CONFIG_CAN_MSCAN) += mscan/
obj-$(CONFIG_CAN_C_CAN) += c_can/
obj-$(CONFIG_CAN_CC770) += cc770/
obj-$(CONFIG_CAN_AT91) += at91_can.o
obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o
obj-$(CONFIG_CAN_MCP251X) += mcp251x.o
......
menuconfig CAN_CC770
tristate "Bosch CC770 and Intel AN82527 devices"
depends on CAN_DEV && HAS_IOMEM
if CAN_CC770
config CAN_CC770_ISA
tristate "ISA Bus based legacy CC770 driver"
---help---
This driver adds legacy support for CC770 and AN82527 chips
connected to the ISA bus using I/O port, memory mapped or
indirect access.
endif
#
# Makefile for the Bosch CC770 CAN controller drivers.
#
obj-$(CONFIG_CAN_CC770) += cc770.o
obj-$(CONFIG_CAN_CC770_ISA) += cc770_isa.o
ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
此差异已折叠。
/*
* cc770.h - Bosch CC770 and Intel AN82527 network device driver
*
* Copyright (C) 2009, 2011 Wolfgang Grandegger <wg@grandegger.com>
*
* Derived from the old Socket-CAN i82527 driver:
*
* Copyright (c) 2002-2007 Volkswagen Group Electronic Research
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Volkswagen nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* Alternatively, provided that this notice is retained in full, this
* software may be distributed under the terms of the GNU General
* Public License ("GPL") version 2, in which case the provisions of the
* GPL apply INSTEAD OF those given above.
*
* The provided data structures and external interfaces from this code
* are not restricted to be used by modules with a GPL compatible license.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* Send feedback to <socketcan-users@lists.berlios.de>
*/
#ifndef CC770_DEV_H
#define CC770_DEV_H
#include <linux/can/dev.h>
struct cc770_msgobj {
u8 ctrl0;
u8 ctrl1;
u8 id[4];
u8 config;
u8 data[8];
u8 dontuse; /* padding */
} __attribute__ ((packed));
struct cc770_regs {
union {
struct cc770_msgobj msgobj[16]; /* Message object 1..15 */
struct {
u8 control; /* Control Register */
u8 status; /* Status Register */
u8 cpu_interface; /* CPU Interface Register */
u8 dontuse1;
u8 high_speed_read[2]; /* High Speed Read */
u8 global_mask_std[2]; /* Standard Global Mask */
u8 global_mask_ext[4]; /* Extended Global Mask */
u8 msg15_mask[4]; /* Message 15 Mask */
u8 dontuse2[15];
u8 clkout; /* Clock Out Register */
u8 dontuse3[15];
u8 bus_config; /* Bus Configuration Register */
u8 dontuse4[15];
u8 bit_timing_0; /* Bit Timing Register byte 0 */
u8 dontuse5[15];
u8 bit_timing_1; /* Bit Timing Register byte 1 */
u8 dontuse6[15];
u8 interrupt; /* Interrupt Register */
u8 dontuse7[15];
u8 rx_error_counter; /* Receive Error Counter */
u8 dontuse8[15];
u8 tx_error_counter; /* Transmit Error Counter */
u8 dontuse9[31];
u8 p1_conf;
u8 dontuse10[15];
u8 p2_conf;
u8 dontuse11[15];
u8 p1_in;
u8 dontuse12[15];
u8 p2_in;
u8 dontuse13[15];
u8 p1_out;
u8 dontuse14[15];
u8 p2_out;
u8 dontuse15[15];
u8 serial_reset_addr;
};
};
} __attribute__ ((packed));
/* Control Register (0x00) */
#define CTRL_INI 0x01 /* Initialization */
#define CTRL_IE 0x02 /* Interrupt Enable */
#define CTRL_SIE 0x04 /* Status Interrupt Enable */
#define CTRL_EIE 0x08 /* Error Interrupt Enable */
#define CTRL_EAF 0x20 /* Enable additional functions */
#define CTRL_CCE 0x40 /* Change Configuration Enable */
/* Status Register (0x01) */
#define STAT_LEC_STUFF 0x01 /* Stuff error */
#define STAT_LEC_FORM 0x02 /* Form error */
#define STAT_LEC_ACK 0x03 /* Acknowledgement error */
#define STAT_LEC_BIT1 0x04 /* Bit1 error */
#define STAT_LEC_BIT0 0x05 /* Bit0 error */
#define STAT_LEC_CRC 0x06 /* CRC error */
#define STAT_LEC_MASK 0x07 /* Last Error Code mask */
#define STAT_TXOK 0x08 /* Transmit Message Successfully */
#define STAT_RXOK 0x10 /* Receive Message Successfully */
#define STAT_WAKE 0x20 /* Wake Up Status */
#define STAT_WARN 0x40 /* Warning Status */
#define STAT_BOFF 0x80 /* Bus Off Status */
/* CPU Interface Register (0x02) */
#define CPUIF_CEN 0x01 /* Clock Out Enable */
#define CPUIF_MUX 0x04 /* Multiplex */
#define CPUIF_SLP 0x08 /* Sleep */
#define CPUIF_PWD 0x10 /* Power Down Mode */
#define CPUIF_DMC 0x20 /* Divide Memory Clock */
#define CPUIF_DSC 0x40 /* Divide System Clock */
#define CPUIF_RST 0x80 /* Hardware Reset Status */
/* Clock Out Register (0x1f) */
#define CLKOUT_CD_MASK 0x0f /* Clock Divider mask */
#define CLKOUT_SL_MASK 0x30 /* Slew Rate mask */
#define CLKOUT_SL_SHIFT 4
/* Bus Configuration Register (0x2f) */
#define BUSCFG_DR0 0x01 /* Disconnect RX0 Input / Select RX input */
#define BUSCFG_DR1 0x02 /* Disconnect RX1 Input / Silent mode */
#define BUSCFG_DT1 0x08 /* Disconnect TX1 Output */
#define BUSCFG_POL 0x20 /* Polarity dominant or recessive */
#define BUSCFG_CBY 0x40 /* Input Comparator Bypass */
/* Message Control Register 0 (Base Address + 0x0) */
#define INTPND_RES 0x01 /* No Interrupt pending */
#define INTPND_SET 0x02 /* Interrupt pending */
#define INTPND_UNC 0x03
#define RXIE_RES 0x04 /* Receive Interrupt Disable */
#define RXIE_SET 0x08 /* Receive Interrupt Enable */
#define RXIE_UNC 0x0c
#define TXIE_RES 0x10 /* Transmit Interrupt Disable */
#define TXIE_SET 0x20 /* Transmit Interrupt Enable */
#define TXIE_UNC 0x30
#define MSGVAL_RES 0x40 /* Message Invalid */
#define MSGVAL_SET 0x80 /* Message Valid */
#define MSGVAL_UNC 0xc0
/* Message Control Register 1 (Base Address + 0x01) */
#define NEWDAT_RES 0x01 /* No New Data */
#define NEWDAT_SET 0x02 /* New Data */
#define NEWDAT_UNC 0x03
#define MSGLST_RES 0x04 /* No Message Lost */
#define MSGLST_SET 0x08 /* Message Lost */
#define MSGLST_UNC 0x0c
#define CPUUPD_RES 0x04 /* No CPU Updating */
#define CPUUPD_SET 0x08 /* CPU Updating */
#define CPUUPD_UNC 0x0c
#define TXRQST_RES 0x10 /* No Transmission Request */
#define TXRQST_SET 0x20 /* Transmission Request */
#define TXRQST_UNC 0x30
#define RMTPND_RES 0x40 /* No Remote Request Pending */
#define RMTPND_SET 0x80 /* Remote Request Pending */
#define RMTPND_UNC 0xc0
/* Message Configuration Register (Base Address + 0x06) */
#define MSGCFG_XTD 0x04 /* Extended Identifier */
#define MSGCFG_DIR 0x08 /* Direction is Transmit */
#define MSGOBJ_FIRST 1
#define MSGOBJ_LAST 15
#define CC770_IO_SIZE 0x100
#define CC770_MAX_IRQ 20 /* max. number of interrupts handled in ISR */
#define CC770_ECHO_SKB_MAX 1
#define cc770_read_reg(priv, member) \
priv->read_reg(priv, offsetof(struct cc770_regs, member))
#define cc770_write_reg(priv, member, value) \
priv->write_reg(priv, offsetof(struct cc770_regs, member), value)
/*
* Message objects and flags used by this driver
*/
#define CC770_OBJ_FLAG_RX 0x01
#define CC770_OBJ_FLAG_RTR 0x02
#define CC770_OBJ_FLAG_EFF 0x04
enum {
CC770_OBJ_RX0 = 0, /* for receiving normal messages */
CC770_OBJ_RX1, /* for receiving normal messages */
CC770_OBJ_RX_RTR0, /* for receiving remote transmission requests */
CC770_OBJ_RX_RTR1, /* for receiving remote transmission requests */
CC770_OBJ_TX, /* for sending messages */
CC770_OBJ_MAX
};
#define obj2msgobj(o) (MSGOBJ_LAST - (o)) /* message object 11..15 */
/*
* CC770 private data structure
*/
struct cc770_priv {
struct can_priv can; /* must be the first member */
int open_time;
struct sk_buff *echo_skb;
/* the lower-layer is responsible for appropriate locking */
u8 (*read_reg)(const struct cc770_priv *priv, int reg);
void (*write_reg)(const struct cc770_priv *priv, int reg, u8 val);
void (*pre_irq)(const struct cc770_priv *priv);
void (*post_irq)(const struct cc770_priv *priv);
void *priv; /* for board-specific data */
struct net_device *dev;
void __iomem *reg_base; /* ioremap'ed address to registers */
unsigned long irq_flags; /* for request_irq() */
unsigned char obj_flags[CC770_OBJ_MAX];
u8 control_normal_mode; /* Control register for normal mode */
u8 cpu_interface; /* CPU interface register */
u8 clkout; /* Clock out register */
u8 bus_config; /* Bus conffiguration register */
};
struct net_device *alloc_cc770dev(int sizeof_priv);
void free_cc770dev(struct net_device *dev);
int register_cc770dev(struct net_device *dev);
void unregister_cc770dev(struct net_device *dev);
#endif /* CC770_DEV_H */
/*
* Copyright (C) 2009, 2011 Wolfgang Grandegger <wg@grandegger.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the version 2 of the GNU General Public License
* as published by the Free Software Foundation
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/can.h>
#include <linux/can/dev.h>
#include "cc770.h"
#define DRV_NAME "cc770_isa"
#define MAXDEV 8
MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
MODULE_DESCRIPTION("Socket-CAN driver for CC770 on the ISA bus");
MODULE_LICENSE("GPL v2");
#define CLK_DEFAULT 16000000 /* 16 MHz */
#define BCR_DEFAULT 0x00
#define COR_DEFAULT 0x00
static unsigned long port[MAXDEV];
static unsigned long mem[MAXDEV];
static int __devinitdata irq[MAXDEV];
static int __devinitdata clk[MAXDEV];
static u8 __devinitdata cir[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
static u8 __devinitdata bcr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
static u8 __devinitdata cor[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
static int __devinitdata indirect[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1};
module_param_array(port, ulong, NULL, S_IRUGO);
MODULE_PARM_DESC(port, "I/O port number");
module_param_array(mem, ulong, NULL, S_IRUGO);
MODULE_PARM_DESC(mem, "I/O memory address");
module_param_array(indirect, int, NULL, S_IRUGO);
MODULE_PARM_DESC(indirect, "Indirect access via address and data port");
module_param_array(irq, int, NULL, S_IRUGO);
MODULE_PARM_DESC(irq, "IRQ number");
module_param_array(clk, int, NULL, S_IRUGO);
MODULE_PARM_DESC(clk, "External oscillator clock frequency "
"(default=16000000 [16 MHz])");
module_param_array(cir, byte, NULL, S_IRUGO);
MODULE_PARM_DESC(cir, "CPU interface register (default=0x40 [CPU_DSC])");
module_param_array(bcr, byte, NULL, S_IRUGO);
MODULE_PARM_DESC(ocr, "Bus configuration register (default=0x00)");
module_param_array(cor, byte, NULL, S_IRUGO);
MODULE_PARM_DESC(cor, "Clockout register (default=0x00)");
#define CC770_IOSIZE 0x20
#define CC770_IOSIZE_INDIRECT 0x02
static struct platform_device *cc770_isa_devs[MAXDEV];
static u8 cc770_isa_mem_read_reg(const struct cc770_priv *priv, int reg)
{
return readb(priv->reg_base + reg);
}
static void cc770_isa_mem_write_reg(const struct cc770_priv *priv,
int reg, u8 val)
{
writeb(val, priv->reg_base + reg);
}
static u8 cc770_isa_port_read_reg(const struct cc770_priv *priv, int reg)
{
return inb((unsigned long)priv->reg_base + reg);
}
static void cc770_isa_port_write_reg(const struct cc770_priv *priv,
int reg, u8 val)
{
outb(val, (unsigned long)priv->reg_base + reg);
}
static u8 cc770_isa_port_read_reg_indirect(const struct cc770_priv *priv,
int reg)
{
unsigned long base = (unsigned long)priv->reg_base;
outb(reg, base);
return inb(base + 1);
}
static void cc770_isa_port_write_reg_indirect(const struct cc770_priv *priv,
int reg, u8 val)
{
unsigned long base = (unsigned long)priv->reg_base;
outb(reg, base);
outb(val, base + 1);
}
static int __devinit cc770_isa_probe(struct platform_device *pdev)
{
struct net_device *dev;
struct cc770_priv *priv;
void __iomem *base = NULL;
int iosize = CC770_IOSIZE;
int idx = pdev->id;
int err;
u32 clktmp;
dev_dbg(&pdev->dev, "probing idx=%d: port=%#lx, mem=%#lx, irq=%d\n",
idx, port[idx], mem[idx], irq[idx]);
if (mem[idx]) {
if (!request_mem_region(mem[idx], iosize, DRV_NAME)) {
err = -EBUSY;
goto exit;
}
base = ioremap_nocache(mem[idx], iosize);
if (!base) {
err = -ENOMEM;
goto exit_release;
}
} else {
if (indirect[idx] > 0 ||
(indirect[idx] == -1 && indirect[0] > 0))
iosize = CC770_IOSIZE_INDIRECT;
if (!request_region(port[idx], iosize, DRV_NAME)) {
err = -EBUSY;
goto exit;
}
}
dev = alloc_cc770dev(0);
if (!dev) {
err = -ENOMEM;
goto exit_unmap;
}
priv = netdev_priv(dev);
dev->irq = irq[idx];
priv->irq_flags = IRQF_SHARED;
if (mem[idx]) {
priv->reg_base = base;
dev->base_addr = mem[idx];
priv->read_reg = cc770_isa_mem_read_reg;
priv->write_reg = cc770_isa_mem_write_reg;
} else {
priv->reg_base = (void __iomem *)port[idx];
dev->base_addr = port[idx];
if (iosize == CC770_IOSIZE_INDIRECT) {
priv->read_reg = cc770_isa_port_read_reg_indirect;
priv->write_reg = cc770_isa_port_write_reg_indirect;
} else {
priv->read_reg = cc770_isa_port_read_reg;
priv->write_reg = cc770_isa_port_write_reg;
}
}
if (clk[idx])
clktmp = clk[idx];
else if (clk[0])
clktmp = clk[0];
else
clktmp = CLK_DEFAULT;
priv->can.clock.freq = clktmp;
if (cir[idx] != 0xff) {
priv->cpu_interface = cir[idx] & 0xff;
} else if (cir[0] != 0xff) {
priv->cpu_interface = cir[0] & 0xff;
} else {
/* The system clock may not exceed 10 MHz */
if (clktmp > 10000000) {
priv->cpu_interface |= CPUIF_DSC;
clktmp /= 2;
}
/* The memory clock may not exceed 8 MHz */
if (clktmp > 8000000)
priv->cpu_interface |= CPUIF_DMC;
}
if (priv->cpu_interface & CPUIF_DSC)
priv->can.clock.freq /= 2;
if (bcr[idx] != 0xff)
priv->bus_config = bcr[idx] & 0xff;
else if (bcr[0] != 0xff)
priv->bus_config = bcr[0] & 0xff;
else
priv->bus_config = BCR_DEFAULT;
if (cor[idx] != 0xff)
priv->clkout = cor[idx];
else if (cor[0] != 0xff)
priv->clkout = cor[0] & 0xff;
else
priv->clkout = COR_DEFAULT;
dev_set_drvdata(&pdev->dev, dev);
SET_NETDEV_DEV(dev, &pdev->dev);
err = register_cc770dev(dev);
if (err) {
dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
DRV_NAME, err);
goto exit_unmap;
}
dev_info(&pdev->dev, "%s device registered (reg_base=0x%p, irq=%d)\n",
DRV_NAME, priv->reg_base, dev->irq);
return 0;
exit_unmap:
if (mem[idx])
iounmap(base);
exit_release:
if (mem[idx])
release_mem_region(mem[idx], iosize);
else
release_region(port[idx], iosize);
exit:
return err;
}
static int __devexit cc770_isa_remove(struct platform_device *pdev)
{
struct net_device *dev = dev_get_drvdata(&pdev->dev);
struct cc770_priv *priv = netdev_priv(dev);
int idx = pdev->id;
unregister_cc770dev(dev);
dev_set_drvdata(&pdev->dev, NULL);
if (mem[idx]) {
iounmap(priv->reg_base);
release_mem_region(mem[idx], CC770_IOSIZE);
} else {
if (priv->read_reg == cc770_isa_port_read_reg_indirect)
release_region(port[idx], CC770_IOSIZE_INDIRECT);
else
release_region(port[idx], CC770_IOSIZE);
}
free_cc770dev(dev);
return 0;
}
static struct platform_driver cc770_isa_driver = {
.probe = cc770_isa_probe,
.remove = __devexit_p(cc770_isa_remove),
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
},
};
static int __init cc770_isa_init(void)
{
int idx, err;
for (idx = 0; idx < MAXDEV; idx++) {
if ((port[idx] || mem[idx]) && irq[idx]) {
cc770_isa_devs[idx] =
platform_device_alloc(DRV_NAME, idx);
if (!cc770_isa_devs[idx]) {
err = -ENOMEM;
goto exit_free_devices;
}
err = platform_device_add(cc770_isa_devs[idx]);
if (err) {
platform_device_put(cc770_isa_devs[idx]);
goto exit_free_devices;
}
pr_debug("%s: platform device %d: port=%#lx, mem=%#lx, "
"irq=%d\n",
DRV_NAME, idx, port[idx], mem[idx], irq[idx]);
} else if (idx == 0 || port[idx] || mem[idx]) {
pr_err("%s: insufficient parameters supplied\n",
DRV_NAME);
err = -EINVAL;
goto exit_free_devices;
}
}
err = platform_driver_register(&cc770_isa_driver);
if (err)
goto exit_free_devices;
pr_info("Legacy %s driver for max. %d devices registered\n",
DRV_NAME, MAXDEV);
return 0;
exit_free_devices:
while (--idx >= 0) {
if (cc770_isa_devs[idx])
platform_device_unregister(cc770_isa_devs[idx]);
}
return err;
}
module_init(cc770_isa_init);
static void __exit cc770_isa_exit(void)
{
int idx;
platform_driver_unregister(&cc770_isa_driver);
for (idx = 0; idx < MAXDEV; idx++) {
if (cc770_isa_devs[idx])
platform_device_unregister(cc770_isa_devs[idx]);
}
}
module_exit(cc770_isa_exit);
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册