}
#endif
+static int flexcan_clks_enable(const struct flexcan_priv *priv)
+{
+ int err;
+
+ err = clk_prepare_enable(priv->clk_ipg);
+ if (err)
+ return err;
+
+ err = clk_prepare_enable(priv->clk_per);
+ if (err)
+ clk_disable_unprepare(priv->clk_ipg);
+
+ return err;
+}
+
+static void flexcan_clks_disable(const struct flexcan_priv *priv)
+{
+ clk_disable_unprepare(priv->clk_ipg);
+ clk_disable_unprepare(priv->clk_per);
+}
+
static inline void flexcan_enter_stop_mode(struct flexcan_priv *priv)
{
/* enable stop request */
const struct flexcan_priv *priv = netdev_priv(dev);
int err;
- err = clk_prepare_enable(priv->clk_ipg);
+ err = flexcan_clks_enable(priv);
if (err)
return err;
- err = clk_prepare_enable(priv->clk_per);
- if (err)
- goto out_disable_ipg;
-
err = __flexcan_get_berr_counter(dev, bec);
- clk_disable_unprepare(priv->clk_per);
- out_disable_ipg:
- clk_disable_unprepare(priv->clk_ipg);
+ flexcan_clks_disable(priv);
return err;
}
u32 reg_mcr, reg_ctrl, reg_ctrl2, reg_mecr, reg_fdctrl;
int err, i;
+ err = flexcan_clks_enable(priv);
+ if (err)
+ return err;
+
/* enable module */
err = flexcan_chip_enable(priv);
if (err)
- return err;
+ goto out_clocks_disable;
/* soft reset */
err = flexcan_chip_softreset(priv);
flexcan_transceiver_disable(priv);
out_chip_disable:
flexcan_chip_disable(priv);
+ out_clocks_disable:
+ flexcan_clks_disable(priv);
+
return err;
}
flexcan_write(priv, FLEXCAN_CTRL, priv->reg_ctrl_default &
~FLEXCAN_CTRL_ERR_ALL);
+ flexcan_clks_disable(priv);
+
flexcan_transceiver_disable(priv);
priv->can.state = CAN_STATE_STOPPED;
}
struct flexcan_priv *priv = netdev_priv(dev);
int err;
- err = clk_prepare_enable(priv->clk_ipg);
+ err = flexcan_clks_enable(priv);
if (err)
return err;
- err = clk_prepare_enable(priv->clk_per);
- if (err)
- goto out_disable_ipg;
-
err = open_candev(dev);
if (err)
- goto out_disable_per;
+ goto out_clocks_disable;
err = request_irq(dev->irq, flexcan_irq, IRQF_SHARED, dev->name, dev);
if (err)
free_irq(dev->irq, dev);
out_close:
close_candev(dev);
- out_disable_per:
- clk_disable_unprepare(priv->clk_per);
- out_disable_ipg:
- clk_disable_unprepare(priv->clk_ipg);
+
+ out_clocks_disable:
+ flexcan_clks_disable(priv);
return err;
}
flexcan_chip_stop(dev);
free_irq(dev->irq, dev);
- clk_disable_unprepare(priv->clk_per);
- clk_disable_unprepare(priv->clk_ipg);
close_candev(dev);
can_led_event(dev, CAN_LED_EVENT_STOP);
+ flexcan_clks_disable(priv);
+
return 0;
}
struct flexcan_priv *priv = netdev_priv(dev);
u32 reg, err;
- err = clk_prepare_enable(priv->clk_ipg);
+ err = flexcan_clks_enable(priv);
if (err)
return err;
- err = clk_prepare_enable(priv->clk_per);
- if (err)
- goto out_disable_ipg;
-
/* select "bus clock", chip must be disabled */
err = flexcan_chip_disable(priv);
if (err)
- goto out_disable_per;
+ goto out_clocks_disable;
reg = flexcan_read(priv, FLEXCAN_CTRL);
reg |= FLEXCAN_CTRL_CLK_SRC;
flexcan_write(priv, FLEXCAN_CTRL, reg);
/* disable core and turn off clocks */
out_chip_disable:
flexcan_chip_disable(priv);
- out_disable_per:
- clk_disable_unprepare(priv->clk_per);
- out_disable_ipg:
- clk_disable_unprepare(priv->clk_ipg);
+ out_clocks_disable:
+ flexcan_clks_disable(priv);
return err;
}