aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/can/mscan/mscan.c
diff options
context:
space:
mode:
authorWolfgang Grandegger <wg@denx.de>2010-01-07 04:43:07 -0500
committerDavid S. Miller <davem@davemloft.net>2010-01-08 04:02:18 -0500
commitbf3af54732bea5894ccc2cbde3ab566f0af7da56 (patch)
treee8e6681168c9f695006962cacfb937d3dc1bbb06 /drivers/net/can/mscan/mscan.c
parent2d4b6faf7d1818e9a52ae9f068ab4ffd9c3be923 (diff)
can: mscan-mpc5xxx: add support for the MPC512x processor
The main differences compared to the MSCAN on the MPC5200 are: - More flexibility in choosing the CAN source clock and frequency: Three different clock sources can be selected: "ip", "ref" or "sys". For the latter two, a clock divider can be defined as well. If the clock source is not specified by the device tree, we first try to find an optimal CAN source clock based on the system clock. If that is not possible, the reference clock will be used. - The behavior of bus-off recovery is configurable: To comply with the usual handling of Socket-CAN bus-off recovery, "recovery on request" is selected (instead of automatic recovery). Note that only MPC5121 Rev. 2 and later is supported. Signed-off-by: Wolfgang Grandegger <wg@denx.de> Reviewed-by: Wolfram Sang <w.sang@pengutronix.de> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/can/mscan/mscan.c')
-rw-r--r--drivers/net/can/mscan/mscan.c51
1 files changed, 41 insertions, 10 deletions
diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c
index 0dcbe8cfab64..500d18918bd5 100644
--- a/drivers/net/can/mscan/mscan.c
+++ b/drivers/net/can/mscan/mscan.c
@@ -152,6 +152,12 @@ static int mscan_start(struct net_device *dev)
152 priv->shadow_canrier = 0; 152 priv->shadow_canrier = 0;
153 priv->flags = 0; 153 priv->flags = 0;
154 154
155 if (priv->type == MSCAN_TYPE_MPC5121) {
156 /* Clear pending bus-off condition */
157 if (in_8(&regs->canmisc) & MSCAN_BOHOLD)
158 out_8(&regs->canmisc, MSCAN_BOHOLD);
159 }
160
155 err = mscan_set_mode(dev, MSCAN_NORMAL_MODE); 161 err = mscan_set_mode(dev, MSCAN_NORMAL_MODE);
156 if (err) 162 if (err)
157 return err; 163 return err;
@@ -163,8 +169,29 @@ static int mscan_start(struct net_device *dev)
163 out_8(&regs->cantier, 0); 169 out_8(&regs->cantier, 0);
164 170
165 /* Enable receive interrupts. */ 171 /* Enable receive interrupts. */
166 out_8(&regs->canrier, MSCAN_OVRIE | MSCAN_RXFIE | MSCAN_CSCIE | 172 out_8(&regs->canrier, MSCAN_RX_INTS_ENABLE);
167 MSCAN_RSTATE1 | MSCAN_RSTATE0 | MSCAN_TSTATE1 | MSCAN_TSTATE0); 173
174 return 0;
175}
176
177static int mscan_restart(struct net_device *dev)
178{
179 struct mscan_priv *priv = netdev_priv(dev);
180
181 if (priv->type == MSCAN_TYPE_MPC5121) {
182 struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
183
184 priv->can.state = CAN_STATE_ERROR_ACTIVE;
185 WARN(!(in_8(&regs->canmisc) & MSCAN_BOHOLD),
186 "bus-off state expected");
187 out_8(&regs->canmisc, MSCAN_BOHOLD);
188 /* Re-enable receive interrupts. */
189 out_8(&regs->canrier, MSCAN_RX_INTS_ENABLE);
190 } else {
191 if (priv->can.state <= CAN_STATE_BUS_OFF)
192 mscan_set_mode(dev, MSCAN_INIT_MODE);
193 return mscan_start(dev);
194 }
168 195
169 return 0; 196 return 0;
170} 197}
@@ -362,9 +389,12 @@ static void mscan_get_err_frame(struct net_device *dev, struct can_frame *frame,
362 * automatically. To avoid that we stop the chip doing 389 * automatically. To avoid that we stop the chip doing
363 * a light-weight stop (we are in irq-context). 390 * a light-weight stop (we are in irq-context).
364 */ 391 */
365 out_8(&regs->cantier, 0); 392 if (priv->type != MSCAN_TYPE_MPC5121) {
366 out_8(&regs->canrier, 0); 393 out_8(&regs->cantier, 0);
367 setbits8(&regs->canctl0, MSCAN_SLPRQ | MSCAN_INITRQ); 394 out_8(&regs->canrier, 0);
395 setbits8(&regs->canctl0,
396 MSCAN_SLPRQ | MSCAN_INITRQ);
397 }
368 can_bus_off(dev); 398 can_bus_off(dev);
369 break; 399 break;
370 default: 400 default:
@@ -494,9 +524,7 @@ static int mscan_do_set_mode(struct net_device *dev, enum can_mode mode)
494 524
495 switch (mode) { 525 switch (mode) {
496 case CAN_MODE_START: 526 case CAN_MODE_START:
497 if (priv->can.state <= CAN_STATE_BUS_OFF) 527 ret = mscan_restart(dev);
498 mscan_set_mode(dev, MSCAN_INIT_MODE);
499 ret = mscan_start(dev);
500 if (ret) 528 if (ret)
501 break; 529 break;
502 if (netif_queue_stopped(dev)) 530 if (netif_queue_stopped(dev))
@@ -595,18 +623,21 @@ static const struct net_device_ops mscan_netdev_ops = {
595 .ndo_start_xmit = mscan_start_xmit, 623 .ndo_start_xmit = mscan_start_xmit,
596}; 624};
597 625
598int register_mscandev(struct net_device *dev, int clock_src) 626int register_mscandev(struct net_device *dev, int mscan_clksrc)
599{ 627{
600 struct mscan_priv *priv = netdev_priv(dev); 628 struct mscan_priv *priv = netdev_priv(dev);
601 struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base; 629 struct mscan_regs *regs = (struct mscan_regs *)priv->reg_base;
602 u8 ctl1; 630 u8 ctl1;
603 631
604 ctl1 = in_8(&regs->canctl1); 632 ctl1 = in_8(&regs->canctl1);
605 if (clock_src) 633 if (mscan_clksrc)
606 ctl1 |= MSCAN_CLKSRC; 634 ctl1 |= MSCAN_CLKSRC;
607 else 635 else
608 ctl1 &= ~MSCAN_CLKSRC; 636 ctl1 &= ~MSCAN_CLKSRC;
609 637
638 if (priv->type == MSCAN_TYPE_MPC5121)
639 ctl1 |= MSCAN_BORM; /* bus-off recovery upon request */
640
610 ctl1 |= MSCAN_CANE; 641 ctl1 |= MSCAN_CANE;
611 out_8(&regs->canctl1, ctl1); 642 out_8(&regs->canctl1, ctl1);
612 udelay(100); 643 udelay(100);