diff options
Diffstat (limited to 'drivers/net/can/flexcan.c')
-rw-r--r-- | drivers/net/can/flexcan.c | 29 |
1 files changed, 19 insertions, 10 deletions
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index c5f143165f8..c78ecfca1e4 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c | |||
@@ -144,6 +144,10 @@ | |||
144 | 144 | ||
145 | #define FLEXCAN_MB_CODE_MASK (0xf0ffffff) | 145 | #define FLEXCAN_MB_CODE_MASK (0xf0ffffff) |
146 | 146 | ||
147 | /* FLEXCAN hardware feature flags */ | ||
148 | #define FLEXCAN_HAS_V10_FEATURES BIT(1) /* For core version >= 10 */ | ||
149 | #define FLEXCAN_HAS_BROKEN_ERR_STATE BIT(2) /* Broken error state handling */ | ||
150 | |||
147 | /* Structure of the message buffer */ | 151 | /* Structure of the message buffer */ |
148 | struct flexcan_mb { | 152 | struct flexcan_mb { |
149 | u32 can_ctrl; | 153 | u32 can_ctrl; |
@@ -178,7 +182,7 @@ struct flexcan_regs { | |||
178 | }; | 182 | }; |
179 | 183 | ||
180 | struct flexcan_devtype_data { | 184 | struct flexcan_devtype_data { |
181 | u32 hw_ver; /* hardware controller version */ | 185 | u32 features; /* hardware controller features */ |
182 | }; | 186 | }; |
183 | 187 | ||
184 | struct flexcan_priv { | 188 | struct flexcan_priv { |
@@ -197,11 +201,11 @@ struct flexcan_priv { | |||
197 | }; | 201 | }; |
198 | 202 | ||
199 | static struct flexcan_devtype_data fsl_p1010_devtype_data = { | 203 | static struct flexcan_devtype_data fsl_p1010_devtype_data = { |
200 | .hw_ver = 3, | 204 | .features = FLEXCAN_HAS_BROKEN_ERR_STATE, |
201 | }; | 205 | }; |
202 | 206 | static struct flexcan_devtype_data fsl_imx28_devtype_data; | |
203 | static struct flexcan_devtype_data fsl_imx6q_devtype_data = { | 207 | static struct flexcan_devtype_data fsl_imx6q_devtype_data = { |
204 | .hw_ver = 10, | 208 | .features = FLEXCAN_HAS_V10_FEATURES | FLEXCAN_HAS_BROKEN_ERR_STATE, |
205 | }; | 209 | }; |
206 | 210 | ||
207 | static const struct can_bittiming_const flexcan_bittiming_const = { | 211 | static const struct can_bittiming_const flexcan_bittiming_const = { |
@@ -741,15 +745,19 @@ static int flexcan_chip_start(struct net_device *dev) | |||
741 | * enable tx and rx warning interrupt | 745 | * enable tx and rx warning interrupt |
742 | * enable bus off interrupt | 746 | * enable bus off interrupt |
743 | * (== FLEXCAN_CTRL_ERR_STATE) | 747 | * (== FLEXCAN_CTRL_ERR_STATE) |
744 | * | ||
745 | * _note_: we enable the "error interrupt" | ||
746 | * (FLEXCAN_CTRL_ERR_MSK), too. Otherwise we don't get any | ||
747 | * warning or bus passive interrupts. | ||
748 | */ | 748 | */ |
749 | reg_ctrl = flexcan_read(®s->ctrl); | 749 | reg_ctrl = flexcan_read(®s->ctrl); |
750 | reg_ctrl &= ~FLEXCAN_CTRL_TSYN; | 750 | reg_ctrl &= ~FLEXCAN_CTRL_TSYN; |
751 | reg_ctrl |= FLEXCAN_CTRL_BOFF_REC | FLEXCAN_CTRL_LBUF | | 751 | reg_ctrl |= FLEXCAN_CTRL_BOFF_REC | FLEXCAN_CTRL_LBUF | |
752 | FLEXCAN_CTRL_ERR_STATE | FLEXCAN_CTRL_ERR_MSK; | 752 | FLEXCAN_CTRL_ERR_STATE; |
753 | /* | ||
754 | * enable the "error interrupt" (FLEXCAN_CTRL_ERR_MSK), | ||
755 | * on most Flexcan cores, too. Otherwise we don't get | ||
756 | * any error warning or passive interrupts. | ||
757 | */ | ||
758 | if (priv->devtype_data->features & FLEXCAN_HAS_BROKEN_ERR_STATE || | ||
759 | priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) | ||
760 | reg_ctrl |= FLEXCAN_CTRL_ERR_MSK; | ||
753 | 761 | ||
754 | /* save for later use */ | 762 | /* save for later use */ |
755 | priv->reg_ctrl_default = reg_ctrl; | 763 | priv->reg_ctrl_default = reg_ctrl; |
@@ -772,7 +780,7 @@ static int flexcan_chip_start(struct net_device *dev) | |||
772 | flexcan_write(0x0, ®s->rx14mask); | 780 | flexcan_write(0x0, ®s->rx14mask); |
773 | flexcan_write(0x0, ®s->rx15mask); | 781 | flexcan_write(0x0, ®s->rx15mask); |
774 | 782 | ||
775 | if (priv->devtype_data->hw_ver >= 10) | 783 | if (priv->devtype_data->features & FLEXCAN_HAS_V10_FEATURES) |
776 | flexcan_write(0x0, ®s->rxfgmask); | 784 | flexcan_write(0x0, ®s->rxfgmask); |
777 | 785 | ||
778 | flexcan_transceiver_switch(priv, 1); | 786 | flexcan_transceiver_switch(priv, 1); |
@@ -954,6 +962,7 @@ static void __devexit unregister_flexcandev(struct net_device *dev) | |||
954 | 962 | ||
955 | static const struct of_device_id flexcan_of_match[] = { | 963 | static const struct of_device_id flexcan_of_match[] = { |
956 | { .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, }, | 964 | { .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, }, |
965 | { .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, }, | ||
957 | { .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, }, | 966 | { .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, }, |
958 | { /* sentinel */ }, | 967 | { /* sentinel */ }, |
959 | }; | 968 | }; |