Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Steffen Trumtrar <s.trumtrar@pengutronix.de>
Acked-by: Hui Wang <jason77.wang@gmail.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>

authored by

Steffen Trumtrar and committed by
Marc Kleine-Budde
3d42a379 194b9a4c

+27 -18
+27 -18
drivers/net/can/flexcan.c
··· 190 190 u32 reg_esr; 191 191 u32 reg_ctrl_default; 192 192 193 - struct clk *clk; 193 + struct clk *clk_ipg; 194 + struct clk *clk_per; 194 195 struct flexcan_platform_data *pdata; 195 196 const struct flexcan_devtype_data *devtype_data; 196 197 }; ··· 829 828 struct flexcan_priv *priv = netdev_priv(dev); 830 829 int err; 831 830 832 - clk_prepare_enable(priv->clk); 831 + clk_prepare_enable(priv->clk_ipg); 832 + clk_prepare_enable(priv->clk_per); 833 833 834 834 err = open_candev(dev); 835 835 if (err) ··· 852 850 out_close: 853 851 close_candev(dev); 854 852 out: 855 - clk_disable_unprepare(priv->clk); 853 + clk_disable_unprepare(priv->clk_per); 854 + clk_disable_unprepare(priv->clk_ipg); 856 855 857 856 return err; 858 857 } ··· 867 864 flexcan_chip_stop(dev); 868 865 869 866 free_irq(dev->irq, dev); 870 - clk_disable_unprepare(priv->clk); 867 + clk_disable_unprepare(priv->clk_per); 868 + clk_disable_unprepare(priv->clk_ipg); 871 869 872 870 close_candev(dev); 873 871 ··· 907 903 struct flexcan_regs __iomem *regs = priv->base; 908 904 u32 reg, err; 909 905 910 - clk_prepare_enable(priv->clk); 906 + clk_prepare_enable(priv->clk_ipg); 907 + clk_prepare_enable(priv->clk_per); 911 908 912 909 /* select "bus clock", chip must be disabled */ 913 910 flexcan_chip_disable(priv); ··· 941 936 out: 942 937 /* disable core and turn off clocks */ 943 938 flexcan_chip_disable(priv); 944 - clk_disable_unprepare(priv->clk); 939 + clk_disable_unprepare(priv->clk_per); 940 + clk_disable_unprepare(priv->clk_ipg); 945 941 946 942 return err; 947 943 } ··· 970 964 struct net_device *dev; 971 965 struct flexcan_priv *priv; 972 966 struct resource *mem; 973 - struct clk *clk = NULL; 967 + struct clk *clk_ipg = NULL, *clk_per = NULL; 974 968 struct pinctrl *pinctrl; 975 969 void __iomem *base; 976 970 resource_size_t mem_size; ··· 986 980 "clock-frequency", &clock_freq); 987 981 988 982 if (!clock_freq) { 989 - clk = clk_get(&pdev->dev, NULL); 990 - if (IS_ERR(clk)) { 991 - dev_err(&pdev->dev, "no clock defined\n"); 992 - err = PTR_ERR(clk); 983 + clk_ipg = devm_clk_get(&pdev->dev, "ipg"); 984 + if (IS_ERR(clk_ipg)) { 985 + dev_err(&pdev->dev, "no ipg clock defined\n"); 986 + err = PTR_ERR(clk_ipg); 993 987 goto failed_clock; 994 988 } 995 - clock_freq = clk_get_rate(clk); 989 + clock_freq = clk_get_rate(clk_ipg); 990 + 991 + clk_per = devm_clk_get(&pdev->dev, "per"); 992 + if (IS_ERR(clk_per)) { 993 + dev_err(&pdev->dev, "no per clock defined\n"); 994 + err = PTR_ERR(clk_per); 995 + goto failed_clock; 996 + } 996 997 } 997 998 998 999 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ··· 1052 1039 CAN_CTRLMODE_BERR_REPORTING; 1053 1040 priv->base = base; 1054 1041 priv->dev = dev; 1055 - priv->clk = clk; 1042 + priv->clk_ipg = clk_ipg; 1043 + priv->clk_per = clk_per; 1056 1044 priv->pdata = pdev->dev.platform_data; 1057 1045 priv->devtype_data = devtype_data; 1058 1046 ··· 1081 1067 failed_map: 1082 1068 release_mem_region(mem->start, mem_size); 1083 1069 failed_get: 1084 - if (clk) 1085 - clk_put(clk); 1086 1070 failed_clock: 1087 1071 return err; 1088 1072 } ··· 1097 1085 1098 1086 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1099 1087 release_mem_region(mem->start, resource_size(mem)); 1100 - 1101 - if (priv->clk) 1102 - clk_put(priv->clk); 1103 1088 1104 1089 free_candev(dev); 1105 1090