summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDong Aisheng <aisheng.dong@nxp.com>2017-10-30 19:13:38 +0800
committerDong Aisheng <aisheng.dong@nxp.com>2017-11-10 17:28:57 +0800
commit2537ceeda2b1abb695c87fd8646a0f1fa4b97055 (patch)
treef3c674f2c07f2dbfc766690e3428c9aa06208d6b
parent6a7e069d0eedd43d9a278715a063a334270e19c1 (diff)
MLK-16757-1 can: flexcan: disable clocks during suspend
Flexcan will be stopped during suspend if no wakeup function required and enabled after resume accordingly. During this period, we could explicitly disable clocks. We do this by moving the clk_prepare_enable/clk_disable_unprepare into flexcan_chip_start and flexcan_chip_stop functions which will be called during suspend/resume function. Reviewed-by: Frank Li <frank.li@nxp.com> Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
-rw-r--r--drivers/net/can/flexcan.c75
1 files changed, 44 insertions, 31 deletions
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 4f86c2547952..b70d77b5ed5e 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -454,6 +454,27 @@ static inline void flexcan_mb_write(const struct flexcan_priv *priv,
}
#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 */
@@ -612,19 +633,13 @@ static int flexcan_get_berr_counter(const struct net_device *dev,
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;
}
@@ -1030,10 +1045,14 @@ static int flexcan_chip_start(struct net_device *dev)
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);
@@ -1211,6 +1230,9 @@ static int flexcan_chip_start(struct net_device *dev)
flexcan_transceiver_disable(priv);
out_chip_disable:
flexcan_chip_disable(priv);
+ out_clocks_disable:
+ flexcan_clks_disable(priv);
+
return err;
}
@@ -1231,6 +1253,8 @@ static void flexcan_chip_stop(struct net_device *dev)
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;
}
@@ -1240,17 +1264,13 @@ static int flexcan_open(struct net_device *dev)
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)
@@ -1272,10 +1292,9 @@ static int flexcan_open(struct net_device *dev)
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;
}
@@ -1289,13 +1308,13 @@ static int flexcan_close(struct net_device *dev)
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;
}
@@ -1331,18 +1350,14 @@ static int register_flexcandev(struct net_device *dev)
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);
@@ -1379,10 +1394,8 @@ static int register_flexcandev(struct net_device *dev)
/* 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;
}