Module: xenomai-2.6 Branch: master Commit: 34c5ec7a704115cd84530ee36c540b981f1fef4e URL: http://git.xenomai.org/?p=xenomai-2.6.git;a=commit;h=34c5ec7a704115cd84530ee36c540b981f1fef4e
Author: Henri Roosen <henriroo...@gmail.com> Date: Tue May 28 13:14:09 2013 +0200 Fix rtcan_flexcan for mx6 for OpenFirmware platforms The default rx fifo global mask register, newly introduced in mx6q, is 0xffffffff and the reset value in Message buffers(can be reused as the memory of rx fifo filter table) is none zero, it will wrongly cause the can to be unable to recevie packets due to filter. We need to clear it to make sure to receive all packets. Signed-off-by: Henri Roosen <henriroo...@gmail.com> Acked-by: Wolfgang Grandegger <w...@grandegger.com> --- ksrc/drivers/can/rtcan_flexcan.c | 146 +++++++++++++++++++++----------------- 1 files changed, 81 insertions(+), 65 deletions(-) diff --git a/ksrc/drivers/can/rtcan_flexcan.c b/ksrc/drivers/can/rtcan_flexcan.c index e73ff49..e97cd92 100644 --- a/ksrc/drivers/can/rtcan_flexcan.c +++ b/ksrc/drivers/can/rtcan_flexcan.c @@ -32,6 +32,7 @@ #include <linux/version.h> #ifdef CONFIG_OF #include <linux/of.h> +#include <linux/of_device.h> #endif #include <linux/platform_device.h> #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) @@ -46,17 +47,6 @@ #include "rtcan_raw.h" #include "rtcan_internal.h" -/* - * Due to a bug in most Flexcan cores, the bus error interrupt needs - * to be enabled. Otherwise we don't get any bus warning or passive - * interrupts. This is not necessay for the i.MX28, for example and - * this modules parameter allows to overcome this limitation. - */ -static int berr_int = 1; -module_param(berr_int, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(berr_int, - "Bus error interrupt [1 (enabled)]. Can be disabled for i.MX28."); - #define DEV_NAME "rtcan%d" #define DRV_NAME "flexcan" @@ -170,6 +160,23 @@ enum flexcan_ip_version { #define FLEXCAN_MB_CODE_MASK (0xf0ffffff) +/* + * FLEXCAN hardware feature flags + * + * Below is some version info we got: + * SOC Version IP-Version Glitch- [TR]WRN_INT + * Filter? connected? + * MX25 FlexCAN2 03.00.00.00 no no + * MX28 FlexCAN2 03.00.04.00 yes yes + * MX35 FlexCAN2 03.00.00.00 no no + * MX53 FlexCAN2 03.00.00.00 yes no + * MX6s FlexCAN3 10.00.12.00 yes yes + * + * Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected. + */ +#define FLEXCAN_HAS_V10_FEATURES BIT(1) /* For core version >= 10 */ +#define FLEXCAN_HAS_BROKEN_ERR_STATE BIT(2) /* [TR]WRN_INT not connected */ + /* Structure of the message buffer */ struct flexcan_mb { u32 can_ctrl; @@ -202,6 +209,10 @@ struct flexcan_regs { struct flexcan_mb cantxfg[64]; }; +struct flexcan_devtype_data { + u32 features; /* hardware controller features */ +}; + struct flexcan_priv { struct rtcan_device *dev; @@ -213,9 +224,15 @@ struct flexcan_priv { struct clk *clk; struct flexcan_platform_data *pdata; struct can_bittime bit_time; -#ifndef CONFIG_OF - enum flexcan_ip_version version; -#endif + const struct flexcan_devtype_data *devtype_data; +}; + +static struct flexcan_devtype_data fsl_p1010_devtype_data = { + .features = FLEXCAN_HAS_BROKEN_ERR_STATE, +}; +static struct flexcan_devtype_data fsl_imx28_devtype_data; +static struct flexcan_devtype_data fsl_imx6q_devtype_data = { + .features = FLEXCAN_HAS_V10_FEATURES, }; static char *flexcan_ctrl_name = "FLEXCAN"; @@ -730,19 +747,17 @@ static int flexcan_chip_start(struct rtcan_device *dev) * enable tx and rx warning interrupt * enable bus off interrupt * (== FLEXCAN_CTRL_ERR_STATE) - * - * _note_: by default we enable the "error interrupt" - * (FLEXCAN_CTRL_ERR_MSK), too. Otherwise we don't get any - * warning or bus passive interrupts on most Flexcan cores. - * The Flexcan on the i.MX28 does not have this bug and it - * can be disabled if no bus error reporting is necessary - * by setting the module parameter "berr_int" to 0. */ reg_ctrl = flexcan_read(®s->ctrl); reg_ctrl &= ~FLEXCAN_CTRL_TSYN; reg_ctrl |= FLEXCAN_CTRL_BOFF_REC | FLEXCAN_CTRL_LBUF | FLEXCAN_CTRL_ERR_STATE; - if (berr_int) + /* + * enable the "error interrupt" (FLEXCAN_CTRL_ERR_MSK), + * on most Flexcan cores, too. Otherwise we don't get + * any error warning or passive interrupts. + */ + if (priv->devtype_data->features & FLEXCAN_HAS_BROKEN_ERR_STATE) reg_ctrl |= FLEXCAN_CTRL_ERR_MSK; /* save for later use */ @@ -766,10 +781,8 @@ static int flexcan_chip_start(struct rtcan_device *dev) flexcan_write(0x0, ®s->rx14mask); flexcan_write(0x0, ®s->rx15mask); -#ifndef CONFIG_OF - if (priv->version >= FLEXCAN_VER_10_0_12) + if (priv->devtype_data->features & FLEXCAN_HAS_V10_FEATURES) flexcan_write(0x0, ®s->rxfgmask); -#endif flexcan_transceiver_switch(priv, 1); @@ -983,8 +996,30 @@ static void unregister_flexcandev(struct rtcan_device *dev) rtcan_dev_unregister(dev); } +#ifdef CONFIG_OF +static struct of_device_id flexcan_of_match[] = { + { .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, }, + { .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, }, + { .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, }, + { /* sentinel */ }, +}; +#endif +static struct platform_device_id flexcan_id_table[] = { + { .name = "imx25-flexcan", .driver_data = (kernel_ulong_t)&fsl_p1010_devtype_data, }, + { .name = "imx28-flexcan", .driver_data = (kernel_ulong_t)&fsl_imx28_devtype_data, }, + { .name = "imx35-flexcan", .driver_data = (kernel_ulong_t)&fsl_p1010_devtype_data, }, + { .name = "imx53-flexcan", .driver_data = (kernel_ulong_t)&fsl_p1010_devtype_data, }, + { .name = "imx6q-flexcan", .driver_data = (kernel_ulong_t)&fsl_imx6q_devtype_data, }, + { .name = "flexcan", .driver_data = (kernel_ulong_t)&fsl_p1010_devtype_data, }, + { /* sentinel */ }, +}; + static int flexcan_probe(struct platform_device *pdev) { +#ifdef CONFIG_OF + const struct of_device_id *of_id; +#endif + const struct flexcan_devtype_data *devtype_data = NULL; struct rtcan_device *dev; struct flexcan_priv *priv; struct resource *mem; @@ -997,6 +1032,7 @@ static int flexcan_probe(struct platform_device *pdev) int err, irq; u32 clock_freq = 0; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) pinctrl = devm_pinctrl_get_select_default(&pdev->dev); if (IS_ERR(pinctrl)) @@ -1009,14 +1045,26 @@ static int flexcan_probe(struct platform_device *pdev) of_property_read_u32(pdev->dev.of_node, "clock-frequency", &clock_freq); #endif -#endif + + of_id = of_match_device(flexcan_of_match, &pdev->dev); + if (of_id) { + devtype_data = of_id->data; + } +#endif /* CONFIG_OF */ + if (!devtype_data && pdev->id_entry->driver_data) { + devtype_data = (struct flexcan_devtype_data *) + pdev->id_entry->driver_data; + } else { + err = -ENODEV; + goto out_error; + } if (!clock_freq) { clk = clk_get(&pdev->dev, NULL); if (IS_ERR(clk)) { dev_err(&pdev->dev, "no clock defined\n"); err = PTR_ERR(clk); - goto out_clock; + goto out_error; } clock_freq = clk_get_rate(clk); } @@ -1053,9 +1101,7 @@ static int flexcan_probe(struct platform_device *pdev) priv->dev = dev; priv->clk = clk; priv->pdata = pdev->dev.platform_data; -#ifndef CONFIG_OF - priv->version = pdev->id_entry->driver_data; -#endif + priv->devtype_data = devtype_data; dev_set_drvdata(&pdev->dev, dev); @@ -1094,7 +1140,7 @@ out_map: out_get: if (clk) clk_put(clk); -out_clock: +out_error: return err; } @@ -1119,46 +1165,16 @@ static int flexcan_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_OF -static struct of_device_id flexcan_of_match[] = { - { - .compatible = "fsl,p1010-flexcan", - }, - {}, -}; -#else -static struct platform_device_id flexcan_devtype[] = { - { - .name = "imx25-flexcan", - .driver_data = FLEXCAN_VER_3_0_0, - }, { - .name = "imx28-flexcan", - .driver_data = FLEXCAN_VER_3_0_4, - }, { - .name = "imx35-flexcan", - .driver_data = FLEXCAN_VER_3_0_0, - }, { - .name = "imx53-flexcan", - .driver_data = FLEXCAN_VER_3_0_0, - }, { - .name = "imx6q-flexcan", - .driver_data = FLEXCAN_VER_10_0_12, - }, -}; -#endif - static struct platform_driver flexcan_driver = { -#ifdef CONFIG_OF .driver = { /* For legacy platform support */ - .name = "flexcan", + .name = DRV_NAME, .owner = THIS_MODULE, +#ifdef CONFIG_OF .of_match_table = flexcan_of_match, - }, -#else - .driver.name = DRV_NAME, - .id_table = flexcan_devtype, #endif + }, + .id_table = flexcan_id_table, .probe = flexcan_probe, .remove = flexcan_remove, }; _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai-git