diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-25 11:25:22 (GMT) |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-25 11:25:22 (GMT) |
commit | 8a9ea3237e7eb5c25f09e429ad242ae5a3d5ea22 (patch) | |
tree | a0a63398a9983667d52cbbbf4e2405b4f22b1d83 /drivers/net/can | |
parent | 1be025d3cb40cd295123af2c394f7229ef9b30ca (diff) | |
parent | 8b3408f8ee994973869d8ba32c5bf482bc4ddca4 (diff) | |
download | linux-fsl-qoriq-8a9ea3237e7eb5c25f09e429ad242ae5a3d5ea22.tar.xz |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1745 commits)
dp83640: free packet queues on remove
dp83640: use proper function to free transmit time stamping packets
ipv6: Do not use routes from locally generated RAs
|PATCH net-next] tg3: add tx_dropped counter
be2net: don't create multiple RX/TX rings in multi channel mode
be2net: don't create multiple TXQs in BE2
be2net: refactor VF setup/teardown code into be_vf_setup/clear()
be2net: add vlan/rx-mode/flow-control config to be_setup()
net_sched: cls_flow: use skb_header_pointer()
ipv4: avoid useless call of the function check_peer_pmtu
TCP: remove TCP_DEBUG
net: Fix driver name for mdio-gpio.c
ipv4: tcp: fix TOS value in ACK messages sent from TIME_WAIT
rtnetlink: Add missing manual netlink notification in dev_change_net_namespaces
ipv4: fix ipsec forward performance regression
jme: fix irq storm after suspend/resume
route: fix ICMP redirect validation
net: hold sock reference while processing tx timestamps
tcp: md5: add more const attributes
Add ethtool -g support to virtio_net
...
Fix up conflicts in:
- drivers/net/Kconfig:
The split-up generated a trivial conflict with removal of a
stale reference to Documentation/networking/net-modules.txt.
Remove it from the new location instead.
- fs/sysfs/dir.c:
Fairly nasty conflicts with the sysfs rb-tree usage, conflicting
with Eric Biederman's changes for tagged directories.
Diffstat (limited to 'drivers/net/can')
-rw-r--r-- | drivers/net/can/at91_can.c | 2 | ||||
-rw-r--r-- | drivers/net/can/dev.c | 14 | ||||
-rw-r--r-- | drivers/net/can/flexcan.c | 189 | ||||
-rw-r--r-- | drivers/net/can/mscan/mscan.c | 26 | ||||
-rw-r--r-- | drivers/net/can/sja1000/Kconfig | 14 | ||||
-rw-r--r-- | drivers/net/can/sja1000/Makefile | 2 | ||||
-rw-r--r-- | drivers/net/can/sja1000/ems_pcmcia.c | 331 | ||||
-rw-r--r-- | drivers/net/can/sja1000/peak_pci.c | 291 | ||||
-rw-r--r-- | drivers/net/can/sja1000/sja1000.c | 2 | ||||
-rw-r--r-- | drivers/net/can/sja1000/sja1000.h | 2 | ||||
-rw-r--r-- | drivers/net/can/slcan.c | 2 | ||||
-rw-r--r-- | drivers/net/can/vcan.c | 2 |
12 files changed, 784 insertions, 93 deletions
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index 121ede6..044ea06 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -8,8 +8,6 @@ * Public License ("GPL") version 2 as distributed in the 'COPYING' * file from the main directory of the linux kernel source. * - * Send feedback to <socketcan-users@lists.berlios.de> - * * * Your platform definition file should specify something like: * diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index 9bf1116..25695bd 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -150,7 +150,19 @@ static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt) bt->prop_seg = tseg1 / 2; bt->phase_seg1 = tseg1 - bt->prop_seg; bt->phase_seg2 = tseg2; - bt->sjw = 1; + + /* check for sjw user settings */ + if (!bt->sjw || !btc->sjw_max) + bt->sjw = 1; + else { + /* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */ + if (bt->sjw > btc->sjw_max) + bt->sjw = btc->sjw_max; + /* bt->sjw must not be higher than tseg2 */ + if (tseg2 < bt->sjw) + bt->sjw = tseg2; + } + bt->brp = best_brp; /* real bit-rate */ bt->bitrate = priv->clock.freq / (bt->brp * (tseg1 + tseg2 + 1)); diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 1767811..e023379 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -33,10 +33,9 @@ #include <linux/kernel.h> #include <linux/list.h> #include <linux/module.h> +#include <linux/of.h> #include <linux/platform_device.h> -#include <mach/clock.h> - #define DRV_NAME "flexcan" /* 8 for RX fifo and 2 error handling */ @@ -192,6 +191,31 @@ static struct can_bittiming_const flexcan_bittiming_const = { }; /* + * Abstract off the read/write for arm versus ppc. + */ +#if defined(__BIG_ENDIAN) +static inline u32 flexcan_read(void __iomem *addr) +{ + return in_be32(addr); +} + +static inline void flexcan_write(u32 val, void __iomem *addr) +{ + out_be32(addr, val); +} +#else +static inline u32 flexcan_read(void __iomem *addr) +{ + return readl(addr); +} + +static inline void flexcan_write(u32 val, void __iomem *addr) +{ + writel(val, addr); +} +#endif + +/* * Swtich transceiver on or off */ static void flexcan_transceiver_switch(const struct flexcan_priv *priv, int on) @@ -212,9 +236,9 @@ static inline void flexcan_chip_enable(struct flexcan_priv *priv) struct flexcan_regs __iomem *regs = priv->base; u32 reg; - reg = readl(®s->mcr); + reg = flexcan_read(®s->mcr); reg &= ~FLEXCAN_MCR_MDIS; - writel(reg, ®s->mcr); + flexcan_write(reg, ®s->mcr); udelay(10); } @@ -224,9 +248,9 @@ static inline void flexcan_chip_disable(struct flexcan_priv *priv) struct flexcan_regs __iomem *regs = priv->base; u32 reg; - reg = readl(®s->mcr); + reg = flexcan_read(®s->mcr); reg |= FLEXCAN_MCR_MDIS; - writel(reg, ®s->mcr); + flexcan_write(reg, ®s->mcr); } static int flexcan_get_berr_counter(const struct net_device *dev, @@ -234,7 +258,7 @@ static int flexcan_get_berr_counter(const struct net_device *dev, { const struct flexcan_priv *priv = netdev_priv(dev); struct flexcan_regs __iomem *regs = priv->base; - u32 reg = readl(®s->ecr); + u32 reg = flexcan_read(®s->ecr); bec->txerr = (reg >> 0) & 0xff; bec->rxerr = (reg >> 8) & 0xff; @@ -268,15 +292,15 @@ static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev) if (cf->can_dlc > 0) { u32 data = be32_to_cpup((__be32 *)&cf->data[0]); - writel(data, ®s->cantxfg[FLEXCAN_TX_BUF_ID].data[0]); + flexcan_write(data, ®s->cantxfg[FLEXCAN_TX_BUF_ID].data[0]); } if (cf->can_dlc > 3) { u32 data = be32_to_cpup((__be32 *)&cf->data[4]); - writel(data, ®s->cantxfg[FLEXCAN_TX_BUF_ID].data[1]); + flexcan_write(data, ®s->cantxfg[FLEXCAN_TX_BUF_ID].data[1]); } - writel(can_id, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_id); - writel(ctrl, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl); + flexcan_write(can_id, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_id); + flexcan_write(ctrl, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl); kfree_skb(skb); @@ -464,8 +488,8 @@ static void flexcan_read_fifo(const struct net_device *dev, struct flexcan_mb __iomem *mb = ®s->cantxfg[0]; u32 reg_ctrl, reg_id; - reg_ctrl = readl(&mb->can_ctrl); - reg_id = readl(&mb->can_id); + reg_ctrl = flexcan_read(&mb->can_ctrl); + reg_id = flexcan_read(&mb->can_id); if (reg_ctrl & FLEXCAN_MB_CNT_IDE) cf->can_id = ((reg_id >> 0) & CAN_EFF_MASK) | CAN_EFF_FLAG; else @@ -475,12 +499,12 @@ static void flexcan_read_fifo(const struct net_device *dev, cf->can_id |= CAN_RTR_FLAG; cf->can_dlc = get_can_dlc((reg_ctrl >> 16) & 0xf); - *(__be32 *)(cf->data + 0) = cpu_to_be32(readl(&mb->data[0])); - *(__be32 *)(cf->data + 4) = cpu_to_be32(readl(&mb->data[1])); + *(__be32 *)(cf->data + 0) = cpu_to_be32(flexcan_read(&mb->data[0])); + *(__be32 *)(cf->data + 4) = cpu_to_be32(flexcan_read(&mb->data[1])); /* mark as read */ - writel(FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, ®s->iflag1); - readl(®s->timer); + flexcan_write(FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, ®s->iflag1); + flexcan_read(®s->timer); } static int flexcan_read_frame(struct net_device *dev) @@ -516,17 +540,17 @@ static int flexcan_poll(struct napi_struct *napi, int quota) * The error bits are cleared on read, * use saved value from irq handler. */ - reg_esr = readl(®s->esr) | priv->reg_esr; + reg_esr = flexcan_read(®s->esr) | priv->reg_esr; /* handle state changes */ work_done += flexcan_poll_state(dev, reg_esr); /* handle RX-FIFO */ - reg_iflag1 = readl(®s->iflag1); + reg_iflag1 = flexcan_read(®s->iflag1); while (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE && work_done < quota) { work_done += flexcan_read_frame(dev); - reg_iflag1 = readl(®s->iflag1); + reg_iflag1 = flexcan_read(®s->iflag1); } /* report bus errors */ @@ -536,8 +560,8 @@ static int flexcan_poll(struct napi_struct *napi, int quota) if (work_done < quota) { napi_complete(napi); /* enable IRQs */ - writel(FLEXCAN_IFLAG_DEFAULT, ®s->imask1); - writel(priv->reg_ctrl_default, ®s->ctrl); + flexcan_write(FLEXCAN_IFLAG_DEFAULT, ®s->imask1); + flexcan_write(priv->reg_ctrl_default, ®s->ctrl); } return work_done; @@ -551,9 +575,9 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) struct flexcan_regs __iomem *regs = priv->base; u32 reg_iflag1, reg_esr; - reg_iflag1 = readl(®s->iflag1); - reg_esr = readl(®s->esr); - writel(FLEXCAN_ESR_ERR_INT, ®s->esr); /* ACK err IRQ */ + reg_iflag1 = flexcan_read(®s->iflag1); + reg_esr = flexcan_read(®s->esr); + flexcan_write(FLEXCAN_ESR_ERR_INT, ®s->esr); /* ACK err IRQ */ /* * schedule NAPI in case of: @@ -569,16 +593,16 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) * save them for later use. */ priv->reg_esr = reg_esr & FLEXCAN_ESR_ERR_BUS; - writel(FLEXCAN_IFLAG_DEFAULT & ~FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, - ®s->imask1); - writel(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL, + flexcan_write(FLEXCAN_IFLAG_DEFAULT & + ~FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, ®s->imask1); + flexcan_write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL, ®s->ctrl); napi_schedule(&priv->napi); } /* FIFO overflow */ if (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_OVERFLOW) { - writel(FLEXCAN_IFLAG_RX_FIFO_OVERFLOW, ®s->iflag1); + flexcan_write(FLEXCAN_IFLAG_RX_FIFO_OVERFLOW, ®s->iflag1); dev->stats.rx_over_errors++; dev->stats.rx_errors++; } @@ -587,7 +611,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) if (reg_iflag1 & (1 << FLEXCAN_TX_BUF_ID)) { /* tx_bytes is incremented in flexcan_start_xmit */ stats->tx_packets++; - writel((1 << FLEXCAN_TX_BUF_ID), ®s->iflag1); + flexcan_write((1 << FLEXCAN_TX_BUF_ID), ®s->iflag1); netif_wake_queue(dev); } @@ -601,7 +625,7 @@ static void flexcan_set_bittiming(struct net_device *dev) struct flexcan_regs __iomem *regs = priv->base; u32 reg; - reg = readl(®s->ctrl); + reg = flexcan_read(®s->ctrl); reg &= ~(FLEXCAN_CTRL_PRESDIV(0xff) | FLEXCAN_CTRL_RJW(0x3) | FLEXCAN_CTRL_PSEG1(0x7) | @@ -625,11 +649,11 @@ static void flexcan_set_bittiming(struct net_device *dev) reg |= FLEXCAN_CTRL_SMP; dev_info(dev->dev.parent, "writing ctrl=0x%08x\n", reg); - writel(reg, ®s->ctrl); + flexcan_write(reg, ®s->ctrl); /* print chip status */ dev_dbg(dev->dev.parent, "%s: mcr=0x%08x ctrl=0x%08x\n", __func__, - readl(®s->mcr), readl(®s->ctrl)); + flexcan_read(®s->mcr), flexcan_read(®s->ctrl)); } /* @@ -650,10 +674,10 @@ static int flexcan_chip_start(struct net_device *dev) flexcan_chip_enable(priv); /* soft reset */ - writel(FLEXCAN_MCR_SOFTRST, ®s->mcr); + flexcan_write(FLEXCAN_MCR_SOFTRST, ®s->mcr); udelay(10); - reg_mcr = readl(®s->mcr); + reg_mcr = flexcan_read(®s->mcr); if (reg_mcr & FLEXCAN_MCR_SOFTRST) { dev_err(dev->dev.parent, "Failed to softreset can module (mcr=0x%08x)\n", @@ -675,12 +699,12 @@ static int flexcan_chip_start(struct net_device *dev) * choose format C * */ - reg_mcr = readl(®s->mcr); + reg_mcr = flexcan_read(®s->mcr); reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT | FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN | FLEXCAN_MCR_IDAM_C; dev_dbg(dev->dev.parent, "%s: writing mcr=0x%08x", __func__, reg_mcr); - writel(reg_mcr, ®s->mcr); + flexcan_write(reg_mcr, ®s->mcr); /* * CTRL @@ -698,7 +722,7 @@ static int flexcan_chip_start(struct net_device *dev) * (FLEXCAN_CTRL_ERR_MSK), too. Otherwise we don't get any * warning or bus passive interrupts. */ - reg_ctrl = readl(®s->ctrl); + reg_ctrl = flexcan_read(®s->ctrl); reg_ctrl &= ~FLEXCAN_CTRL_TSYN; reg_ctrl |= FLEXCAN_CTRL_BOFF_REC | FLEXCAN_CTRL_LBUF | FLEXCAN_CTRL_ERR_STATE | FLEXCAN_CTRL_ERR_MSK; @@ -706,38 +730,39 @@ static int flexcan_chip_start(struct net_device *dev) /* save for later use */ priv->reg_ctrl_default = reg_ctrl; dev_dbg(dev->dev.parent, "%s: writing ctrl=0x%08x", __func__, reg_ctrl); - writel(reg_ctrl, ®s->ctrl); + flexcan_write(reg_ctrl, ®s->ctrl); for (i = 0; i < ARRAY_SIZE(regs->cantxfg); i++) { - writel(0, ®s->cantxfg[i].can_ctrl); - writel(0, ®s->cantxfg[i].can_id); - writel(0, ®s->cantxfg[i].data[0]); - writel(0, ®s->cantxfg[i].data[1]); + flexcan_write(0, ®s->cantxfg[i].can_ctrl); + flexcan_write(0, ®s->cantxfg[i].can_id); + flexcan_write(0, ®s->cantxfg[i].data[0]); + flexcan_write(0, ®s->cantxfg[i].data[1]); /* put MB into rx queue */ - writel(FLEXCAN_MB_CNT_CODE(0x4), ®s->cantxfg[i].can_ctrl); + flexcan_write(FLEXCAN_MB_CNT_CODE(0x4), + ®s->cantxfg[i].can_ctrl); } /* acceptance mask/acceptance code (accept everything) */ - writel(0x0, ®s->rxgmask); - writel(0x0, ®s->rx14mask); - writel(0x0, ®s->rx15mask); + flexcan_write(0x0, ®s->rxgmask); + flexcan_write(0x0, ®s->rx14mask); + flexcan_write(0x0, ®s->rx15mask); flexcan_transceiver_switch(priv, 1); /* synchronize with the can bus */ - reg_mcr = readl(®s->mcr); + reg_mcr = flexcan_read(®s->mcr); reg_mcr &= ~FLEXCAN_MCR_HALT; - writel(reg_mcr, ®s->mcr); + flexcan_write(reg_mcr, ®s->mcr); priv->can.state = CAN_STATE_ERROR_ACTIVE; /* enable FIFO interrupts */ - writel(FLEXCAN_IFLAG_DEFAULT, ®s->imask1); + flexcan_write(FLEXCAN_IFLAG_DEFAULT, ®s->imask1); /* print chip status */ dev_dbg(dev->dev.parent, "%s: reading mcr=0x%08x ctrl=0x%08x\n", - __func__, readl(®s->mcr), readl(®s->ctrl)); + __func__, flexcan_read(®s->mcr), flexcan_read(®s->ctrl)); return 0; @@ -759,12 +784,12 @@ static void flexcan_chip_stop(struct net_device *dev) u32 reg; /* Disable all interrupts */ - writel(0, ®s->imask1); + flexcan_write(0, ®s->imask1); /* Disable + halt module */ - reg = readl(®s->mcr); + reg = flexcan_read(®s->mcr); reg |= FLEXCAN_MCR_MDIS | FLEXCAN_MCR_HALT; - writel(reg, ®s->mcr); + flexcan_write(reg, ®s->mcr); flexcan_transceiver_switch(priv, 0); priv->can.state = CAN_STATE_STOPPED; @@ -856,24 +881,24 @@ static int __devinit register_flexcandev(struct net_device *dev) /* select "bus clock", chip must be disabled */ flexcan_chip_disable(priv); - reg = readl(®s->ctrl); + reg = flexcan_read(®s->ctrl); reg |= FLEXCAN_CTRL_CLK_SRC; - writel(reg, ®s->ctrl); + flexcan_write(reg, ®s->ctrl); flexcan_chip_enable(priv); /* set freeze, halt and activate FIFO, restrict register access */ - reg = readl(®s->mcr); + reg = flexcan_read(®s->mcr); reg |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT | FLEXCAN_MCR_FEN | FLEXCAN_MCR_SUPV; - writel(reg, ®s->mcr); + flexcan_write(reg, ®s->mcr); /* * Currently we only support newer versions of this core * featuring a RX FIFO. Older cores found on some Coldfire * derivates are not yet supported. */ - reg = readl(®s->mcr); + reg = flexcan_read(®s->mcr); if (!(reg & FLEXCAN_MCR_FEN)) { dev_err(dev->dev.parent, "Could not enable RX FIFO, unsupported core\n"); @@ -901,16 +926,29 @@ static int __devinit flexcan_probe(struct platform_device *pdev) struct net_device *dev; struct flexcan_priv *priv; struct resource *mem; - struct clk *clk; + struct clk *clk = NULL; void __iomem *base; resource_size_t mem_size; int err, irq; + u32 clock_freq = 0; + + if (pdev->dev.of_node) { + const u32 *clock_freq_p; - clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(clk)) { - dev_err(&pdev->dev, "no clock defined\n"); - err = PTR_ERR(clk); - goto failed_clock; + clock_freq_p = of_get_property(pdev->dev.of_node, + "clock-frequency", NULL); + if (clock_freq_p) + clock_freq = *clock_freq_p; + } + + if (!clock_freq) { + clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(clk)) { + dev_err(&pdev->dev, "no clock defined\n"); + err = PTR_ERR(clk); + goto failed_clock; + } + clock_freq = clk_get_rate(clk); } mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -943,7 +981,7 @@ static int __devinit flexcan_probe(struct platform_device *pdev) dev->flags |= IFF_ECHO; /* we support local echo in hardware */ priv = netdev_priv(dev); - priv->can.clock.freq = clk_get_rate(clk); + priv->can.clock.freq = clock_freq; priv->can.bittiming_const = &flexcan_bittiming_const; priv->can.do_set_mode = flexcan_set_mode; priv->can.do_get_berr_counter = flexcan_get_berr_counter; @@ -978,7 +1016,8 @@ static int __devinit flexcan_probe(struct platform_device *pdev) failed_map: release_mem_region(mem->start, mem_size); failed_get: - clk_put(clk); + if (clk) + clk_put(clk); failed_clock: return err; } @@ -996,15 +1035,27 @@ static int __devexit flexcan_remove(struct platform_device *pdev) mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(mem->start, resource_size(mem)); - clk_put(priv->clk); + if (priv->clk) + clk_put(priv->clk); free_candev(dev); return 0; } +static struct of_device_id flexcan_of_match[] = { + { + .compatible = "fsl,p1010-flexcan", + }, + {}, +}; + static struct platform_driver flexcan_driver = { - .driver.name = DRV_NAME, + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + .of_match_table = flexcan_of_match, + }, .probe = flexcan_probe, .remove = __devexit_p(flexcan_remove), }; diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c index 4cc6f44..ec4a311 100644 --- a/drivers/net/can/mscan/mscan.c +++ b/drivers/net/can/mscan/mscan.c @@ -62,7 +62,7 @@ static enum can_state state_map[] = { static int mscan_set_mode(struct net_device *dev, u8 mode) { struct mscan_priv *priv = netdev_priv(dev); - struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; + struct mscan_regs __iomem *regs = priv->reg_base; int ret = 0; int i; u8 canctl1; @@ -138,7 +138,7 @@ static int mscan_set_mode(struct net_device *dev, u8 mode) static int mscan_start(struct net_device *dev) { struct mscan_priv *priv = netdev_priv(dev); - struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; + struct mscan_regs __iomem *regs = priv->reg_base; u8 canrflg; int err; @@ -178,7 +178,7 @@ static int mscan_restart(struct net_device *dev) struct mscan_priv *priv = netdev_priv(dev); if (priv->type == MSCAN_TYPE_MPC5121) { - struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; + struct mscan_regs __iomem *regs = priv->reg_base; priv->can.state = CAN_STATE_ERROR_ACTIVE; WARN(!(in_8(®s->canmisc) & MSCAN_BOHOLD), @@ -199,7 +199,7 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct can_frame *frame = (struct can_frame *)skb->data; struct mscan_priv *priv = netdev_priv(dev); - struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; + struct mscan_regs __iomem *regs = priv->reg_base; int i, rtr, buf_id; u32 can_id; @@ -307,7 +307,7 @@ static enum can_state check_set_state(struct net_device *dev, u8 canrflg) static void mscan_get_rx_frame(struct net_device *dev, struct can_frame *frame) { struct mscan_priv *priv = netdev_priv(dev); - struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; + struct mscan_regs __iomem *regs = priv->reg_base; u32 can_id; int i; @@ -348,7 +348,7 @@ static void mscan_get_err_frame(struct net_device *dev, struct can_frame *frame, u8 canrflg) { struct mscan_priv *priv = netdev_priv(dev); - struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; + struct mscan_regs __iomem *regs = priv->reg_base; struct net_device_stats *stats = &dev->stats; enum can_state old_state; @@ -411,7 +411,7 @@ static int mscan_rx_poll(struct napi_struct *napi, int quota) { struct mscan_priv *priv = container_of(napi, struct mscan_priv, napi); struct net_device *dev = napi->dev; - struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; + struct mscan_regs __iomem *regs = priv->reg_base; struct net_device_stats *stats = &dev->stats; int npackets = 0; int ret = 1; @@ -458,7 +458,7 @@ static irqreturn_t mscan_isr(int irq, void *dev_id) { struct net_device *dev = (struct net_device *)dev_id; struct mscan_priv *priv = netdev_priv(dev); - struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; + struct mscan_regs __iomem *regs = priv->reg_base; struct net_device_stats *stats = &dev->stats; u8 cantier, cantflg, canrflg; irqreturn_t ret = IRQ_NONE; @@ -542,7 +542,7 @@ static int mscan_do_set_mode(struct net_device *dev, enum can_mode mode) static int mscan_do_set_bittiming(struct net_device *dev) { struct mscan_priv *priv = netdev_priv(dev); - struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; + struct mscan_regs __iomem *regs = priv->reg_base; struct can_bittiming *bt = &priv->can.bittiming; u8 btr0, btr1; @@ -564,7 +564,7 @@ static int mscan_open(struct net_device *dev) { int ret; struct mscan_priv *priv = netdev_priv(dev); - struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; + struct mscan_regs __iomem *regs = priv->reg_base; /* common open */ ret = open_candev(dev); @@ -603,7 +603,7 @@ exit_napi_disable: static int mscan_close(struct net_device *dev) { struct mscan_priv *priv = netdev_priv(dev); - struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; + struct mscan_regs __iomem *regs = priv->reg_base; netif_stop_queue(dev); napi_disable(&priv->napi); @@ -627,7 +627,7 @@ static const struct net_device_ops mscan_netdev_ops = { int register_mscandev(struct net_device *dev, int mscan_clksrc) { struct mscan_priv *priv = netdev_priv(dev); - struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; + struct mscan_regs __iomem *regs = priv->reg_base; u8 ctl1; ctl1 = in_8(®s->canctl1); @@ -664,7 +664,7 @@ int register_mscandev(struct net_device *dev, int mscan_clksrc) void unregister_mscandev(struct net_device *dev) { struct mscan_priv *priv = netdev_priv(dev); - struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; + struct mscan_regs __iomem *regs = priv->reg_base; mscan_set_mode(dev, MSCAN_INIT_MODE); clrbits8(®s->canctl1, MSCAN_CANE); unregister_candev(dev); diff --git a/drivers/net/can/sja1000/Kconfig b/drivers/net/can/sja1000/Kconfig index 6fdc031..fe9e64d 100644 --- a/drivers/net/can/sja1000/Kconfig +++ b/drivers/net/can/sja1000/Kconfig @@ -29,6 +29,13 @@ config CAN_SJA1000_OF_PLATFORM OpenFirmware bindings, e.g. if you have a PowerPC based system you may want to enable this option. +config CAN_EMS_PCMCIA + tristate "EMS CPC-CARD Card" + depends on PCMCIA + ---help--- + This driver is for the one or two channel CPC-CARD cards from + EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de). + config CAN_EMS_PCI tristate "EMS CPC-PCI, CPC-PCIe and CPC-104P Card" depends on PCI @@ -37,6 +44,13 @@ config CAN_EMS_PCI CPC-PCIe and CPC-104P cards from EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de). +config CAN_PEAK_PCI + tristate "PEAK PCAN PCI/PCIe 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). + config CAN_KVASER_PCI tristate "Kvaser PCIcanx and Kvaser PCIcan PCI Cards" depends on PCI diff --git a/drivers/net/can/sja1000/Makefile b/drivers/net/can/sja1000/Makefile index 2c591eb..0604f24 100644 --- a/drivers/net/can/sja1000/Makefile +++ b/drivers/net/can/sja1000/Makefile @@ -6,8 +6,10 @@ obj-$(CONFIG_CAN_SJA1000) += sja1000.o obj-$(CONFIG_CAN_SJA1000_ISA) += sja1000_isa.o obj-$(CONFIG_CAN_SJA1000_PLATFORM) += sja1000_platform.o 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_PCI) += peak_pci.o obj-$(CONFIG_CAN_PLX_PCI) += plx_pci.o obj-$(CONFIG_CAN_TSCAN1) += tscan1.o diff --git a/drivers/net/can/sja1000/ems_pcmcia.c b/drivers/net/can/sja1000/ems_pcmcia.c new file mode 100644 index 0000000..075a545 --- /dev/null +++ b/drivers/net/can/sja1000/ems_pcmcia.c @@ -0,0 +1,331 @@ +/* + * Copyright (C) 2008 Sebastian Haas (initial chardev implementation) + * Copyright (C) 2010 Markus Plessing <plessing@ems-wuensche.com> + * Rework for mainline by Oliver Hartkopp <socketcan@hartkopp.net> + * + * 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/io.h> +#include <pcmcia/cistpl.h> +#include <pcmcia/ds.h> +#include <linux/can.h> +#include <linux/can/dev.h> +#include "sja1000.h" + +#define DRV_NAME "ems_pcmcia" + +MODULE_AUTHOR("Markus Plessing <plessing@ems-wuensche.com>"); +MODULE_DESCRIPTION("Socket-CAN driver for EMS CPC-CARD cards"); +MODULE_SUPPORTED_DEVICE("EMS CPC-CARD CAN card"); +MODULE_LICENSE("GPL v2"); + +#define EMS_PCMCIA_MAX_CHAN 2 + +struct ems_pcmcia_card { + int channels; + struct pcmcia_device *pcmcia_dev; + struct net_device *net_dev[EMS_PCMCIA_MAX_CHAN]; + void __iomem *base_addr; +}; + +#define EMS_PCMCIA_CAN_CLOCK (16000000 / 2) + +/* + * The board configuration is probably following: + * RX1 is connected to ground. + * TX1 is not connected. + * CLKO is not connected. + * Setting the OCR register to 0xDA is a good idea. + * This means normal output mode , push-pull and the correct polarity. + */ +#define EMS_PCMCIA_OCR (OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL) + +/* + * In the CDR register, you should set CBP to 1. + * You will probably also want to set the clock divider value to 7 + * (meaning direct oscillator output) because the second SJA1000 chip + * is driven by the first one CLKOUT output. + */ +#define EMS_PCMCIA_CDR (CDR_CBP | CDR_CLKOUT_MASK) +#define EMS_PCMCIA_MEM_SIZE 4096 /* Size of the remapped io-memory */ +#define EMS_PCMCIA_CAN_BASE_OFFSET 0x100 /* Offset where controllers starts */ +#define EMS_PCMCIA_CAN_CTRL_SIZE 0x80 /* Memory size for each controller */ + +#define EMS_CMD_RESET 0x00 /* Perform a reset of the card */ +#define EMS_CMD_MAP 0x03 /* Map CAN controllers into card' memory */ +#define EMS_CMD_UMAP 0x02 /* Unmap CAN controllers from card' memory */ + +static struct pcmcia_device_id ems_pcmcia_tbl[] = { + PCMCIA_DEVICE_PROD_ID123("EMS_T_W", "CPC-Card", "V2.0", 0xeab1ea23, + 0xa338573f, 0xe4575800), + PCMCIA_DEVICE_NULL, +}; + +MODULE_DEVICE_TABLE(pcmcia, ems_pcmcia_tbl); + +static u8 ems_pcmcia_read_reg(const struct sja1000_priv *priv, int port) +{ + return readb(priv->reg_base + port); +} + +static void ems_pcmcia_write_reg(const struct sja1000_priv *priv, int port, + u8 val) +{ + writeb(val, priv->reg_base + port); +} + +static irqreturn_t ems_pcmcia_interrupt(int irq, void *dev_id) +{ + struct ems_pcmcia_card *card = dev_id; + struct net_device *dev; + irqreturn_t retval = IRQ_NONE; + int i, again; + + /* Card not present */ + if (readw(card->base_addr) != 0xAA55) + return IRQ_HANDLED; + + do { + again = 0; + + /* Check interrupt for each channel */ + for (i = 0; i < card->channels; i++) { + dev = card->net_dev[i]; + if (!dev) + continue; + + if (sja1000_interrupt(irq, dev) == IRQ_HANDLED) + again = 1; + } + /* At least one channel handled the interrupt */ + if (again) + retval = IRQ_HANDLED; + + } while (again); + + return retval; +} + +/* + * Check if a CAN controller is present at the specified location + * by trying to set 'em into the PeliCAN mode + */ +static inline int ems_pcmcia_check_chan(struct sja1000_priv *priv) +{ + /* Make sure SJA1000 is in reset mode */ + ems_pcmcia_write_reg(priv, REG_MOD, 1); + ems_pcmcia_write_reg(priv, REG_CDR, CDR_PELICAN); + + /* read reset-values */ + if (ems_pcmcia_read_reg(priv, REG_CDR) == CDR_PELICAN) + return 1; + + return 0; +} + +static void ems_pcmcia_del_card(struct pcmcia_device *pdev) +{ + struct ems_pcmcia_card *card = pdev->priv; + struct net_device *dev; + int i; + + free_irq(pdev->irq, card); + + for (i = 0; i < card->channels; i++) { + dev = card->net_dev[i]; + if (!dev) + continue; + + printk(KERN_INFO "%s: removing %s on channel #%d\n", + DRV_NAME, dev->name, i); + unregister_sja1000dev(dev); + free_sja1000dev(dev); + } + + writeb(EMS_CMD_UMAP, card->base_addr); + iounmap(card->base_addr); + kfree(card); + + pdev->priv = NULL; +} + +/* + * Probe PCI device for EMS CAN signature and register each available + * CAN channel to SJA1000 Socket-CAN subsystem. + */ +static int __devinit ems_pcmcia_add_card(struct pcmcia_device *pdev, + unsigned long base) +{ + struct sja1000_priv *priv; + struct net_device *dev; + struct ems_pcmcia_card *card; + int err, i; + + /* Allocating card structures to hold addresses, ... */ + card = kzalloc(sizeof(struct ems_pcmcia_card), GFP_KERNEL); + if (!card) + return -ENOMEM; + + pdev->priv = card; + card->channels = 0; + + card->base_addr = ioremap(base, EMS_PCMCIA_MEM_SIZE); + if (!card->base_addr) { + err = -ENOMEM; + goto failure_cleanup; + } + + /* Check for unique EMS CAN signature */ + if (readw(card->base_addr) != 0xAA55) { + err = -ENODEV; + goto failure_cleanup; + } + + /* Request board reset */ + writeb(EMS_CMD_RESET, card->base_addr); + + /* Make sure CAN controllers are mapped into card's memory space */ + writeb(EMS_CMD_MAP, card->base_addr); + + /* Detect available channels */ + for (i = 0; i < EMS_PCMCIA_MAX_CHAN; i++) { + dev = alloc_sja1000dev(0); + if (!dev) { + err = -ENOMEM; + goto failure_cleanup; + } + + card->net_dev[i] = dev; + priv = netdev_priv(dev); + priv->priv = card; + SET_NETDEV_DEV(dev, &pdev->dev); + + priv->irq_flags = IRQF_SHARED; + dev->irq = pdev->irq; + priv->reg_base = card->base_addr + EMS_PCMCIA_CAN_BASE_OFFSET + + (i * EMS_PCMCIA_CAN_CTRL_SIZE); + + /* Check if channel is present */ + if (ems_pcmcia_check_chan(priv)) { + priv->read_reg = ems_pcmcia_read_reg; + priv->write_reg = ems_pcmcia_write_reg; + priv->can.clock.freq = EMS_PCMCIA_CAN_CLOCK; + priv->ocr = EMS_PCMCIA_OCR; + priv->cdr = EMS_PCMCIA_CDR; + priv->flags |= SJA1000_CUSTOM_IRQ_HANDLER; + + /* Register SJA1000 device */ + err = register_sja1000dev(dev); + if (err) { + free_sja1000dev(dev); + goto failure_cleanup; + } + + card->channels++; + + printk(KERN_INFO "%s: registered %s on channel " + "#%d at 0x%p, irq %d\n", DRV_NAME, dev->name, + i, priv->reg_base, dev->irq); + } else + free_sja1000dev(dev); + } + + err = request_irq(dev->irq, &ems_pcmcia_interrupt, IRQF_SHARED, + DRV_NAME, card); + if (!err) + return 0; + +failure_cleanup: + ems_pcmcia_del_card(pdev); + return err; +} + +/* + * Setup PCMCIA socket and probe for EMS CPC-CARD + */ +static int __devinit ems_pcmcia_probe(struct pcmcia_device *dev) +{ + int csval; + + /* General socket configuration */ + dev->config_flags |= CONF_ENABLE_IRQ; + dev->config_index = 1; + dev->config_regs = PRESENT_OPTION; + + /* The io structure describes IO port mapping */ + dev->resource[0]->end = 16; + dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; + dev->resource[1]->end = 16; + dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_16; + dev->io_lines = 5; + + /* Allocate a memory window */ + dev->resource[2]->flags = + (WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE); + dev->resource[2]->start = dev->resource[2]->end = 0; + + csval = pcmcia_request_window(dev, dev->resource[2], 0); + if (csval) { + dev_err(&dev->dev, "pcmcia_request_window failed (err=%d)\n", + csval); + return 0; + } + + csval = pcmcia_map_mem_page(dev, dev->resource[2], dev->config_base); + if (csval) { + dev_err(&dev->dev, "pcmcia_map_mem_page failed (err=%d)\n", + csval); + return 0; + } + + csval = pcmcia_enable_device(dev); + if (csval) { + dev_err(&dev->dev, "pcmcia_enable_device failed (err=%d)\n", + csval); + return 0; + } + + ems_pcmcia_add_card(dev, dev->resource[2]->start); + return 0; +} + +/* + * Release claimed resources + */ +static void ems_pcmcia_remove(struct pcmcia_device *dev) +{ + ems_pcmcia_del_card(dev); + pcmcia_disable_device(dev); +} + +static struct pcmcia_driver ems_pcmcia_driver = { + .name = DRV_NAME, + .probe = ems_pcmcia_probe, + .remove = ems_pcmcia_remove, + .id_table = ems_pcmcia_tbl, +}; + +static int __init ems_pcmcia_init(void) +{ + return pcmcia_register_driver(&ems_pcmcia_driver); +} +module_init(ems_pcmcia_init); + +static void __exit ems_pcmcia_exit(void) +{ + pcmcia_unregister_driver(&ems_pcmcia_driver); +} +module_exit(ems_pcmcia_exit); diff --git a/drivers/net/can/sja1000/peak_pci.c b/drivers/net/can/sja1000/peak_pci.c new file mode 100644 index 0000000..905bce0 --- /dev/null +++ b/drivers/net/can/sja1000/peak_pci.c @@ -0,0 +1,291 @@ +/* + * Copyright (C) 2007, 2011 Wolfgang Grandegger <wg@grandegger.com> + * + * Derived from the PCAN project file driver/src/pcan_pci.c: + * + * Copyright (C) 2001-2006 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. + * + * 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/interrupt.h> +#include <linux/netdevice.h> +#include <linux/delay.h> +#include <linux/pci.h> +#include <linux/io.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_LICENSE("GPL v2"); + +#define DRV_NAME "peak_pci" + +struct peak_pci_chan { + void __iomem *cfg_base; /* Common for all channels */ + struct net_device *next_dev; /* Chain of network devices */ + u16 icr_mask; /* Interrupt mask for fast ack */ +}; + +#define PEAK_PCI_CAN_CLOCK (16000000 / 2) + +#define PEAK_PCI_CDR (CDR_CBP | CDR_CLKOUT_MASK) +#define PEAK_PCI_OCR OCR_TX0_PUSHPULL + +/* + * Important PITA registers + */ +#define PITA_ICR 0x00 /* Interrupt control register */ +#define PITA_GPIOICR 0x18 /* GPIO interface control register */ +#define PITA_MISC 0x1C /* Miscellaneous register */ + +#define PEAK_PCI_CFG_SIZE 0x1000 /* Size of the config PCI bar */ +#define PEAK_PCI_CHAN_SIZE 0x0400 /* Size used by the channel */ + +#define PEAK_PCI_VENDOR_ID 0x001C /* The PCI device and vendor IDs */ +#define PEAK_PCI_DEVICE_ID 0x0001 /* for PCI/PCIe slot cards */ + +static const u16 peak_pci_icr_masks[] = {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,}, + {0,} +}; + +MODULE_DEVICE_TABLE(pci, peak_pci_tbl); + +static u8 peak_pci_read_reg(const struct sja1000_priv *priv, int port) +{ + return readb(priv->reg_base + (port << 2)); +} + +static void peak_pci_write_reg(const struct sja1000_priv *priv, + int port, u8 val) +{ + writeb(val, priv->reg_base + (port << 2)); +} + +static void peak_pci_post_irq(const struct sja1000_priv *priv) +{ + struct peak_pci_chan *chan = priv->priv; + u16 icr; + + /* Select and clear in PITA stored interrupt */ + icr = readw(chan->cfg_base + PITA_ICR); + if (icr & chan->icr_mask) + writew(chan->icr_mask, chan->cfg_base + PITA_ICR); +} + +static int __devinit peak_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct sja1000_priv *priv; + struct peak_pci_chan *chan; + struct net_device *dev, *dev0 = NULL; + void __iomem *cfg_base, *reg_base; + u16 sub_sys_id, icr; + int i, err, channels; + + err = pci_enable_device(pdev); + if (err) + return err; + + err = pci_request_regions(pdev, DRV_NAME); + if (err) + goto failure_disable_pci; + + err = pci_read_config_word(pdev, 0x2e, &sub_sys_id); + if (err) + goto failure_release_regions; + + dev_dbg(&pdev->dev, "probing device %04x:%04x:%04x\n", + pdev->vendor, pdev->device, sub_sys_id); + + err = pci_write_config_word(pdev, 0x44, 0); + if (err) + goto failure_release_regions; + + if (sub_sys_id >= 12) + channels = 4; + else if (sub_sys_id >= 10) + channels = 3; + else if (sub_sys_id >= 4) + channels = 2; + else + channels = 1; + + cfg_base = pci_iomap(pdev, 0, PEAK_PCI_CFG_SIZE); + if (!cfg_base) { + dev_err(&pdev->dev, "failed to map PCI resource #0\n"); + goto failure_release_regions; + } + + reg_base = pci_iomap(pdev, 1, PEAK_PCI_CHAN_SIZE * channels); + if (!reg_base) { + dev_err(&pdev->dev, "failed to map PCI resource #1\n"); + goto failure_unmap_cfg_base; + } + + /* Set GPIO control register */ + writew(0x0005, cfg_base + PITA_GPIOICR + 2); + /* Enable all channels of this card */ + writeb(0x00, cfg_base + PITA_GPIOICR); + /* Toggle reset */ + writeb(0x05, cfg_base + PITA_MISC + 3); + mdelay(5); + /* Leave parport mux mode */ + writeb(0x04, cfg_base + PITA_MISC + 3); + + icr = readw(cfg_base + PITA_ICR + 2); + + for (i = 0; i < channels; i++) { + dev = alloc_sja1000dev(sizeof(struct peak_pci_chan)); + if (!dev) { + err = -ENOMEM; + goto failure_remove_channels; + } + + priv = netdev_priv(dev); + chan = priv->priv; + + chan->cfg_base = cfg_base; + priv->reg_base = reg_base + i * PEAK_PCI_CHAN_SIZE; + + priv->read_reg = peak_pci_read_reg; + priv->write_reg = peak_pci_write_reg; + priv->post_irq = peak_pci_post_irq; + + priv->can.clock.freq = PEAK_PCI_CAN_CLOCK; + priv->ocr = PEAK_PCI_OCR; + priv->cdr = PEAK_PCI_CDR; + /* Neither a slave nor a single device distributes the clock */ + if (channels == 1 || i > 0) + priv->cdr |= CDR_CLK_OFF; + + /* Setup interrupt handling */ + priv->irq_flags = IRQF_SHARED; + dev->irq = pdev->irq; + + chan->icr_mask = peak_pci_icr_masks[i]; + icr |= chan->icr_mask; + + SET_NETDEV_DEV(dev, &pdev->dev); + + err = register_sja1000dev(dev); + if (err) { + dev_err(&pdev->dev, "failed to register device\n"); + free_sja1000dev(dev); + goto failure_remove_channels; + } + + /* Create chain of SJA1000 devices */ + if (i == 0) + dev0 = dev; + else + chan->next_dev = 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); + } + + pci_set_drvdata(pdev, dev0); + + /* Enable interrupts */ + writew(icr, cfg_base + PITA_ICR + 2); + + return 0; + +failure_remove_channels: + /* Disable interrupts */ + writew(0x0, cfg_base + PITA_ICR + 2); + + for (dev = dev0; dev; dev = chan->next_dev) { + unregister_sja1000dev(dev); + free_sja1000dev(dev); + priv = netdev_priv(dev); + chan = priv->priv; + dev = chan->next_dev; + } + + pci_iounmap(pdev, reg_base); + +failure_unmap_cfg_base: + pci_iounmap(pdev, cfg_base); + +failure_release_regions: + pci_release_regions(pdev); + +failure_disable_pci: + pci_disable_device(pdev); + + return err; +} + +static void __devexit peak_pci_remove(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); /* First device */ + struct sja1000_priv *priv = netdev_priv(dev); + struct peak_pci_chan *chan = priv->priv; + void __iomem *cfg_base = chan->cfg_base; + void __iomem *reg_base = priv->reg_base; + + /* Disable interrupts */ + writew(0x0, cfg_base + PITA_ICR + 2); + + /* Loop over all registered devices */ + while (1) { + dev_info(&pdev->dev, "removing device %s\n", dev->name); + unregister_sja1000dev(dev); + free_sja1000dev(dev); + dev = chan->next_dev; + if (!dev) + break; + priv = netdev_priv(dev); + chan = priv->priv; + } + + pci_iounmap(pdev, reg_base); + pci_iounmap(pdev, cfg_base); + pci_release_regions(pdev); + pci_disable_device(pdev); + + pci_set_drvdata(pdev, NULL); +} + +static struct pci_driver peak_pci_driver = { + .name = DRV_NAME, + .id_table = peak_pci_tbl, + .probe = peak_pci_probe, + .remove = __devexit_p(peak_pci_remove), +}; + +static int __init peak_pci_init(void) +{ + return pci_register_driver(&peak_pci_driver); +} +module_init(peak_pci_init); + +static void __exit peak_pci_exit(void) +{ + pci_unregister_driver(&peak_pci_driver); +} +module_exit(peak_pci_exit); diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c index f501bba..04a3f1b 100644 --- a/drivers/net/can/sja1000/sja1000.c +++ b/drivers/net/can/sja1000/sja1000.c @@ -40,8 +40,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. * - * Send feedback to <socketcan-users@lists.berlios.de> - * */ #include <linux/module.h> diff --git a/drivers/net/can/sja1000/sja1000.h b/drivers/net/can/sja1000/sja1000.h index 78bd4ec..23fff06 100644 --- a/drivers/net/can/sja1000/sja1000.h +++ b/drivers/net/can/sja1000/sja1000.h @@ -40,8 +40,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. * - * Send feedback to <socketcan-users@lists.berlios.de> - * */ #ifndef SJA1000_DEV_H diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c index 4b70b7e..a979b00 100644 --- a/drivers/net/can/slcan.c +++ b/drivers/net/can/slcan.c @@ -35,8 +35,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. * - * Send feedback to <socketcan-users@lists.berlios.de> - * */ #include <linux/module.h> diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c index a30b8f4..f93e2d6 100644 --- a/drivers/net/can/vcan.c +++ b/drivers/net/can/vcan.c @@ -37,8 +37,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. * - * Send feedback to <socketcan-users@lists.berlios.de> - * */ #include <linux/module.h> |