summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2013-09-04 01:54:02 (GMT)
committerDavid S. Miller <davem@davemloft.net>2013-09-04 01:54:02 (GMT)
commitc12a22428ae773eff27bad490d35028fe036bf35 (patch)
tree7ca4b687b6033031b243518e6252700ffcb27340 /drivers
parente7abfe40928f4f8c1aa908477c36c13843bd1a57 (diff)
parent391ac1282dd7ff1cb8245cccc5262e8e4173edc4 (diff)
downloadlinux-fsl-qoriq-c12a22428ae773eff27bad490d35028fe036bf35.tar.xz
Merge branch 'for-davem' of git://gitorious.org/linux-can/linux-can-next
Marc Kleine-Budde says: ==================== this is a pull request for net-next. There are two patches from Gerhard Sittig, which improves the clock handling on mpc5121. Oliver Hartkopp provides a patch that adds a per rule limitation of frame hops. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/can/mscan/mpc5xxx_can.c23
-rw-r--r--drivers/net/can/mscan/mscan.c25
-rw-r--r--drivers/net/can/mscan/mscan.h3
3 files changed, 43 insertions, 8 deletions
diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index 5b0ee8e..e59b3a3 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -40,6 +40,7 @@ struct mpc5xxx_can_data {
unsigned int type;
u32 (*get_clock)(struct platform_device *ofdev, const char *clock_name,
int *mscan_clksrc);
+ void (*put_clock)(struct platform_device *ofdev);
};
#ifdef CONFIG_PPC_MPC52xx
@@ -148,7 +149,10 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
goto exit_put;
}
- /* Determine the MSCAN device index from the physical address */
+ /* Determine the MSCAN device index from the peripheral's
+ * physical address. Register address offsets against the
+ * IMMR base are: 0x1300, 0x1380, 0x2300, 0x2380
+ */
pval = of_get_property(ofdev->dev.of_node, "reg", &plen);
BUG_ON(!pval || plen < sizeof(*pval));
clockidx = (*pval & 0x80) ? 1 : 0;
@@ -177,7 +181,7 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
clockdiv = 1;
if (!clock_name || !strcmp(clock_name, "sys")) {
- sys_clk = clk_get(&ofdev->dev, "sys_clk");
+ sys_clk = devm_clk_get(&ofdev->dev, "sys_clk");
if (IS_ERR(sys_clk)) {
dev_err(&ofdev->dev, "couldn't get sys_clk\n");
goto exit_unmap;
@@ -200,7 +204,7 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
}
if (clocksrc < 0) {
- ref_clk = clk_get(&ofdev->dev, "ref_clk");
+ ref_clk = devm_clk_get(&ofdev->dev, "ref_clk");
if (IS_ERR(ref_clk)) {
dev_err(&ofdev->dev, "couldn't get ref_clk\n");
goto exit_unmap;
@@ -277,6 +281,8 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
dev = alloc_mscandev();
if (!dev)
goto exit_dispose_irq;
+ platform_set_drvdata(ofdev, dev);
+ SET_NETDEV_DEV(dev, &ofdev->dev);
priv = netdev_priv(dev);
priv->reg_base = base;
@@ -293,8 +299,6 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
goto exit_free_mscan;
}
- SET_NETDEV_DEV(dev, &ofdev->dev);
-
err = register_mscandev(dev, mscan_clksrc);
if (err) {
dev_err(&ofdev->dev, "registering %s failed (err=%d)\n",
@@ -302,8 +306,6 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev)
goto exit_free_mscan;
}
- platform_set_drvdata(ofdev, dev);
-
dev_info(&ofdev->dev, "MSCAN at 0x%p, irq %d, clock %d Hz\n",
priv->reg_base, dev->irq, priv->can.clock.freq);
@@ -321,10 +323,17 @@ exit_unmap_mem:
static int mpc5xxx_can_remove(struct platform_device *ofdev)
{
+ const struct of_device_id *match;
+ const struct mpc5xxx_can_data *data;
struct net_device *dev = platform_get_drvdata(ofdev);
struct mscan_priv *priv = netdev_priv(dev);
+ match = of_match_device(mpc5xxx_can_table, &ofdev->dev);
+ data = match ? match->data : NULL;
+
unregister_mscandev(dev);
+ if (data && data->put_clock)
+ data->put_clock(ofdev);
iounmap(priv->reg_base);
irq_dispose_mapping(dev->irq);
free_candev(dev);
diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c
index e6b4095..a955ec8 100644
--- a/drivers/net/can/mscan/mscan.c
+++ b/drivers/net/can/mscan/mscan.c
@@ -573,10 +573,21 @@ static int mscan_open(struct net_device *dev)
struct mscan_priv *priv = netdev_priv(dev);
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);
@@ -604,6 +615,13 @@ exit_free_irq:
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;
}
@@ -621,6 +639,11 @@ static int mscan_close(struct net_device *dev)
close_candev(dev);
free_irq(dev->irq, dev);
+ if (priv->clk_can)
+ clk_disable_unprepare(priv->clk_can);
+ if (priv->clk_ipg)
+ clk_disable_unprepare(priv->clk_ipg);
+
return 0;
}
diff --git a/drivers/net/can/mscan/mscan.h b/drivers/net/can/mscan/mscan.h
index af2ed8b..9c24d60 100644
--- a/drivers/net/can/mscan/mscan.h
+++ b/drivers/net/can/mscan/mscan.h
@@ -21,6 +21,7 @@
#ifndef __MSCAN_H__
#define __MSCAN_H__
+#include <linux/clk.h>
#include <linux/types.h>
/* MSCAN control register 0 (CANCTL0) bits */
@@ -283,6 +284,8 @@ struct mscan_priv {
unsigned int type; /* MSCAN type variants */
unsigned long flags;
void __iomem *reg_base; /* ioremap'ed address to registers */
+ struct clk *clk_ipg; /* clock for registers */
+ struct clk *clk_can; /* clock for bitrates */
u8 shadow_statflg;
u8 shadow_canrier;
u8 cur_pri;