diff options
author | David S. Miller <davem@davemloft.net> | 2013-09-03 21:54:02 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-09-03 21:54:02 -0400 |
commit | c12a22428ae773eff27bad490d35028fe036bf35 (patch) | |
tree | 7ca4b687b6033031b243518e6252700ffcb27340 /drivers | |
parent | e7abfe40928f4f8c1aa908477c36c13843bd1a57 (diff) | |
parent | 391ac1282dd7ff1cb8245cccc5262e8e4173edc4 (diff) |
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.c | 23 | ||||
-rw-r--r-- | drivers/net/can/mscan/mscan.c | 25 | ||||
-rw-r--r-- | drivers/net/can/mscan/mscan.h | 3 |
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 5b0ee8ef5885..e59b3a392af6 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 { | |||
40 | unsigned int type; | 40 | unsigned int type; |
41 | u32 (*get_clock)(struct platform_device *ofdev, const char *clock_name, | 41 | u32 (*get_clock)(struct platform_device *ofdev, const char *clock_name, |
42 | int *mscan_clksrc); | 42 | int *mscan_clksrc); |
43 | void (*put_clock)(struct platform_device *ofdev); | ||
43 | }; | 44 | }; |
44 | 45 | ||
45 | #ifdef CONFIG_PPC_MPC52xx | 46 | #ifdef CONFIG_PPC_MPC52xx |
@@ -148,7 +149,10 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev, | |||
148 | goto exit_put; | 149 | goto exit_put; |
149 | } | 150 | } |
150 | 151 | ||
151 | /* Determine the MSCAN device index from the physical address */ | 152 | /* Determine the MSCAN device index from the peripheral's |
153 | * physical address. Register address offsets against the | ||
154 | * IMMR base are: 0x1300, 0x1380, 0x2300, 0x2380 | ||
155 | */ | ||
152 | pval = of_get_property(ofdev->dev.of_node, "reg", &plen); | 156 | pval = of_get_property(ofdev->dev.of_node, "reg", &plen); |
153 | BUG_ON(!pval || plen < sizeof(*pval)); | 157 | BUG_ON(!pval || plen < sizeof(*pval)); |
154 | clockidx = (*pval & 0x80) ? 1 : 0; | 158 | clockidx = (*pval & 0x80) ? 1 : 0; |
@@ -177,7 +181,7 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev, | |||
177 | clockdiv = 1; | 181 | clockdiv = 1; |
178 | 182 | ||
179 | if (!clock_name || !strcmp(clock_name, "sys")) { | 183 | if (!clock_name || !strcmp(clock_name, "sys")) { |
180 | sys_clk = clk_get(&ofdev->dev, "sys_clk"); | 184 | sys_clk = devm_clk_get(&ofdev->dev, "sys_clk"); |
181 | if (IS_ERR(sys_clk)) { | 185 | if (IS_ERR(sys_clk)) { |
182 | dev_err(&ofdev->dev, "couldn't get sys_clk\n"); | 186 | dev_err(&ofdev->dev, "couldn't get sys_clk\n"); |
183 | goto exit_unmap; | 187 | goto exit_unmap; |
@@ -200,7 +204,7 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev, | |||
200 | } | 204 | } |
201 | 205 | ||
202 | if (clocksrc < 0) { | 206 | if (clocksrc < 0) { |
203 | ref_clk = clk_get(&ofdev->dev, "ref_clk"); | 207 | ref_clk = devm_clk_get(&ofdev->dev, "ref_clk"); |
204 | if (IS_ERR(ref_clk)) { | 208 | if (IS_ERR(ref_clk)) { |
205 | dev_err(&ofdev->dev, "couldn't get ref_clk\n"); | 209 | dev_err(&ofdev->dev, "couldn't get ref_clk\n"); |
206 | goto exit_unmap; | 210 | goto exit_unmap; |
@@ -277,6 +281,8 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev) | |||
277 | dev = alloc_mscandev(); | 281 | dev = alloc_mscandev(); |
278 | if (!dev) | 282 | if (!dev) |
279 | goto exit_dispose_irq; | 283 | goto exit_dispose_irq; |
284 | platform_set_drvdata(ofdev, dev); | ||
285 | SET_NETDEV_DEV(dev, &ofdev->dev); | ||
280 | 286 | ||
281 | priv = netdev_priv(dev); | 287 | priv = netdev_priv(dev); |
282 | priv->reg_base = base; | 288 | priv->reg_base = base; |
@@ -293,8 +299,6 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev) | |||
293 | goto exit_free_mscan; | 299 | goto exit_free_mscan; |
294 | } | 300 | } |
295 | 301 | ||
296 | SET_NETDEV_DEV(dev, &ofdev->dev); | ||
297 | |||
298 | err = register_mscandev(dev, mscan_clksrc); | 302 | err = register_mscandev(dev, mscan_clksrc); |
299 | if (err) { | 303 | if (err) { |
300 | dev_err(&ofdev->dev, "registering %s failed (err=%d)\n", | 304 | dev_err(&ofdev->dev, "registering %s failed (err=%d)\n", |
@@ -302,8 +306,6 @@ static int mpc5xxx_can_probe(struct platform_device *ofdev) | |||
302 | goto exit_free_mscan; | 306 | goto exit_free_mscan; |
303 | } | 307 | } |
304 | 308 | ||
305 | platform_set_drvdata(ofdev, dev); | ||
306 | |||
307 | dev_info(&ofdev->dev, "MSCAN at 0x%p, irq %d, clock %d Hz\n", | 309 | dev_info(&ofdev->dev, "MSCAN at 0x%p, irq %d, clock %d Hz\n", |
308 | priv->reg_base, dev->irq, priv->can.clock.freq); | 310 | priv->reg_base, dev->irq, priv->can.clock.freq); |
309 | 311 | ||
@@ -321,10 +323,17 @@ exit_unmap_mem: | |||
321 | 323 | ||
322 | static int mpc5xxx_can_remove(struct platform_device *ofdev) | 324 | static int mpc5xxx_can_remove(struct platform_device *ofdev) |
323 | { | 325 | { |
326 | const struct of_device_id *match; | ||
327 | const struct mpc5xxx_can_data *data; | ||
324 | struct net_device *dev = platform_get_drvdata(ofdev); | 328 | struct net_device *dev = platform_get_drvdata(ofdev); |
325 | struct mscan_priv *priv = netdev_priv(dev); | 329 | struct mscan_priv *priv = netdev_priv(dev); |
326 | 330 | ||
331 | match = of_match_device(mpc5xxx_can_table, &ofdev->dev); | ||
332 | data = match ? match->data : NULL; | ||
333 | |||
327 | unregister_mscandev(dev); | 334 | unregister_mscandev(dev); |
335 | if (data && data->put_clock) | ||
336 | data->put_clock(ofdev); | ||
328 | iounmap(priv->reg_base); | 337 | iounmap(priv->reg_base); |
329 | irq_dispose_mapping(dev->irq); | 338 | irq_dispose_mapping(dev->irq); |
330 | free_candev(dev); | 339 | free_candev(dev); |
diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c index e6b40954e204..a955ec8c4b97 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) | |||
573 | struct mscan_priv *priv = netdev_priv(dev); | 573 | struct mscan_priv *priv = netdev_priv(dev); |
574 | struct mscan_regs __iomem *regs = priv->reg_base; | 574 | struct mscan_regs __iomem *regs = priv->reg_base; |
575 | 575 | ||
576 | if (priv->clk_ipg) { | ||
577 | ret = clk_prepare_enable(priv->clk_ipg); | ||
578 | if (ret) | ||
579 | goto exit_retcode; | ||
580 | } | ||
581 | if (priv->clk_can) { | ||
582 | ret = clk_prepare_enable(priv->clk_can); | ||
583 | if (ret) | ||
584 | goto exit_dis_ipg_clock; | ||
585 | } | ||
586 | |||
576 | /* common open */ | 587 | /* common open */ |
577 | ret = open_candev(dev); | 588 | ret = open_candev(dev); |
578 | if (ret) | 589 | if (ret) |
579 | return ret; | 590 | goto exit_dis_can_clock; |
580 | 591 | ||
581 | napi_enable(&priv->napi); | 592 | napi_enable(&priv->napi); |
582 | 593 | ||
@@ -604,6 +615,13 @@ exit_free_irq: | |||
604 | exit_napi_disable: | 615 | exit_napi_disable: |
605 | napi_disable(&priv->napi); | 616 | napi_disable(&priv->napi); |
606 | close_candev(dev); | 617 | close_candev(dev); |
618 | exit_dis_can_clock: | ||
619 | if (priv->clk_can) | ||
620 | clk_disable_unprepare(priv->clk_can); | ||
621 | exit_dis_ipg_clock: | ||
622 | if (priv->clk_ipg) | ||
623 | clk_disable_unprepare(priv->clk_ipg); | ||
624 | exit_retcode: | ||
607 | return ret; | 625 | return ret; |
608 | } | 626 | } |
609 | 627 | ||
@@ -621,6 +639,11 @@ static int mscan_close(struct net_device *dev) | |||
621 | close_candev(dev); | 639 | close_candev(dev); |
622 | free_irq(dev->irq, dev); | 640 | free_irq(dev->irq, dev); |
623 | 641 | ||
642 | if (priv->clk_can) | ||
643 | clk_disable_unprepare(priv->clk_can); | ||
644 | if (priv->clk_ipg) | ||
645 | clk_disable_unprepare(priv->clk_ipg); | ||
646 | |||
624 | return 0; | 647 | return 0; |
625 | } | 648 | } |
626 | 649 | ||
diff --git a/drivers/net/can/mscan/mscan.h b/drivers/net/can/mscan/mscan.h index af2ed8baf0a3..9c24d60a23b1 100644 --- a/drivers/net/can/mscan/mscan.h +++ b/drivers/net/can/mscan/mscan.h | |||
@@ -21,6 +21,7 @@ | |||
21 | #ifndef __MSCAN_H__ | 21 | #ifndef __MSCAN_H__ |
22 | #define __MSCAN_H__ | 22 | #define __MSCAN_H__ |
23 | 23 | ||
24 | #include <linux/clk.h> | ||
24 | #include <linux/types.h> | 25 | #include <linux/types.h> |
25 | 26 | ||
26 | /* MSCAN control register 0 (CANCTL0) bits */ | 27 | /* MSCAN control register 0 (CANCTL0) bits */ |
@@ -283,6 +284,8 @@ struct mscan_priv { | |||
283 | unsigned int type; /* MSCAN type variants */ | 284 | unsigned int type; /* MSCAN type variants */ |
284 | unsigned long flags; | 285 | unsigned long flags; |
285 | void __iomem *reg_base; /* ioremap'ed address to registers */ | 286 | void __iomem *reg_base; /* ioremap'ed address to registers */ |
287 | struct clk *clk_ipg; /* clock for registers */ | ||
288 | struct clk *clk_can; /* clock for bitrates */ | ||
286 | u8 shadow_statflg; | 289 | u8 shadow_statflg; |
287 | u8 shadow_canrier; | 290 | u8 shadow_canrier; |
288 | u8 cur_pri; | 291 | u8 cur_pri; |