Module: xenomai-2.6 Branch: master Commit: a7b7adec9123dc60587d160f0818322a9a547630 URL: http://git.xenomai.org/?p=xenomai-2.6.git;a=commit;h=a7b7adec9123dc60587d160f0818322a9a547630
Author: Philippe Gerum <r...@xenomai.org> Date: Fri Jan 16 14:43:23 2015 +0100 can/flexcan: fixup for kernel release >= 3.11 As the platform data completely disappears, the information to enable/disable the transceiver should be pulled from the device tree data. Two clocks (periodic and IPG) need setup for each CAN controller. --- ksrc/drivers/can/rtcan_flexcan.c | 141 ++++++++++++++++++++++++++------------ ksrc/drivers/can/rtcan_module.c | 5 +- 2 files changed, 101 insertions(+), 45 deletions(-) diff --git a/ksrc/drivers/can/rtcan_flexcan.c b/ksrc/drivers/can/rtcan_flexcan.c index 1674b73..f5477db 100644 --- a/ksrc/drivers/can/rtcan_flexcan.c +++ b/ksrc/drivers/can/rtcan_flexcan.c @@ -19,7 +19,6 @@ * GNU General Public License for more details. */ -#include <linux/can/platform/flexcan.h> #include <linux/clk.h> #include <linux/delay.h> #include <linux/if_arp.h> @@ -38,6 +37,11 @@ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) #include <linux/pinctrl/consumer.h> #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0) +#include <linux/can/platform/flexcan.h> +#else +#include <linux/regulator/consumer.h> +#endif #include <asm/unaligned.h> #include <rtdm/rtdm_driver.h> @@ -222,10 +226,16 @@ struct flexcan_priv { u32 reg_esr; u32 reg_ctrl_default; - struct clk *clk; - struct flexcan_platform_data *pdata; struct can_bittime bit_time; const struct flexcan_devtype_data *devtype_data; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0) + struct flexcan_platform_data *pdata; + struct clk *clk; +#else + struct regulator *reg_xceiver; + struct clk *clk_ipg; + struct clk *clk_per; +#endif }; static struct flexcan_devtype_data fsl_p1010_devtype_data = { @@ -251,7 +261,18 @@ static struct can_bittiming_const flexcan_bittiming_const = { }; /* Compatibility functions to support old kernel versions */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) +static inline void flexcan_clk_enable(struct flexcan_priv *priv) +{ + clk_prepare_enable(priv->clk_ipg); + clk_prepare_enable(priv->clk_per); +} +static inline void flexcan_clk_disable(struct flexcan_priv *priv) +{ + clk_disable_unprepare(priv->clk_ipg); + clk_disable_unprepare(priv->clk_per); +} +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) static inline void flexcan_clk_enable(struct flexcan_priv *priv) { clk_prepare_enable(priv->clk); @@ -297,13 +318,28 @@ static inline void flexcan_write(u32 val, void __iomem *addr) #endif /* - * Swtich transceiver on or off + * Switch transceiver on or off */ -static void flexcan_transceiver_switch(const struct flexcan_priv *priv, int on) +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0) +static int flexcan_transceiver_switch(const struct flexcan_priv *priv, int on) { if (priv->pdata && priv->pdata->transceiver_switch) priv->pdata->transceiver_switch(on); + + return 0; } +#else +static int flexcan_transceiver_switch(const struct flexcan_priv *priv, int on) +{ + if (priv->reg_xceiver == NULL) + return 0; + + if (on) + return regulator_enable(priv->reg_xceiver); + + return regulator_disable(priv->reg_xceiver); +} +#endif static inline void flexcan_chip_enable(struct flexcan_priv *priv) { @@ -1013,6 +1049,16 @@ static struct platform_device_id flexcan_id_table[] = { { /* sentinel */ }, }; +static void put_clocks(struct flexcan_priv *priv) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0) + clk_put(priv->clk); +#else + clk_put(priv->clk_per); + clk_put(priv->clk_ipg); +#endif +} + static int flexcan_probe(struct platform_device *pdev) { #ifdef CONFIG_OF @@ -1022,10 +1068,6 @@ static int flexcan_probe(struct platform_device *pdev) struct rtcan_device *dev; struct flexcan_priv *priv; struct resource *mem; - struct clk *clk = NULL; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) - struct pinctrl *pinctrl; -#endif void __iomem *base; resource_size_t mem_size; int err, irq; @@ -1033,9 +1075,12 @@ static int flexcan_probe(struct platform_device *pdev) #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) - pinctrl = devm_pinctrl_get_select_default(&pdev->dev); - if (IS_ERR(pinctrl)) - return PTR_ERR(pinctrl); + { + struct pinctrl *pinctrl; + pinctrl = devm_pinctrl_get_select_default(&pdev->dev); + if (IS_ERR(pinctrl)) + return PTR_ERR(pinctrl); + } #endif #ifdef CONFIG_OF @@ -1053,22 +1098,41 @@ static int flexcan_probe(struct platform_device *pdev) if (!devtype_data && pdev->id_entry->driver_data) { devtype_data = (struct flexcan_devtype_data *) pdev->id_entry->driver_data; - } else { - if (!devtype_data){ - err = -ENODEV; - goto out_error; - } - } + } else if (!devtype_data) + return -ENODEV; + + dev = rtcan_dev_alloc(sizeof(struct flexcan_priv), 0); + if (dev == NULL) + return -ENOMEM; + priv = rtcan_priv(dev); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0) if (!clock_freq) { - clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(clk)) { + priv->clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(priv->clk)) { dev_err(&pdev->dev, "no clock defined\n"); - err = PTR_ERR(clk); - goto out_error; + return PTR_ERR(priv->clk); + } + clock_freq = clk_get_rate(priv->clk); + } +#else + if (!clock_freq) { + priv->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); + if (IS_ERR(priv->clk_ipg)) { + dev_err(&pdev->dev, "no ipg clock defined\n"); + return PTR_ERR(priv->clk_ipg); + } + + priv->clk_per = devm_clk_get(&pdev->dev, "per"); + if (IS_ERR(priv->clk_per)) { + clk_put(priv->clk_ipg); + dev_err(&pdev->dev, "no per clock defined\n"); + return PTR_ERR(priv->clk_per); } - clock_freq = clk_get_rate(clk); + clock_freq = clk_get_rate(priv->clk_per); } +#endif mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); @@ -1089,20 +1153,17 @@ static int flexcan_probe(struct platform_device *pdev) goto out_map; } - dev = rtcan_dev_alloc(sizeof(struct flexcan_priv), 0); - if (!dev) { - err = -ENOMEM; - goto out_alloc; - } - - priv = rtcan_priv(dev); - priv->base = base; priv->irq = irq; priv->dev = dev; - priv->clk = clk; - priv->pdata = pdev->dev.platform_data; priv->devtype_data = devtype_data; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0) + priv->pdata = pdev->dev.platform_data; +#else + priv->reg_xceiver = devm_regulator_get(&pdev->dev, "xceiver"); + if (IS_ERR(priv->reg_xceiver)) + priv->reg_xceiver = NULL; +#endif dev_set_drvdata(&pdev->dev, dev); @@ -1133,15 +1194,13 @@ static int flexcan_probe(struct platform_device *pdev) return 0; out_register: - rtcan_dev_free(dev); -out_alloc: iounmap(base); out_map: release_mem_region(mem->start, mem_size); out_get: - if (clk) - clk_put(clk); -out_error: + put_clocks(priv); + rtcan_dev_free(dev); + return err; } @@ -1158,9 +1217,7 @@ static int flexcan_remove(struct platform_device *pdev) mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(mem->start, resource_size(mem)); - if (priv->clk) - clk_put(priv->clk); - + put_clocks(priv); rtcan_dev_free(dev); return 0; diff --git a/ksrc/drivers/can/rtcan_module.c b/ksrc/drivers/can/rtcan_module.c index 764df94..3460d08 100644 --- a/ksrc/drivers/can/rtcan_module.c +++ b/ksrc/drivers/can/rtcan_module.c @@ -333,9 +333,8 @@ static const struct file_operations rtcan_proc_filter_ops = { static int rtcan_read_proc_version(struct seq_file *p, void *data) { - seq_printf(p, "RT-Socket-CAN %d.%d.%d - built on %s %s\n", - RTCAN_MAJOR_VER, RTCAN_MINOR_VER, RTCAN_BUGFIX_VER, - __DATE__, __TIME__); + seq_printf(p, "RT-Socket-CAN %d.%d.%d\n", + RTCAN_MAJOR_VER, RTCAN_MINOR_VER, RTCAN_BUGFIX_VER); return 0; } _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai-git