Commit 3d42a379 authored by Steffen Trumtrar's avatar Steffen Trumtrar Committed by Marc Kleine-Budde

can: flexcan: add 2nd clock to support imx53 and newer

This patch adds support for a second clock to the flexcan driver. On
modern freescale ARM cores like the imx53 and imx6q two clocks ("ipg"
and "per") must be enabled in order to access the CAN core.

In the original driver, the clock was requested without specifying the
connection id, further all mainline ARM archs with flexcan support
(imx28, imx25, imx35) register their flexcan clock without a
connection id, too.

This patch first renames the existing clk variable to clk_ipg and
converts it to devm for easier error handling. The connection id "ipg"
is added to the devm_clk_get() call. Then a second clock "per" is
requested. As all archs don't specify a connection id, both clk_get
return the same clock. This ensures compatibility to existing flexcan
support and adds support for imx53 at the same time.

After this patch hits mainline, the archs may give their existing
flexcan clock the "ipg" connection id and implement a dummy "per"
clock.

This patch has been tested on imx28 (unmodified clk tree) and on imx53
with a seperate "ipg" and "per" clock.

Cc: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: default avatarSteffen Trumtrar <s.trumtrar@pengutronix.de>
Acked-by: default avatarHui Wang <jason77.wang@gmail.com>
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent 194b9a4c
...@@ -190,7 +190,8 @@ struct flexcan_priv { ...@@ -190,7 +190,8 @@ struct flexcan_priv {
u32 reg_esr; u32 reg_esr;
u32 reg_ctrl_default; u32 reg_ctrl_default;
struct clk *clk; struct clk *clk_ipg;
struct clk *clk_per;
struct flexcan_platform_data *pdata; struct flexcan_platform_data *pdata;
const struct flexcan_devtype_data *devtype_data; const struct flexcan_devtype_data *devtype_data;
}; };
...@@ -828,7 +829,8 @@ static int flexcan_open(struct net_device *dev) ...@@ -828,7 +829,8 @@ static int flexcan_open(struct net_device *dev)
struct flexcan_priv *priv = netdev_priv(dev); struct flexcan_priv *priv = netdev_priv(dev);
int err; int err;
clk_prepare_enable(priv->clk); clk_prepare_enable(priv->clk_ipg);
clk_prepare_enable(priv->clk_per);
err = open_candev(dev); err = open_candev(dev);
if (err) if (err)
...@@ -850,7 +852,8 @@ static int flexcan_open(struct net_device *dev) ...@@ -850,7 +852,8 @@ static int flexcan_open(struct net_device *dev)
out_close: out_close:
close_candev(dev); close_candev(dev);
out: out:
clk_disable_unprepare(priv->clk); clk_disable_unprepare(priv->clk_per);
clk_disable_unprepare(priv->clk_ipg);
return err; return err;
} }
...@@ -864,7 +867,8 @@ static int flexcan_close(struct net_device *dev) ...@@ -864,7 +867,8 @@ static int flexcan_close(struct net_device *dev)
flexcan_chip_stop(dev); flexcan_chip_stop(dev);
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
clk_disable_unprepare(priv->clk); clk_disable_unprepare(priv->clk_per);
clk_disable_unprepare(priv->clk_ipg);
close_candev(dev); close_candev(dev);
...@@ -903,7 +907,8 @@ static int __devinit register_flexcandev(struct net_device *dev) ...@@ -903,7 +907,8 @@ static int __devinit register_flexcandev(struct net_device *dev)
struct flexcan_regs __iomem *regs = priv->base; struct flexcan_regs __iomem *regs = priv->base;
u32 reg, err; u32 reg, err;
clk_prepare_enable(priv->clk); clk_prepare_enable(priv->clk_ipg);
clk_prepare_enable(priv->clk_per);
/* select "bus clock", chip must be disabled */ /* select "bus clock", chip must be disabled */
flexcan_chip_disable(priv); flexcan_chip_disable(priv);
...@@ -936,7 +941,8 @@ static int __devinit register_flexcandev(struct net_device *dev) ...@@ -936,7 +941,8 @@ static int __devinit register_flexcandev(struct net_device *dev)
out: out:
/* disable core and turn off clocks */ /* disable core and turn off clocks */
flexcan_chip_disable(priv); flexcan_chip_disable(priv);
clk_disable_unprepare(priv->clk); clk_disable_unprepare(priv->clk_per);
clk_disable_unprepare(priv->clk_ipg);
return err; return err;
} }
...@@ -964,7 +970,7 @@ static int __devinit flexcan_probe(struct platform_device *pdev) ...@@ -964,7 +970,7 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
struct net_device *dev; struct net_device *dev;
struct flexcan_priv *priv; struct flexcan_priv *priv;
struct resource *mem; struct resource *mem;
struct clk *clk = NULL; struct clk *clk_ipg = NULL, *clk_per = NULL;
struct pinctrl *pinctrl; struct pinctrl *pinctrl;
void __iomem *base; void __iomem *base;
resource_size_t mem_size; resource_size_t mem_size;
...@@ -980,13 +986,20 @@ static int __devinit flexcan_probe(struct platform_device *pdev) ...@@ -980,13 +986,20 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
"clock-frequency", &clock_freq); "clock-frequency", &clock_freq);
if (!clock_freq) { if (!clock_freq) {
clk = clk_get(&pdev->dev, NULL); clk_ipg = devm_clk_get(&pdev->dev, "ipg");
if (IS_ERR(clk)) { if (IS_ERR(clk_ipg)) {
dev_err(&pdev->dev, "no clock defined\n"); dev_err(&pdev->dev, "no ipg clock defined\n");
err = PTR_ERR(clk); err = PTR_ERR(clk_ipg);
goto failed_clock;
}
clock_freq = clk_get_rate(clk_ipg);
clk_per = devm_clk_get(&pdev->dev, "per");
if (IS_ERR(clk_per)) {
dev_err(&pdev->dev, "no per clock defined\n");
err = PTR_ERR(clk_per);
goto failed_clock; goto failed_clock;
} }
clock_freq = clk_get_rate(clk);
} }
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
...@@ -1039,7 +1052,8 @@ static int __devinit flexcan_probe(struct platform_device *pdev) ...@@ -1039,7 +1052,8 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
CAN_CTRLMODE_BERR_REPORTING; CAN_CTRLMODE_BERR_REPORTING;
priv->base = base; priv->base = base;
priv->dev = dev; priv->dev = dev;
priv->clk = clk; priv->clk_ipg = clk_ipg;
priv->clk_per = clk_per;
priv->pdata = pdev->dev.platform_data; priv->pdata = pdev->dev.platform_data;
priv->devtype_data = devtype_data; priv->devtype_data = devtype_data;
...@@ -1067,8 +1081,6 @@ static int __devinit flexcan_probe(struct platform_device *pdev) ...@@ -1067,8 +1081,6 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
failed_map: failed_map:
release_mem_region(mem->start, mem_size); release_mem_region(mem->start, mem_size);
failed_get: failed_get:
if (clk)
clk_put(clk);
failed_clock: failed_clock:
return err; return err;
} }
...@@ -1086,9 +1098,6 @@ static int __devexit flexcan_remove(struct platform_device *pdev) ...@@ -1086,9 +1098,6 @@ static int __devexit flexcan_remove(struct platform_device *pdev)
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(mem->start, resource_size(mem)); release_mem_region(mem->start, resource_size(mem));
if (priv->clk)
clk_put(priv->clk);
free_candev(dev); free_candev(dev);
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment