From 665d7eb8877c6bb777039efb22f894740be10bcb Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 15 Aug 2011 12:45:08 +0200 Subject: net/can/mscan: add __iomem annotations This patch fixes the following sparse warning by adding the missing __iomem annotation. drivers/net/can/mscan/mscan.c:73:32: warning: incorrect type in argument 1 (different address spaces) drivers/net/can/mscan/mscan.c:73:32: expected unsigned char volatile [noderef] [usertype] *addr drivers/net/can/mscan/mscan.c:73:32: got unsigned char * Signed-off-by: Marc Kleine-Budde --- drivers/net/can/mscan/mscan.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/net/can') diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c index 92feac68b66e..ac42f5da91b5 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; @@ -305,7 +305,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; @@ -343,7 +343,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; @@ -406,7 +406,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; @@ -453,7 +453,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; @@ -537,7 +537,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; @@ -559,7 +559,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); @@ -598,7 +598,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); @@ -622,7 +622,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); @@ -659,7 +659,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); -- cgit v1.2.3 From 12732c308340ad786d540b3a85f7b164189f2108 Mon Sep 17 00:00:00 2001 From: "holt@sgi.com" Date: Tue, 16 Aug 2011 17:32:19 +0000 Subject: flexcan: Remove #include powerpc does not have a mach-####/clock.h. When testing, I found neither arm nor powerpc needed the mach/clock.h at all so I removed it. Signed-off-by: Robin Holt Acked-by: Marc Kleine-Budde Acked-by: Wolfgang Grandegger Cc: U Bhaskar-B22300 Cc: socketcan-core@lists.berlios.de Cc: netdev@vger.kernel.org Cc: PPC list Signed-off-by: David S. Miller --- drivers/net/can/flexcan.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net/can') diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 17678117ed69..586b2cdcee90 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -35,8 +35,6 @@ #include #include -#include - #define DRV_NAME "flexcan" /* 8 for RX fifo and 2 error handling */ -- cgit v1.2.3 From 61e271ee64f1da6f69e56419ecf2ca7330884564 Mon Sep 17 00:00:00 2001 From: "holt@sgi.com" Date: Tue, 16 Aug 2011 17:32:20 +0000 Subject: flexcan: Abstract off read/write for big/little endian. Make flexcan driver handle register reads in the appropriate endianess. This was a basic search and replace and then define some inlines. Signed-off-by: Robin Holt Acked-by: Marc Kleine-Budde Acked-by: Wolfgang Grandegger Cc: U Bhaskar-B22300 Cc: socketcan-core@lists.berlios.de Cc: netdev@vger.kernel.org Cc: PPC list Signed-off-by: David S. Miller --- drivers/net/can/flexcan.c | 140 +++++++++++++++++++++++++++------------------- 1 file changed, 83 insertions(+), 57 deletions(-) (limited to 'drivers/net/can') diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 586b2cdcee90..68cbe5243493 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -189,6 +189,31 @@ static struct can_bittiming_const flexcan_bittiming_const = { .brp_inc = 1, }; +/* + * 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 */ @@ -210,9 +235,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); } @@ -222,9 +247,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, @@ -232,7 +257,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; @@ -266,15 +291,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); @@ -462,8 +487,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 @@ -473,12 +498,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) @@ -514,17 +539,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 */ @@ -534,8 +559,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; @@ -549,9 +574,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: @@ -567,16 +592,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++; } @@ -585,7 +610,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); } @@ -599,7 +624,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) | @@ -623,11 +648,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)); } /* @@ -648,10 +673,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", @@ -673,12 +698,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 @@ -696,7 +721,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; @@ -704,38 +729,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; @@ -757,12 +783,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; @@ -854,24 +880,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"); -- cgit v1.2.3 From c8aef4cb788b760331e6df06a5d93389824882b4 Mon Sep 17 00:00:00 2001 From: "holt@sgi.com" Date: Tue, 16 Aug 2011 17:32:22 +0000 Subject: flexcan: Add of_match to platform_device definition. On powerpc, the OpenFirmware devices are not matched without specifying an of_match array. Introduce that array as that is used for matching on the Freescale P1010 processor. Signed-off-by: Robin Holt Acked-by: Marc Kleine-Budde Acked-by: Wolfgang Grandegger Cc: U Bhaskar-B22300 Cc: Grant Likely Cc: socketcan-core@lists.berlios.de Cc: netdev@vger.kernel.org Cc: PPC list Cc: devicetree-discuss@lists.ozlabs.org Signed-off-by: David S. Miller --- drivers/net/can/flexcan.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers/net/can') diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 68cbe5243493..cc1e0a7b554f 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -1027,8 +1027,19 @@ static int __devexit flexcan_remove(struct platform_device *pdev) 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), }; -- cgit v1.2.3 From 97efe9aef1ae8922666d32f28d712745a86859e9 Mon Sep 17 00:00:00 2001 From: "holt@sgi.com" Date: Tue, 16 Aug 2011 17:32:23 +0000 Subject: flexcan: Prefer device tree clock frequency if available. If our CAN device's device tree node has a clock-frequency property, then use that value for the can devices clock frequency. If not, fall back to asking the platform/mach code for the clock frequency associated with the flexcan device. Signed-off-by: Robin Holt Acked-by: Wolfgang Grandegger , Cc: Kumar Gala Cc: Marc Kleine-Budde , Cc: U Bhaskar-B22300 Cc: Scott Wood Cc: Grant Likely Cc: socketcan-core@lists.berlios.de, Cc: netdev@vger.kernel.org, Cc: PPC list Cc: devicetree-discuss@lists.ozlabs.org Signed-off-by: David S. Miller --- drivers/net/can/flexcan.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) (limited to 'drivers/net/can') diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index cc1e0a7b554f..e02337953f41 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #define DRV_NAME "flexcan" @@ -925,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); @@ -967,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; @@ -1002,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; } @@ -1020,7 +1035,8 @@ 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); -- cgit v1.2.3 From 38034518c086fc48232b641cab97396a615864d0 Mon Sep 17 00:00:00 2001 From: Wolfgang Grandegger Date: Mon, 12 Sep 2011 21:16:06 +0000 Subject: can/sja1000: driver for PEAK PCAN PCI/PCIe cards This patch add the peak_pci driver for the PCAN PCI/PCIe cards (1, 2, 3 or 4 channels) from PEAK Systems (http://www.peak-system.com). Signed-off-by: Wolfgang Grandegger Acked-by: Marc Kleine-Budde Tested-by: Oliver Hartkopp Signed-off-by: David S. Miller --- drivers/net/can/sja1000/Kconfig | 7 + drivers/net/can/sja1000/Makefile | 1 + drivers/net/can/sja1000/peak_pci.c | 291 +++++++++++++++++++++++++++++++++++++ 3 files changed, 299 insertions(+) create mode 100644 drivers/net/can/sja1000/peak_pci.c (limited to 'drivers/net/can') diff --git a/drivers/net/can/sja1000/Kconfig b/drivers/net/can/sja1000/Kconfig index 6fdc031daaae..72b637d31c91 100644 --- a/drivers/net/can/sja1000/Kconfig +++ b/drivers/net/can/sja1000/Kconfig @@ -37,6 +37,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 2c591eb321c7..428f5cf30b60 100644 --- a/drivers/net/can/sja1000/Makefile +++ b/drivers/net/can/sja1000/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_CAN_SJA1000_PLATFORM) += sja1000_platform.o obj-$(CONFIG_CAN_SJA1000_OF_PLATFORM) += sja1000_of_platform.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/peak_pci.c b/drivers/net/can/sja1000/peak_pci.c new file mode 100644 index 000000000000..905bce0b3a43 --- /dev/null +++ b/drivers/net/can/sja1000/peak_pci.c @@ -0,0 +1,291 @@ +/* + * Copyright (C) 2007, 2011 Wolfgang Grandegger + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sja1000.h" + +MODULE_AUTHOR("Wolfgang Grandegger "); +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); -- cgit v1.2.3 From fd734c6f25aea4b2b44b045e489aec67b388577e Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Fri, 23 Sep 2011 06:59:48 +0000 Subject: can/sja1000: add driver for EMS PCMCIA card This patch adds the driver for the SJA1000 based PCMCIA card 'CPC-Card' from EMS Dr. Thomas Wuensche (http://www.ems-wuensche.de). Signed-off-by: Oliver Hartkopp Acked-by: Markus Plessing Signed-off-by: David S. Miller --- drivers/net/can/sja1000/Kconfig | 7 + drivers/net/can/sja1000/Makefile | 1 + drivers/net/can/sja1000/ems_pcmcia.c | 331 +++++++++++++++++++++++++++++++++++ 3 files changed, 339 insertions(+) create mode 100644 drivers/net/can/sja1000/ems_pcmcia.c (limited to 'drivers/net/can') diff --git a/drivers/net/can/sja1000/Kconfig b/drivers/net/can/sja1000/Kconfig index 72b637d31c91..fe9e64d476eb 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 diff --git a/drivers/net/can/sja1000/Makefile b/drivers/net/can/sja1000/Makefile index 428f5cf30b60..0604f240c8b1 100644 --- a/drivers/net/can/sja1000/Makefile +++ b/drivers/net/can/sja1000/Makefile @@ -6,6 +6,7 @@ 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 diff --git a/drivers/net/can/sja1000/ems_pcmcia.c b/drivers/net/can/sja1000/ems_pcmcia.c new file mode 100644 index 000000000000..075a5457a190 --- /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 + * Rework for mainline by Oliver Hartkopp + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sja1000.h" + +#define DRV_NAME "ems_pcmcia" + +MODULE_AUTHOR("Markus Plessing "); +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); -- cgit v1.2.3 From 2e1143742789463c00ed5e7f9bf471f2b707b493 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Wed, 28 Sep 2011 02:50:11 +0000 Subject: candev: allow SJW user setting for bittiming calculation This patch adds support for SJW user settings to not set the synchronization jump width (SJW) to 1 in any case when using the in-kernel bittiming calculation. The ip-tool from iproute2 already supports to pass the user defined SJW value. The given SJW value is sanitized with the controller specific sjw_max and the calculated tseg2 value. As the SJW can have values up to 4 providing this value will lead to the maximum possible SJW automatically. A higher SJW allows higher controller oscillator tolerances. Signed-off-by: Oliver Hartkopp Acked-by: Wolfgang Grandegger Signed-off-by: David S. Miller --- drivers/net/can/dev.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers/net/can') diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index 9bf1116e5b5e..25695bde0549 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)); -- cgit v1.2.3 From f861c2b80c45954e1ea04ead24cafcb1806dd536 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 17 Oct 2011 09:32:00 +0000 Subject: can: remove references to berlios mailinglist The BerliOS project, which currently hosts our mailinglist, will close with the end of the year. Now take the chance and remove all occurrences of the mailinglist address from the source files. Signed-off-by: Marc Kleine-Budde Signed-off-by: David S. Miller --- drivers/net/can/at91_can.c | 2 -- drivers/net/can/sja1000/sja1000.c | 2 -- drivers/net/can/sja1000/sja1000.h | 2 -- drivers/net/can/slcan.c | 2 -- drivers/net/can/vcan.c | 2 -- 5 files changed, 10 deletions(-) (limited to 'drivers/net/can') diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index 121ede663e20..044ea0647b04 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 - * * * Your platform definition file should specify something like: * diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c index f501bba1fc6f..04a3f1b756a8 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 - * */ #include diff --git a/drivers/net/can/sja1000/sja1000.h b/drivers/net/can/sja1000/sja1000.h index 78bd4ecac140..23fff06875f5 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 - * */ #ifndef SJA1000_DEV_H diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c index 4b70b7e8bdeb..a979b006f459 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 - * */ #include diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c index a30b8f480f61..f93e2d6fc88c 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 - * */ #include -- cgit v1.2.3