diff options
Diffstat (limited to 'drivers/net/can/mscan/mscan.c')
| -rw-r--r-- | drivers/net/can/mscan/mscan.c | 123 |
1 files changed, 80 insertions, 43 deletions
diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c index 92feac68b66..e0c9be5e2ab 100644 --- a/drivers/net/can/mscan/mscan.c +++ b/drivers/net/can/mscan/mscan.c @@ -16,8 +16,7 @@ * 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 + * along with this program; if not, see <http://www.gnu.org/licenses/>. */ #include <linux/kernel.h> @@ -34,7 +33,7 @@ #include "mscan.h" -static struct can_bittiming_const mscan_bittiming_const = { +static const struct can_bittiming_const mscan_bittiming_const = { .name = "mscan", .tseg1_min = 4, .tseg1_max = 16, @@ -62,7 +61,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; @@ -95,9 +94,9 @@ static int mscan_set_mode(struct net_device *dev, u8 mode) * any, at once. */ if (i >= MSCAN_SET_MODE_RETRIES) - dev_dbg(dev->dev.parent, - "device failed to enter sleep mode. " - "We proceed anyhow.\n"); + netdev_dbg(dev, + "device failed to enter sleep mode. " + "We proceed anyhow.\n"); else priv->can.state = CAN_STATE_SLEEPING; } @@ -138,7 +137,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 +177,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 +198,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; @@ -213,7 +212,7 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev) switch (hweight8(i)) { case 0: netif_stop_queue(dev); - dev_err(dev->dev.parent, "Tx Ring full when queue awake!\n"); + netdev_err(dev, "Tx Ring full when queue awake!\n"); return NETDEV_TX_BUSY; case 1: /* @@ -261,11 +260,13 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev) void __iomem *data = ®s->tx.dsr1_0; u16 *payload = (u16 *)frame->data; - /* It is safe to write into dsr[dlc+1] */ - for (i = 0; i < (frame->can_dlc + 1) / 2; i++) { + for (i = 0; i < frame->can_dlc / 2; i++) { out_be16(data, *payload++); data += 2 + _MSCAN_RESERVED_DSR_SIZE; } + /* write remaining byte if necessary */ + if (frame->can_dlc & 1) + out_8(data, frame->data[frame->can_dlc - 1]); } out_8(®s->tx.dlr, frame->can_dlc); @@ -305,7 +306,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; @@ -330,10 +331,13 @@ static void mscan_get_rx_frame(struct net_device *dev, struct can_frame *frame) void __iomem *data = ®s->rx.dsr1_0; u16 *payload = (u16 *)frame->data; - for (i = 0; i < (frame->can_dlc + 1) / 2; i++) { + for (i = 0; i < frame->can_dlc / 2; i++) { *payload++ = in_be16(data); data += 2 + _MSCAN_RESERVED_DSR_SIZE; } + /* read remaining byte if necessary */ + if (frame->can_dlc & 1) + frame->data[frame->can_dlc - 1] = in_8(data); } out_8(®s->canrflg, MSCAN_RXF); @@ -343,11 +347,11 @@ 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; - dev_dbg(dev->dev.parent, "error interrupt (canrflg=%#x)\n", canrflg); + netdev_dbg(dev, "error interrupt (canrflg=%#x)\n", canrflg); frame->can_id = CAN_ERR_FLAG; if (canrflg & MSCAN_OVRIF) { @@ -406,7 +410,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; @@ -422,7 +426,7 @@ static int mscan_rx_poll(struct napi_struct *napi, int quota) skb = alloc_can_skb(dev, &frame); if (!skb) { if (printk_ratelimit()) - dev_notice(dev->dev.parent, "packet dropped\n"); + netdev_notice(dev, "packet dropped\n"); stats->rx_dropped++; out_8(®s->canrflg, canrflg); continue; @@ -453,7 +457,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; @@ -512,12 +516,8 @@ static irqreturn_t mscan_isr(int irq, void *dev_id) static int mscan_do_set_mode(struct net_device *dev, enum can_mode mode) { - struct mscan_priv *priv = netdev_priv(dev); int ret = 0; - if (!priv->open_time) - return -EINVAL; - switch (mode) { case CAN_MODE_START: ret = mscan_restart(dev); @@ -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; @@ -546,8 +546,7 @@ static int mscan_do_set_bittiming(struct net_device *dev) BTR1_SET_TSEG2(bt->phase_seg2) | BTR1_SET_SAM(priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)); - dev_info(dev->dev.parent, "setting BTR0=0x%02x BTR1=0x%02x\n", - btr0, btr1); + netdev_info(dev, "setting BTR0=0x%02x BTR1=0x%02x\n", btr0, btr1); out_8(®s->canbtr0, btr0); out_8(®s->canbtr1, btr1); @@ -555,28 +554,52 @@ static int mscan_do_set_bittiming(struct net_device *dev) return 0; } +static int mscan_get_berr_counter(const struct net_device *dev, + struct can_berr_counter *bec) +{ + struct mscan_priv *priv = netdev_priv(dev); + struct mscan_regs __iomem *regs = priv->reg_base; + + bec->txerr = in_8(®s->cantxerr); + bec->rxerr = in_8(®s->canrxerr); + + return 0; +} + 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; + + if (priv->clk_ipg) { + ret = clk_prepare_enable(priv->clk_ipg); + if (ret) + goto exit_retcode; + } + if (priv->clk_can) { + ret = clk_prepare_enable(priv->clk_can); + if (ret) + goto exit_dis_ipg_clock; + } /* common open */ ret = open_candev(dev); if (ret) - return ret; + goto exit_dis_can_clock; napi_enable(&priv->napi); ret = request_irq(dev->irq, mscan_isr, 0, dev->name, dev); if (ret < 0) { - dev_err(dev->dev.parent, "failed to attach interrupt\n"); + netdev_err(dev, "failed to attach interrupt\n"); goto exit_napi_disable; } - priv->open_time = jiffies; - - clrbits8(®s->canctl1, MSCAN_LISTEN); + if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) + setbits8(®s->canctl1, MSCAN_LISTEN); + else + clrbits8(®s->canctl1, MSCAN_LISTEN); ret = mscan_start(dev); if (ret) @@ -587,18 +610,24 @@ static int mscan_open(struct net_device *dev) return 0; exit_free_irq: - priv->open_time = 0; free_irq(dev->irq, dev); exit_napi_disable: napi_disable(&priv->napi); close_candev(dev); +exit_dis_can_clock: + if (priv->clk_can) + clk_disable_unprepare(priv->clk_can); +exit_dis_ipg_clock: + if (priv->clk_ipg) + clk_disable_unprepare(priv->clk_ipg); +exit_retcode: return ret; } 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); @@ -608,21 +637,26 @@ static int mscan_close(struct net_device *dev) mscan_set_mode(dev, MSCAN_INIT_MODE); close_candev(dev); free_irq(dev->irq, dev); - priv->open_time = 0; + + if (priv->clk_can) + clk_disable_unprepare(priv->clk_can); + if (priv->clk_ipg) + clk_disable_unprepare(priv->clk_ipg); return 0; } static const struct net_device_ops mscan_netdev_ops = { - .ndo_open = mscan_open, - .ndo_stop = mscan_close, - .ndo_start_xmit = mscan_start_xmit, + .ndo_open = mscan_open, + .ndo_stop = mscan_close, + .ndo_start_xmit = mscan_start_xmit, + .ndo_change_mtu = can_change_mtu, }; 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); @@ -631,8 +665,10 @@ int register_mscandev(struct net_device *dev, int mscan_clksrc) else ctl1 &= ~MSCAN_CLKSRC; - if (priv->type == MSCAN_TYPE_MPC5121) + if (priv->type == MSCAN_TYPE_MPC5121) { + priv->can.do_get_berr_counter = mscan_get_berr_counter; ctl1 |= MSCAN_BORM; /* bus-off recovery upon request */ + } ctl1 |= MSCAN_CANE; out_8(®s->canctl1, ctl1); @@ -659,7 +695,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); @@ -685,7 +721,8 @@ struct net_device *alloc_mscandev(void) priv->can.bittiming_const = &mscan_bittiming_const; priv->can.do_set_bittiming = mscan_do_set_bittiming; priv->can.do_set_mode = mscan_do_set_mode; - priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES; + priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | + CAN_CTRLMODE_LISTENONLY; for (i = 0; i < TX_QUEUE_SIZE; i++) { priv->tx_queue[i].id = i; |
